Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[show] vnet endpoint [ip/ipv6] command #2342

Merged
merged 11 commits into from
Oct 3, 2022
36 changes: 36 additions & 0 deletions doc/Command-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -9517,6 +9517,42 @@ This command displays brief information about all the vnets configured in the de
Vnet_3000 tunnel1 3000 Vnet_2000,Vnet4000
```

**show vnet endpoint <ip/ipv6>**

This command displays the list or vxlan tunnel endpoints and their status. In addition it also shows the number of prefixes associated with each endpoints in the tunnels. If an IP address of an endpoint is provided, this command also shows the associated prefixes a well.

- Usage:

```
show vnet endpoint <ipv4_address/ipv6_address>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also print the "endpoint_monitor" ip so we have a mapping? BFD session just have endpoint_monitor'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


```

- Example:

```
admin@sonic:~$ show vnet endpoint
Endpoint prefix count status
--------------------- -------------- --------
fddd:a100:a251::a10:1 1 Down
fddd:a101:a251::a10:1 1 Up
100.251.7.1 3 Up

or

admin@sonic:~$ show vnet endpoint fddd:a101:a251::a10:1
Endpoint prefix status
--------------------- ---------------------------- --------
fddd:a101:a251::a10:1 ['fddd:a150:a251::a6:1/128'] Up

or

admin@sonic:~$ show vnet endpoint 100.251.7.1
Endpoint prefix status
----------- --------------------------------------------------------- --------
100.251.7.1 ['160.62.191.1/32', '160.63.191.1/32', '160.64.191.1/32'] Up
```

**show vnet name <vnet_name>**

This command displays brief information about <vnet_name> configured in the device.
Expand Down
80 changes: 79 additions & 1 deletion show/vnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from natsort import natsorted
from swsscommon.swsscommon import SonicV2Connector, ConfigDBConnector
from tabulate import tabulate

import ipaddress

#
# 'vnet' command ("show vnet")
Expand Down Expand Up @@ -195,6 +195,84 @@ def neighbors():
if not bool(vnet_intfs):
click.echo(tabulate(table, header))

@vnet.command()
@click.argument('args', metavar='[IPADDRESS]', nargs=1, required=False)
def endpoint(args):
"""Show Vxlan tunnel endpoint status"""
"""Specify IPv4 or IPv6 address for detail"""

state_db = SonicV2Connector()
state_db.connect(state_db.STATE_DB)
appl_db = SonicV2Connector()
appl_db.connect(appl_db.APPL_DB)
filter_by_ip = ''
if args and len(args) > 0:
try:
filter_by_ip = ipaddress.ip_network(args)
except ValueError:
# Not ip address just ignore it
print ("wrong parameter",args)
return
# Fetching data from appl_db for VNET TUNNEL ROUTES
vnet_rt_keys = appl_db.keys(appl_db.APPL_DB, "VNET_ROUTE_TUNNEL_TABLE:*")
vnet_rt_keys = natsorted(vnet_rt_keys) if vnet_rt_keys else []
bfd_keys = state_db.keys(state_db.STATE_DB, "BFD_SESSION_TABLE|*")
if not filter_by_ip:
header = ['Endpoint', 'prefix count', 'status']
prefix_count ={}
monitor_dict = {}
table = []
for k in vnet_rt_keys:
val = appl_db.get_all(appl_db.APPL_DB, k)
endpoints = val.get('endpoint').split(',') if 'endpoint' in val else []
if 'endpoint_monitor' in val:
monitors = val.get('endpoint_monitor').split(',')
else:
continue
for idx, endpoint in enumerate(endpoints):
monitor_dict[endpoint] = monitors[idx]
if endpoint not in prefix_count:
prefix_count[endpoint] =0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space after = for consistency

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

prefix_count[endpoint] += 1
for endpoint in prefix_count:
r = []
r.append(endpoint)
r.append(prefix_count[endpoint])
bfd_session_key = "BFD_SESSION_TABLE|default|default|" + monitor_dict[endpoint]
if bfd_session_key in bfd_keys:
val_state = state_db.get_all(state_db.STATE_DB, bfd_session_key)
r.append(val_state.get('state'))
else:
r.append('Unknown')
table.append(r)
else:
table = []
header = ['Endpoint', 'prefix', 'status']
state = 'Unknown'
prefix =[]
have_status = False
for k in vnet_rt_keys:
val = appl_db.get_all(appl_db.APPL_DB, k)
endpoints = val.get('endpoint').split(',')
monitors = val.get('endpoint_monitor').split(',')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra space after =. Please fix spacing in all places

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

for idx, endpoint in enumerate(endpoints):
if args == endpoint:
prefix.append(k.split(":", 2)[2])
if not have_status:
bfd_session_key = "BFD_SESSION_TABLE|default|default|" + monitors[idx]
if bfd_session_key in bfd_keys:
val_state = state_db.get_all(state_db.STATE_DB, bfd_session_key)
state = val_state.get('state')
have_status = True
break
if prefix:
r = []
r.append(args)
r.append(prefix)
r.append(state)
table.append(r)
click.echo(tabulate(table, header))


@vnet.group()
def routes():
Expand Down
12 changes: 8 additions & 4 deletions tests/mock_tables/appl_db.json
Original file line number Diff line number Diff line change
Expand Up @@ -315,15 +315,19 @@
"alias": "Vlan1000"
},
"VNET_ROUTE_TUNNEL_TABLE:test_v4_in_v4-0:160.163.191.1/32": {
"endpoint":"100.251.7.1"
"endpoint":"100.251.7.1",
"endpoint_monitor":"100.251.7.1"
},
"VNET_ROUTE_TUNNEL_TABLE:Vnet_v6_in_v6-0:fddd:a156:a251::a6:1/128": {
"endpoint": "fddd:a100:a251::a10:1,fddd:a101:a251::a10:1"
"endpoint": "fddd:a100:a251::a10:1,fddd:a101:a251::a10:1",
"endpoint_monitor":"fddd:a100:a251::a10:1,fddd:a101:a251::a10:1"
},
"VNET_ROUTE_TUNNEL_TABLE:test_v4_in_v4-0:160.162.191.1/32": {
"endpoint":"100.251.7.1"
"endpoint":"100.251.7.1",
"endpoint_monitor":"100.251.7.1"
},
"VNET_ROUTE_TUNNEL_TABLE:test_v4_in_v4-0:160.164.191.1/32": {
"endpoint":"100.251.7.1"
"endpoint":"100.251.7.1",
"endpoint_monitor":"100.251.7.1"
}
}
18 changes: 18 additions & 0 deletions tests/mock_tables/state_db.json
Original file line number Diff line number Diff line change
Expand Up @@ -890,5 +890,23 @@
"VNET_ROUTE_TUNNEL_TABLE|Vnet_v6_in_v6-0|fddd:a156:a251::a6:1/128": {
"active_endpoints":"fddd:a100:a251::a10:1,fddd:a101:a251::a10:1",
"state":"active"
},
"BFD_SESSION_TABLE|default|default|100.251.7.1": {
"state":"Up",
"type": "async_active",
"local_addr" : "10.0.0.1",
"tx_interval" :"300",
"rx_interval" : "500",
"multiplier" : "3",
"multihop": "true"
},
"BFD_SESSION_TABLE|default|default|fddd:a101:a251::a10:1": {
"state":"Down",
"type": "async_active",
"local_addr" : "fddd:c101:a251::a10:2",
"tx_interval" :"300",
"rx_interval" : "500",
"multiplier" : "3",
"multihop": "true"
}
}
24 changes: 14 additions & 10 deletions tests/show_bfd_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ def test_bfd_show(self):
"tx_interval" :"400", "rx_interval" : "500", "multiplier" : "5", "multihop": "false"})

expected_output = """\
Total number of BFD sessions: 4
Peer Addr Interface Vrf State Type Local Addr TX Interval RX Interval Multiplier Multihop
----------- ----------- ------- ------- ------------ ------------ ------------- ------------- ------------ ----------
10.0.1.1 default default DOWN async_active 10.0.0.1 300 500 3 true
10.0.2.1 Ethernet12 default UP async_active 10.0.0.1 200 600 3 false
2000::10:1 default default UP async_active 2000::1 100 700 3 false
10.0.1.1 default VrfRed UP async_active 10.0.0.1 400 500 5 false
Total number of BFD sessions: 6
Peer Addr Interface Vrf State Type Local Addr TX Interval RX Interval Multiplier Multihop
--------------------- ----------- ------- ------- ------------ --------------------- ------------- ------------- ------------ ----------
100.251.7.1 default default Up async_active 10.0.0.1 300 500 3 true
fddd:a101:a251::a10:1 default default Down async_active fddd:c101:a251::a10:2 300 500 3 true
10.0.1.1 default default DOWN async_active 10.0.0.1 300 500 3 true
10.0.2.1 Ethernet12 default UP async_active 10.0.0.1 200 600 3 false
2000::10:1 default default UP async_active 2000::1 100 700 3 false
10.0.1.1 default VrfRed UP async_active 10.0.0.1 400 500 5 false
"""

result = runner.invoke(show.cli.commands['bfd'].commands['summary'], [], obj=db)
Expand Down Expand Up @@ -88,9 +90,11 @@ def test_bfd_show_no_session(self):
db = Db()

expected_output = """\
Total number of BFD sessions: 0
Peer Addr Interface Vrf State Type Local Addr TX Interval RX Interval Multiplier Multihop
----------- ----------- ----- ------- ------ ------------ ------------- ------------- ------------ ----------
Total number of BFD sessions: 2
Peer Addr Interface Vrf State Type Local Addr TX Interval RX Interval Multiplier Multihop
--------------------- ----------- ------- ------- ------------ --------------------- ------------- ------------- ------------ ----------
100.251.7.1 default default Up async_active 10.0.0.1 300 500 3 true
fddd:a101:a251::a10:1 default default Down async_active fddd:c101:a251::a10:2 300 500 3 true
"""

result = runner.invoke(show.cli.commands['bfd'].commands['summary'], [], obj=db)
Expand Down
74 changes: 74 additions & 0 deletions tests/show_vnet_vxlan_cli_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import os
import sys
import traceback
import mock_tables.dbconnector
from click.testing import CliRunner
from unittest import mock
from utilities_common.db import Db
import show.main as show

#test_path = os.path.dirname(os.path.abspath(__file__))



class TestShowVnet(object):
@classmethod
def setup_class(cls):
print("SETUP")
os.environ["UTILITIES_UNIT_TESTING"] = "1"

def test_show_vnet_routes_all_basic(self):
runner = CliRunner()
db = Db()
result = runner.invoke(show.cli.commands['vnet'].commands['routes'].commands['all'], [], obj=db)
assert result.exit_code == 0
expected_output = """\
vnet name prefix nexthop interface
----------- -------- --------- -----------

vnet name prefix endpoint mac address vni status
--------------- ------------------------ ------------------------------------------- ------------- ----- --------
Vnet_v6_in_v6-0 fddd:a156:a251::a6:1/128 fddd:a100:a251::a10:1,fddd:a101:a251::a10:1 active
test_v4_in_v4-0 160.162.191.1/32 100.251.7.1 active
test_v4_in_v4-0 160.163.191.1/32 100.251.7.1 active
test_v4_in_v4-0 160.164.191.1/32 100.251.7.1
"""
assert result.output == expected_output

def test_show_vnet_endpoint(self):
runner = CliRunner()
db = Db()
result = runner.invoke(show.cli.commands['vnet'].commands['endpoint'], [], obj=db)
assert result.exit_code == 0
expected_output = """\
Endpoint prefix count status
--------------------- -------------- --------
fddd:a100:a251::a10:1 1 Unknown
fddd:a101:a251::a10:1 1 Down
100.251.7.1 3 Up
"""
assert result.output == expected_output

def test_show_vnet_endpoint_ipv4(self):
runner = CliRunner()
db = Db()
result = runner.invoke(show.cli.commands['vnet'].commands['endpoint'], ['100.251.7.1'], obj=db)
assert result.exit_code == 0
expected_output = """\
Endpoint prefix status
----------- ------------------------------------------------------------ --------
100.251.7.1 ['160.162.191.1/32', '160.163.191.1/32', '160.164.191.1/32'] Up
"""
assert result.output == expected_output

def test_show_vnet_endpoint_ipv6(self):
runner = CliRunner()
db = Db()
result = runner.invoke(show.cli.commands['vnet'].commands['endpoint'], ['fddd:a101:a251::a10:1'], obj=db)
assert result.exit_code == 0
expected_output = """\
Endpoint prefix status
--------------------- ---------------------------- --------
fddd:a101:a251::a10:1 ['fddd:a156:a251::a6:1/128'] Down
"""
assert result.output == expected_output