Skip to content

Commit aeba823

Browse files
authored
feat: support namespace arg for show bfd (#3885)
What I did Added the namespace support for show bfd summary & show bfd peer <peer_id> command. For example, users can run show bfd summary -n asic0, show bfd peer 10.0.1.1 -n asic0 and etc. How I did it How to verify it Run show bfd summary -n <namespace> and show bfd peer <peer_id> -n <namespace> and verify the output Previous command output (if the output of a command-line utility has changed) Nothing has changed to the output of these 2 commands, we are only adding the namespace argument support in this PR. Users can still use the sudo ip netns exec asicX ... way after this PR. I confirmed the output of sudo ip netns exec asicX show bfd summary and show bfd summary -n asicX are the same, and sudo ip netns exec asicX show bfd peer <peer_id> and show bfd peer <peer_id> -n asicX are the same New command output (if the output of a command-line utility has changed) Nothing has changed to the output of these 2 commands, we are only adding the namespace argument support in this PR. Users can still use the sudo ip netns exec asicX ... way after this PR. I confirmed the output of sudo ip netns exec asicX show bfd summary and show bfd summary -n asicX are the same, and sudo ip netns exec asicX show bfd peer <peer_id> and show bfd peer <peer_id> -n asicX are the same co-authorized by: jianquanye@microsoft.com
1 parent 6ce5257 commit aeba823

6 files changed

Lines changed: 149 additions & 9 deletions

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ dist/
1515
coverage.xml
1616
htmlcov/
1717

18+
# Dev tools
19+
.vscode/
20+
.idea/
21+
1822
# Ignores for sonic-utilities-data
1923
sonic-utilities-data/debian/*
2024
!sonic-utilities-data/debian/changelog

doc/Command-Reference.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2337,7 +2337,7 @@ This command displays the state and key parameters of all BFD sessions.
23372337

23382338
- Usage:
23392339
```
2340-
show bfd summary
2340+
show bfd summary [-n <namespace>]
23412341
```
23422342
- Example:
23432343
```
@@ -2356,7 +2356,7 @@ This command displays the state and key parameters of all BFD sessions that matc
23562356

23572357
- Usage:
23582358
```
2359-
show bfd peer <peer-ip>
2359+
show bfd peer <peer-ip> [-n <namespace>]
23602360
```
23612361
- Example:
23622362
```

show/main.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2567,20 +2567,25 @@ def bfd():
25672567
# 'summary' subcommand ("show bfd summary")
25682568
@bfd.command()
25692569
@clicommon.pass_db
2570-
def summary(db):
2570+
@click.option('--namespace', '-n', 'namespace', default=None, type=str, show_default=True,
2571+
help='Namespace name or all', callback=multi_asic_util.multi_asic_namespace_validation_callback)
2572+
def summary(db, namespace):
25712573
"""Show bfd session information"""
25722574
bfd_headers = ["Peer Addr", "Interface", "Vrf", "State", "Type", "Local Addr",
25732575
"TX Interval", "RX Interval", "Multiplier", "Multihop", "Local Discriminator"]
25742576

2575-
bfd_keys = db.db.keys(db.db.STATE_DB, "BFD_SESSION_TABLE|*")
2577+
if namespace is None:
2578+
namespace = constants.DEFAULT_NAMESPACE
2579+
2580+
bfd_keys = db.db_clients[namespace].keys(db.db.STATE_DB, "BFD_SESSION_TABLE|*")
25762581

25772582
click.echo("Total number of BFD sessions: {}".format(0 if bfd_keys is None else len(bfd_keys)))
25782583

25792584
bfd_body = []
25802585
if bfd_keys is not None:
25812586
for key in bfd_keys:
25822587
key_values = key.split('|')
2583-
values = db.db.get_all(db.db.STATE_DB, key)
2588+
values = db.db_clients[namespace].get_all(db.db.STATE_DB, key)
25842589
if "local_discriminator" not in values.keys():
25852590
values["local_discriminator"] = "NA"
25862591
bfd_body.append([key_values[3], key_values[2], key_values[1], values["state"], values["type"], values["local_addr"],
@@ -2593,13 +2598,18 @@ def summary(db):
25932598
@bfd.command()
25942599
@clicommon.pass_db
25952600
@click.argument('peer_ip', required=True)
2596-
def peer(db, peer_ip):
2601+
@click.option('--namespace', '-n', 'namespace', default=None, type=str, show_default=True,
2602+
help='Namespace name or all', callback=multi_asic_util.multi_asic_namespace_validation_callback)
2603+
def peer(db, peer_ip, namespace):
25972604
"""Show bfd session information for BFD peer"""
25982605
bfd_headers = ["Peer Addr", "Interface", "Vrf", "State", "Type", "Local Addr",
25992606
"TX Interval", "RX Interval", "Multiplier", "Multihop", "Local Discriminator"]
26002607

2601-
bfd_keys = db.db.keys(db.db.STATE_DB, "BFD_SESSION_TABLE|*|{}".format(peer_ip))
2602-
delimiter = db.db.get_db_separator(db.db.STATE_DB)
2608+
if namespace is None:
2609+
namespace = constants.DEFAULT_NAMESPACE
2610+
2611+
bfd_keys = db.db_clients[namespace].keys(db.db.STATE_DB, "BFD_SESSION_TABLE|*|{}".format(peer_ip))
2612+
delimiter = db.db_clients[namespace].get_db_separator(db.db.STATE_DB)
26032613

26042614
if bfd_keys is None or len(bfd_keys) == 0:
26052615
click.echo("No BFD sessions found for peer IP {}".format(peer_ip))
@@ -2611,7 +2621,7 @@ def peer(db, peer_ip):
26112621
if bfd_keys is not None:
26122622
for key in bfd_keys:
26132623
key_values = key.split(delimiter)
2614-
values = db.db.get_all(db.db.STATE_DB, key)
2624+
values = db.db_clients[namespace].get_all(db.db.STATE_DB, key)
26152625
if "local_discriminator" not in values.keys():
26162626
values["local_discriminator"] = "NA"
26172627
bfd_body.append([key_values[3], key_values[2], key_values[1], values.get("state"), values.get("type"), values.get("local_addr"),
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
expected_show_bfd_summary_output = """\
2+
Total number of BFD sessions: 4
3+
Peer Addr Interface Vrf State Type Local Addr TX Interval RX Interval Multiplier Multihop Local Discriminator
4+
----------- ----------- ------- ------- ------------ ------------ ------------- ------------- ------------ ---------- ---------------------
5+
10.0.1.1 default default DOWN async_active 10.0.0.1 300 500 3 true NA
6+
10.0.2.1 Ethernet12 default UP async_active 10.0.0.1 200 600 3 false 88
7+
2000::10:1 default default UP async_active 2000::1 100 700 3 false NA
8+
10.0.1.1 default VrfRed UP async_active 10.0.0.1 400 500 5 false NA
9+
""" # noqa: E501
10+
11+
expected_show_bfd_peer_output = """\
12+
Total number of BFD sessions for peer IP 10.0.1.1: 2
13+
Peer Addr Interface Vrf State Type Local Addr TX Interval RX Interval Multiplier Multihop Local Discriminator
14+
----------- ----------- ------- ------- ------------ ------------ ------------- ------------- ------------ ---------- ---------------------
15+
10.0.1.1 default default DOWN async_active 10.0.0.1 300 500 3 true NA
16+
10.0.1.1 default VrfRed UP async_active 10.0.0.1 400 500 5 false NA
17+
""" # noqa: E501
18+
19+
test_data = {
20+
"show_bfd_summary_masic_asic0": {
21+
"cmd": "summary",
22+
"args": ["-n", "asic0"],
23+
"expected_output": expected_show_bfd_summary_output,
24+
},
25+
"show_bfd_peer_masic_asic0": {
26+
"cmd": "peer",
27+
"args": ["10.0.1.1", "-n", "asic0"],
28+
"expected_output": expected_show_bfd_peer_output,
29+
},
30+
}

tests/mock_tables/asic0/state_db.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,5 +339,42 @@
339339
},
340340
"PORT_CAPACITY_TABLE|PORT_CAPACITY_DATA" : {
341341
"capacity": "80000"
342+
},
343+
"BFD_SESSION_TABLE|default|default|10.0.1.1": {
344+
"state": "DOWN",
345+
"type": "async_active",
346+
"local_addr" : "10.0.0.1",
347+
"tx_interval" :"300",
348+
"rx_interval" : "500",
349+
"multiplier" : "3",
350+
"multihop": "true"
351+
},
352+
"BFD_SESSION_TABLE|default|Ethernet12|10.0.2.1": {
353+
"state": "UP",
354+
"type": "async_active",
355+
"local_addr" : "10.0.0.1",
356+
"tx_interval" :"200",
357+
"rx_interval" : "600",
358+
"multiplier" : "3",
359+
"multihop": "false",
360+
"local_discriminator": "88"
361+
},
362+
"BFD_SESSION_TABLE|default|default|2000::10:1": {
363+
"state": "UP",
364+
"type": "async_active",
365+
"local_addr" : "2000::1",
366+
"tx_interval" :"100",
367+
"rx_interval" : "700",
368+
"multiplier" : "3",
369+
"multihop": "false"
370+
},
371+
"BFD_SESSION_TABLE|VrfRed|default|10.0.1.1": {
372+
"state": "UP",
373+
"type": "async_active",
374+
"local_addr" : "10.0.0.1",
375+
"tx_interval" :"400",
376+
"rx_interval" : "500",
377+
"multiplier" : "5",
378+
"multihop": "false"
342379
}
343380
}

tests/multi_asic_show_bfd_test.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import os
2+
import sys
3+
from importlib import reload
4+
5+
from click.testing import CliRunner
6+
7+
import show.main as show
8+
from tests.bfd_input.bfd_masic_test_vectors import test_data
9+
10+
test_path = os.path.dirname(os.path.abspath(__file__))
11+
modules_path = os.path.dirname(test_path)
12+
scripts_path = os.path.join(modules_path, "scripts")
13+
sys.path.insert(0, test_path)
14+
sys.path.insert(0, modules_path)
15+
16+
17+
class TestShowBfdMultiAsic(object):
18+
@classmethod
19+
def setup_class(cls):
20+
print("SETUP")
21+
22+
os.environ["PATH"] += os.pathsep + scripts_path
23+
os.environ['UTILITIES_UNIT_TESTING'] = "2"
24+
os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = "multi_asic"
25+
26+
# Set the database to mock multi-asic state
27+
from mock_tables import mock_multi_asic
28+
reload(mock_multi_asic)
29+
from mock_tables import dbconnector
30+
dbconnector.load_namespace_config()
31+
32+
def test_show_bfd_summary_masic_asic0(self):
33+
self.command_executor(test_data["show_bfd_summary_masic_asic0"])
34+
35+
def test_show_bfd_peer_masic_asic0(self):
36+
self.command_executor(test_data["show_bfd_peer_masic_asic0"])
37+
38+
@classmethod
39+
def teardown_class(cls):
40+
# Reset the database to mock single-asic state
41+
from mock_tables import mock_single_asic
42+
reload(mock_single_asic)
43+
from mock_tables import dbconnector
44+
dbconnector.load_database_config()
45+
46+
os.environ["PATH"] = os.pathsep.join(os.environ["PATH"].split(os.pathsep)[:-1])
47+
os.environ['UTILITIES_UNIT_TESTING'] = "0"
48+
os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = ""
49+
50+
print("TEARDOWN")
51+
52+
@staticmethod
53+
def command_executor(test_case_data):
54+
runner = CliRunner()
55+
result = runner.invoke(show.cli.commands["bfd"].commands[test_case_data["cmd"]], args=test_case_data["args"])
56+
print("result.exit_code: {}".format(result.exit_code))
57+
print("result.output: {}".format(result.output))
58+
assert result.exit_code == 0
59+
assert result.output == test_case_data["expected_output"]

0 commit comments

Comments
 (0)