Skip to content

Commit 0bbe54a

Browse files
authored
[show] vnet endpoint [ip/ipv6] command (#2342) (#2421) (#2474)
What I did Created a new CLI Command Show vnet endpoint with option to give IPv4 or IPv6 address parameter. How I did it This command goes over all vxlan tunnels and checks each endpoints monitor session to populate the endpoint state. while doing so it also tracks the prefixes pointing to an endpoint. How to verify it run show vnet endpoint or show vnet endpoint<ipv4 address/ipv6 address>. >>show vnet endpoint Endpoint Endpoint Monitor prefix count status --------------------- --------------------- -------------- -------- fddd:a100:a251::a10:1 fddd:a100:a251::a10:1 1 Unknown fddd:a101:a251::a10:1 fddd:a101:a251::a10:1 1 Down 100.251.7.1 100.251.7.1 3 Up >>show vnet endpoint fddd:a101:a251::a10:1 Endpoint Endpoint Monitor prefix status --------------------- ------------------------- ---------------------------- -------- fddd:a101:a251::a10:1 ['fddd:a101:a251::a10:1'] ['fddd:a156:a251::a6:1/128'] Down >>show vnet endpoint 100.251.7.1 Endpoint Endpoint Monitor prefix status ----------- ------------------ ------------------------------------------------------------ -------- 100.251.7.1 ['100.251.7.1'] ['160.162.191.1/32', '160.163.191.1/32', '160.164.191.1/32'] Up Previous command output (if the output of a command-line utility has changed) None New command output (if the output of a command-line utility has changed) NA
1 parent b1b3661 commit 0bbe54a

File tree

6 files changed

+233
-15
lines changed

6 files changed

+233
-15
lines changed

doc/Command-Reference.md

+36
Original file line numberDiff line numberDiff line change
@@ -9417,6 +9417,42 @@ This command displays brief information about all the vnets configured in the de
94179417
Vnet_3000 tunnel1 3000 Vnet_2000,Vnet4000
94189418
```
94199419
9420+
**show vnet endpoint <ip/ipv6>**
9421+
9422+
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.
9423+
9424+
- Usage:
9425+
9426+
```
9427+
show vnet endpoint <ipv4_address/ipv6_address>
9428+
9429+
```
9430+
9431+
- Example:
9432+
9433+
```
9434+
admin@sonic:~$ show vnet endpoint
9435+
Endpoint prefix count status
9436+
--------------------- -------------- --------
9437+
fddd:a100:a251::a10:1 1 Down
9438+
fddd:a101:a251::a10:1 1 Up
9439+
100.251.7.1 3 Up
9440+
9441+
or
9442+
9443+
admin@sonic:~$ show vnet endpoint fddd:a101:a251::a10:1
9444+
Endpoint prefix status
9445+
--------------------- ---------------------------- --------
9446+
fddd:a101:a251::a10:1 ['fddd:a150:a251::a6:1/128'] Up
9447+
9448+
or
9449+
9450+
admin@sonic:~$ show vnet endpoint 100.251.7.1
9451+
Endpoint prefix status
9452+
----------- --------------------------------------------------------- --------
9453+
100.251.7.1 ['160.62.191.1/32', '160.63.191.1/32', '160.64.191.1/32'] Up
9454+
```
9455+
94209456
**show vnet name <vnet_name>**
94219457
94229458
This command displays brief information about <vnet_name> configured in the device.

show/vnet.py

+83-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from natsort import natsorted
44
from swsscommon.swsscommon import SonicV2Connector, ConfigDBConnector
55
from tabulate import tabulate
6-
6+
import ipaddress
77

88
#
99
# 'vnet' command ("show vnet")
@@ -195,6 +195,88 @@ def neighbors():
195195
if not bool(vnet_intfs):
196196
click.echo(tabulate(table, header))
197197

198+
@vnet.command()
199+
@click.argument('args', metavar='[IPADDRESS]', nargs=1, required=False)
200+
def endpoint(args):
201+
"""Show Vxlan tunnel endpoint status"""
202+
"""Specify IPv4 or IPv6 address for detail"""
203+
204+
state_db = SonicV2Connector()
205+
state_db.connect(state_db.STATE_DB)
206+
appl_db = SonicV2Connector()
207+
appl_db.connect(appl_db.APPL_DB)
208+
filter_by_ip = ''
209+
if args and len(args) > 0:
210+
try:
211+
filter_by_ip = ipaddress.ip_network(args)
212+
except ValueError:
213+
# Not ip address just ignore it
214+
print ("wrong parameter",args)
215+
return
216+
# Fetching data from appl_db for VNET TUNNEL ROUTES
217+
vnet_rt_keys = appl_db.keys(appl_db.APPL_DB, "VNET_ROUTE_TUNNEL_TABLE:*")
218+
vnet_rt_keys = natsorted(vnet_rt_keys) if vnet_rt_keys else []
219+
bfd_keys = state_db.keys(state_db.STATE_DB, "BFD_SESSION_TABLE|*")
220+
if not filter_by_ip:
221+
header = ['Endpoint', 'Endpoint Monitor', 'prefix count', 'status']
222+
prefix_count = {}
223+
monitor_dict = {}
224+
table = []
225+
for k in vnet_rt_keys:
226+
val = appl_db.get_all(appl_db.APPL_DB, k)
227+
endpoints = val.get('endpoint').split(',') if 'endpoint' in val else []
228+
if 'endpoint_monitor' in val:
229+
monitors = val.get('endpoint_monitor').split(',')
230+
else:
231+
continue
232+
for idx, endpoint in enumerate(endpoints):
233+
monitor_dict[endpoint] = monitors[idx]
234+
if endpoint not in prefix_count:
235+
prefix_count[endpoint] = 0
236+
prefix_count[endpoint] += 1
237+
for endpoint in prefix_count:
238+
r = []
239+
r.append(endpoint)
240+
r.append(monitor_dict[endpoint])
241+
r.append(prefix_count[endpoint])
242+
bfd_session_key = "BFD_SESSION_TABLE|default|default|" + monitor_dict[endpoint]
243+
if bfd_session_key in bfd_keys:
244+
val_state = state_db.get_all(state_db.STATE_DB, bfd_session_key)
245+
r.append(val_state.get('state'))
246+
else:
247+
r.append('Unknown')
248+
table.append(r)
249+
else:
250+
table = []
251+
header = ['Endpoint', 'Endpoint Monitor', 'prefix', 'status']
252+
state = 'Unknown'
253+
prefix = []
254+
monitor_list = []
255+
have_status = False
256+
for k in vnet_rt_keys:
257+
val = appl_db.get_all(appl_db.APPL_DB, k)
258+
endpoints = val.get('endpoint').split(',')
259+
monitors = val.get('endpoint_monitor').split(',')
260+
for idx, endpoint in enumerate(endpoints):
261+
if args == endpoint:
262+
prefix.append(k.split(":", 2)[2])
263+
if not have_status:
264+
bfd_session_key = "BFD_SESSION_TABLE|default|default|" + monitors[idx]
265+
if bfd_session_key in bfd_keys:
266+
val_state = state_db.get_all(state_db.STATE_DB, bfd_session_key)
267+
state = val_state.get('state')
268+
have_status = True
269+
monitor_list.append( monitors[idx])
270+
break
271+
if prefix:
272+
r = []
273+
r.append(args)
274+
r.append(monitor_list)
275+
r.append(prefix)
276+
r.append(state)
277+
table.append(r)
278+
click.echo(tabulate(table, header))
279+
198280

199281
@vnet.group()
200282
def routes():

tests/mock_tables/appl_db.json

+8-4
Original file line numberDiff line numberDiff line change
@@ -315,15 +315,19 @@
315315
"alias": "Vlan1000"
316316
},
317317
"VNET_ROUTE_TUNNEL_TABLE:test_v4_in_v4-0:160.163.191.1/32": {
318-
"endpoint":"100.251.7.1"
318+
"endpoint":"100.251.7.1",
319+
"endpoint_monitor":"100.251.7.1"
319320
},
320321
"VNET_ROUTE_TUNNEL_TABLE:Vnet_v6_in_v6-0:fddd:a156:a251::a6:1/128": {
321-
"endpoint": "fddd:a100:a251::a10:1,fddd:a101:a251::a10:1"
322+
"endpoint": "fddd:a100:a251::a10:1,fddd:a101:a251::a10:1",
323+
"endpoint_monitor":"fddd:a100:a251::a10:1,fddd:a101:a251::a10:1"
322324
},
323325
"VNET_ROUTE_TUNNEL_TABLE:test_v4_in_v4-0:160.162.191.1/32": {
324-
"endpoint":"100.251.7.1"
326+
"endpoint":"100.251.7.1",
327+
"endpoint_monitor":"100.251.7.1"
325328
},
326329
"VNET_ROUTE_TUNNEL_TABLE:test_v4_in_v4-0:160.164.191.1/32": {
327-
"endpoint":"100.251.7.1"
330+
"endpoint":"100.251.7.1",
331+
"endpoint_monitor":"100.251.7.1"
328332
}
329333
}

tests/mock_tables/state_db.json

+18
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,24 @@
876876
"LINK_TRAINING|Ethernet112": {
877877
"status": "off"
878878
},
879+
"BFD_SESSION_TABLE|default|default|100.251.7.1": {
880+
"state":"Up",
881+
"type": "async_active",
882+
"local_addr" : "10.0.0.1",
883+
"tx_interval" :"300",
884+
"rx_interval" : "500",
885+
"multiplier" : "3",
886+
"multihop": "true"
887+
},
888+
"BFD_SESSION_TABLE|default|default|fddd:a101:a251::a10:1": {
889+
"state":"Down",
890+
"type": "async_active",
891+
"local_addr" : "fddd:c101:a251::a10:2",
892+
"tx_interval" :"300",
893+
"rx_interval" : "500",
894+
"multiplier" : "3",
895+
"multihop": "true"
896+
},
879897
"VNET_ROUTE_TUNNEL_TABLE|test_v4_in_v4-0|160.162.191.1/32": {
880898
"active_endpoints":"100.251.7.1",
881899
"state":"active"

tests/show_bfd_test.py

+14-10
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,15 @@ def test_bfd_show(self):
3838
"tx_interval" :"400", "rx_interval" : "500", "multiplier" : "5", "multihop": "false"})
3939

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

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

9092
expected_output = """\
91-
Total number of BFD sessions: 0
92-
Peer Addr Interface Vrf State Type Local Addr TX Interval RX Interval Multiplier Multihop
93-
----------- ----------- ----- ------- ------ ------------ ------------- ------------- ------------ ----------
93+
Total number of BFD sessions: 2
94+
Peer Addr Interface Vrf State Type Local Addr TX Interval RX Interval Multiplier Multihop
95+
--------------------- ----------- ------- ------- ------------ --------------------- ------------- ------------- ------------ ----------
96+
100.251.7.1 default default Up async_active 10.0.0.1 300 500 3 true
97+
fddd:a101:a251::a10:1 default default Down async_active fddd:c101:a251::a10:2 300 500 3 true
9498
"""
9599

96100
result = runner.invoke(show.cli.commands['bfd'].commands['summary'], [], obj=db)

tests/show_vnet_vxlan_cli_test.py

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import os
2+
import sys
3+
import traceback
4+
import mock_tables.dbconnector
5+
from click.testing import CliRunner
6+
from unittest import mock
7+
from utilities_common.db import Db
8+
import show.main as show
9+
10+
#test_path = os.path.dirname(os.path.abspath(__file__))
11+
12+
13+
14+
class TestShowVnet(object):
15+
@classmethod
16+
def setup_class(cls):
17+
print("SETUP")
18+
os.environ["UTILITIES_UNIT_TESTING"] = "1"
19+
20+
def test_show_vnet_routes_all_basic(self):
21+
runner = CliRunner()
22+
db = Db()
23+
result = runner.invoke(show.cli.commands['vnet'].commands['routes'].commands['all'], [], obj=db)
24+
assert result.exit_code == 0
25+
expected_output = """\
26+
vnet name prefix nexthop interface
27+
----------- -------- --------- -----------
28+
29+
vnet name prefix endpoint mac address vni status
30+
--------------- ------------------------ ------------------------------------------- ------------- ----- --------
31+
Vnet_v6_in_v6-0 fddd:a156:a251::a6:1/128 fddd:a100:a251::a10:1,fddd:a101:a251::a10:1 active
32+
test_v4_in_v4-0 160.162.191.1/32 100.251.7.1 active
33+
test_v4_in_v4-0 160.163.191.1/32 100.251.7.1 active
34+
test_v4_in_v4-0 160.164.191.1/32 100.251.7.1
35+
"""
36+
assert result.output == expected_output
37+
38+
def test_show_vnet_endpoint(self):
39+
runner = CliRunner()
40+
db = Db()
41+
result = runner.invoke(show.cli.commands['vnet'].commands['endpoint'], [], obj=db)
42+
assert result.exit_code == 0
43+
expected_output = """\
44+
Endpoint Endpoint Monitor prefix count status
45+
--------------------- --------------------- -------------- --------
46+
fddd:a100:a251::a10:1 fddd:a100:a251::a10:1 1 Unknown
47+
fddd:a101:a251::a10:1 fddd:a101:a251::a10:1 1 Down
48+
100.251.7.1 100.251.7.1 3 Up
49+
"""
50+
assert result.output == expected_output
51+
52+
def test_show_vnet_endpoint_ipv4(self):
53+
runner = CliRunner()
54+
db = Db()
55+
result = runner.invoke(show.cli.commands['vnet'].commands['endpoint'], ['100.251.7.1'], obj=db)
56+
assert result.exit_code == 0
57+
expected_output = """\
58+
Endpoint Endpoint Monitor prefix status
59+
----------- ------------------ ------------------------------------------------------------ --------
60+
100.251.7.1 ['100.251.7.1'] ['160.162.191.1/32', '160.163.191.1/32', '160.164.191.1/32'] Up
61+
"""
62+
assert result.output == expected_output
63+
64+
def test_show_vnet_endpoint_ipv6(self):
65+
runner = CliRunner()
66+
db = Db()
67+
result = runner.invoke(show.cli.commands['vnet'].commands['endpoint'], ['fddd:a101:a251::a10:1'], obj=db)
68+
assert result.exit_code == 0
69+
expected_output = """\
70+
Endpoint Endpoint Monitor prefix status
71+
--------------------- ------------------------- ---------------------------- --------
72+
fddd:a101:a251::a10:1 ['fddd:a101:a251::a10:1'] ['fddd:a156:a251::a6:1/128'] Down
73+
"""
74+
assert result.output == expected_output

0 commit comments

Comments
 (0)