Skip to content

Commit 4681697

Browse files
Support command show ip fib and show ipv6 fib (sonic-net#2100)
Signed-off-by: Yutong Zhang <[email protected]> #### What I did Support command `show ip fib` and `show ipv6 fib`to get dataplane/FIB routes from APPL_DB ROUTE_TABLE. #### How I did it Add a script `fibshow` under the folder scripts/ and modify the script `main.py` under the show folder. #### How to verify it By using command `show ip fib`, `show ipv6 fib`, `fibshow -4`, `fibshow -6` on dut. And it also support given a specific ip prefix like `show ipv6 fib 20c0:dfe8::/64` #### New command output (if the output of a command-line utility has changed) ``` admin@vlab-01:~$ show ipv6 fib No. Vrf Route Nexthop Ifname ----- ----- ------------------- ----------------------------------- ----------------------------------------------------------- 1 20c0:fe28:0:80::/64 fc00::72,fc00::76,fc00::7a,fc00::7e PortChannel101,PortChannel102,PortChannel103,PortChannel104 2 20c0:fe28::/64 fc00::72,fc00::76,fc00::7a,fc00::7e PortChannel101,PortChannel102,PortChannel103,PortChannel104 3 20c0:fe30:0:80::/64 PortChannel101,PortChannel102,PortChannel103,PortChannel104 Total number of entries 3 ...... Total number of entries 6410 admin@vlab-01:~$ fibshow -4 No. Vrf Route Nexthop Ifname ----- ----- ------------------ --------------------------------------- ----------------------------------------------------------- 1 192.168.104.0/25 10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63 PortChannel101,PortChannel102,PortChannel103,PortChannel104 2 192.168.104.128/25 PortChannel101,PortChannel102,PortChannel103,PortChannel104 3 192.168.112.0/25 10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63 4 192.168.120.0/25 10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63 PortChannel101,PortChannel102,PortChannel103,PortChannel104 5 Red 192.168.112.128/25 10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63 PortChannel101,PortChannel102,PortChannel103,PortChannel104 Total number of entries 5 ``` ``` admin@vlab-01:~$ show ipv6 fib 20c0:fe28:0:80::/64 No. Vrf Route Nexthop Ifname ----- ----- ------------------- ----------------------------------- ----------------------------------------------------------- 1 20c0:fe28:0:80::/64 fc00::72,fc00::76,fc00::7a,fc00::7e PortChannel101,PortChannel102,PortChannel103,PortChannel104 Total number of entries 3 ```
1 parent 2a982a1 commit 4681697

File tree

9 files changed

+328
-25
lines changed

9 files changed

+328
-25
lines changed

scripts/fanshow

+1-3
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,15 @@ class FanShow(object):
6565

6666
presence = data_dict[PRESENCE_FIELD_NAME].lower()
6767
presence = 'Present' if presence == 'true' else 'Not Present'
68-
6968
status = data_dict[STATUS_FIELD_NAME]
7069
status_lower = status.lower()
7170
if status_lower == 'true':
7271
status = 'OK'
7372
elif status_lower == 'false':
7473
status = 'Not OK'
7574

76-
table.append((data_dict[DRAWER_FIELD_NAME], data_dict[LED_STATUS_FIELD_NAME], name, speed, data_dict[DIRECTION_FIELD_NAME], presence, status,
75+
table.append((data_dict[DRAWER_FIELD_NAME], data_dict[LED_STATUS_FIELD_NAME], name, speed, data_dict[DIRECTION_FIELD_NAME], presence, status,
7776
data_dict[TIMESTAMP_FIELD_NAME]))
78-
7977
if table:
8078
print(tabulate(table, header, tablefmt='simple', stralign='right'))
8179
else:

scripts/fibshow

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
Script to show dataplane/FIB entries
5+
6+
usage: fibshow [-ip IPADDR] v
7+
optional arguments:
8+
-ip IPADDR, --ipaddr IPADDR
9+
dataplane/FIB entry for a specific address
10+
11+
Example of the output:
12+
admin@str~$ fibshow -4
13+
No. Vrf Route Nexthop Ifname
14+
----- ------- ------------------ --------------------------------------- -----------------------------------------------------------
15+
1 Red 192.181.8.0/25 10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63 PortChannel101,PortChannel102,PortChannel103,PortChannel104
16+
2 192.184.56.0/25 10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63 PortChannel101,PortChannel102,PortChannel103,PortChannel104
17+
...
18+
Total number of entries 19
19+
20+
admin@str:~$ fibshow -6 -ip 20c0:b560:0:80::
21+
No. Vrf Route Nexthop Ifname
22+
----- ------- ------------------- ----------------------------------- -----------------------------------------------------------
23+
1 20c0:b560:0:80::/64 fc00::72,fc00::76,fc00::7a,fc00::7e PortChannel101,PortChannel102,PortChannel103,PortChannel104
24+
Total number of entries 1
25+
"""
26+
import argparse
27+
import sys
28+
import os
29+
import re
30+
31+
# mock the redis for unit test purposes #
32+
try: # pragma: no cover
33+
if os.environ["UTILITIES_UNIT_TESTING"] == "1":
34+
modules_path = os.path.join(os.path.dirname(__file__), "..")
35+
test_path = os.path.join(modules_path, "tests")
36+
sys.path.insert(0, modules_path)
37+
sys.path.insert(0, test_path)
38+
import mock_tables.dbconnector
39+
mock_variants = { "1": 'appl_db'}
40+
mock_db_path = os.path.join(test_path, "fibshow_input")
41+
file_name = mock_variants[os.environ["FIBSHOW_MOCK"]]
42+
jsonfile_asic = os.path.join(mock_db_path, file_name)
43+
mock_tables.dbconnector.dedicated_dbs['APPL_DB'] = jsonfile_asic
44+
except KeyError: # pragma: no cover
45+
pass
46+
47+
import ipaddress
48+
49+
from swsscommon.swsscommon import SonicV2Connector
50+
from tabulate import tabulate
51+
52+
"""
53+
Base class for v4 and v6 FIB entries.
54+
"""
55+
56+
57+
class FibBase(object):
58+
59+
HEADER = ["No.", "Vrf", "Route", "Nexthop", "Ifname"]
60+
61+
def __init__(self):
62+
super(FibBase, self).__init__()
63+
self.db = SonicV2Connector(host="127.0.0.1")
64+
self.fetch_fib_data()
65+
66+
def fetch_fib_data(self):
67+
"""
68+
Fetch FIB entries from APPL_DB
69+
"""
70+
self.db.connect(self.db.APPL_DB)
71+
self.fib_entry_list = []
72+
73+
fib_str = self.db.keys(self.db.APPL_DB, "ROUTE_TABLE:*")
74+
if not fib_str:
75+
return
76+
77+
for s in fib_str:
78+
fib_entry = s
79+
fib = fib_entry.split(":", 1)[-1]
80+
if not fib:
81+
continue
82+
83+
ent = self.db.get_all(self.db.APPL_DB, s)
84+
if not ent:
85+
continue
86+
87+
self.fib_entry_list.append((fib,) + (ent["nexthop"],) + (ent["ifname"],) )
88+
self.fib_entry_list.sort(key=lambda x: x[0])
89+
return
90+
91+
def display(self, version, address):
92+
"""
93+
Display FIB entries from APPL_DB
94+
"""
95+
output = []
96+
fdb_index = 1
97+
for fib in self.fib_entry_list:
98+
prefix = fib[0]
99+
100+
if 'VRF' in fib[0]:
101+
vrf = re.match(r"VRF-(.*)",fib[0].split(":")[0]).group(1)
102+
prefix = fib[0].split(":")[1]
103+
else:
104+
vrf = ""
105+
ip = ipaddress.ip_address(prefix.split("/")[0])
106+
107+
if address is not None:
108+
if fib[0] == address:
109+
if ip.version == 4 and version == "-4":
110+
output.append([fdb_index, vrf, prefix, fib[1], fib[2]])
111+
fdb_index += 1
112+
elif ip.version == 6 and version == "-6":
113+
output.append([fdb_index, vrf, prefix, fib[1], fib[2]])
114+
fdb_index += 1
115+
break
116+
else:
117+
continue
118+
else:
119+
if ip.version == 4 and version == "-4":
120+
output.append([fdb_index, vrf, prefix, fib[1], fib[2]])
121+
fdb_index += 1
122+
elif ip.version == 6 and version == "-6":
123+
output.append([fdb_index, vrf, prefix, fib[1], fib[2]])
124+
fdb_index += 1
125+
print(tabulate(output, self.HEADER))
126+
print("Total number of entries {0}".format(len(output)))
127+
128+
def main():
129+
130+
parser = argparse.ArgumentParser(description='Show dataplane/FIB entries',
131+
formatter_class=argparse.RawTextHelpFormatter)
132+
parser.add_argument('-ip', '--ipaddr', type=str,
133+
help='dataplane/FIB route for a specific address', default=None)
134+
parser.add_argument('v', help='IP Version -4 or -6')
135+
136+
args = parser.parse_args()
137+
138+
try:
139+
fib = FibBase()
140+
fib.display(args.v, args.ipaddr)
141+
except Exception as e:
142+
print(str(e))
143+
sys.exit(1)
144+
145+
146+
if __name__ == "__main__":
147+
main()

setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
'scripts/fast-reboot-dump.py',
102102
'scripts/fdbclear',
103103
'scripts/fdbshow',
104+
'scripts/fibshow',
104105
'scripts/flow_counters_stat',
105106
'scripts/gearboxutil',
106107
'scripts/generate_dump',

show/main.py

+26
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,19 @@ def protocol(verbose):
854854
cmd = 'sudo {} -c "show ip protocol"'.format(constants.RVTYSH_COMMAND)
855855
run_command(cmd, display_cmd=verbose)
856856

857+
#
858+
# 'fib' subcommand ("show ip fib")
859+
#
860+
@ip.command()
861+
@click.argument('ipaddress', required=False)
862+
@click.option('--verbose', is_flag=True, help="Enable verbose output")
863+
def fib(ipaddress, verbose):
864+
"""Show IP FIB table"""
865+
cmd = "fibshow -4"
866+
if ipaddress is not None:
867+
cmd += " -ip {}".format(ipaddress)
868+
run_command(cmd, display_cmd=verbose)
869+
857870

858871
#
859872
# 'ipv6' group ("show ipv6 ...")
@@ -983,6 +996,19 @@ def link_local_mode(verbose):
983996

984997
click.echo(tabulate(body, header, tablefmt="grid"))
985998

999+
#
1000+
# 'fib' subcommand ("show ipv6 fib")
1001+
#
1002+
@ipv6.command()
1003+
@click.argument('ipaddress', required=False)
1004+
@click.option('--verbose', is_flag=True, help="Enable verbose output")
1005+
def fib(ipaddress, verbose):
1006+
"""Show IP FIB table"""
1007+
cmd = "fibshow -6"
1008+
if ipaddress is not None:
1009+
cmd += " -ip {}".format(ipaddress)
1010+
run_command(cmd, display_cmd=verbose)
1011+
9861012
#
9871013
# 'lldp' group ("show lldp ...")
9881014
#

tests/conftest.py

+5
Original file line numberDiff line numberDiff line change
@@ -313,3 +313,8 @@ def setup_ip_route_commands():
313313

314314
return show
315315

316+
@pytest.fixture
317+
def setup_fib_commands():
318+
import show.main as show
319+
return show
320+

tests/fibshow_input/__init__.py

Whitespace-only changes.

tests/fibshow_input/appl_db.json

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"ROUTE_TABLE:192.168.104.0/25": {
3+
"nexthop": "10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63",
4+
"ifname" : "PortChannel101,PortChannel102,PortChannel103,PortChannel104"
5+
},
6+
"ROUTE_TABLE:192.168.104.128/25": {
7+
"nexthop": "",
8+
"ifname" : "PortChannel101,PortChannel102,PortChannel103,PortChannel104"
9+
},
10+
"ROUTE_TABLE:192.168.112.0/25": {
11+
"nexthop": "10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63",
12+
"ifname" : ""
13+
},
14+
"ROUTE_TABLE:VRF-Red:192.168.112.128/25": {
15+
"nexthop": "10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63",
16+
"ifname" : "PortChannel101,PortChannel102,PortChannel103,PortChannel104"
17+
},
18+
"ROUTE_TABLE:192.168.120.0/25": {
19+
"nexthop": "10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63",
20+
"ifname" : "PortChannel101,PortChannel102,PortChannel103,PortChannel104"
21+
},
22+
"ROUTE_TABLE:20c0:fe28:0:80::/64": {
23+
"nexthop": "fc00::72,fc00::76,fc00::7a,fc00::7e",
24+
"ifname" : "PortChannel101,PortChannel102,PortChannel103,PortChannel104"
25+
},
26+
"ROUTE_TABLE:20c0:fe28::/64": {
27+
"nexthop": "fc00::72,fc00::76,fc00::7a,fc00::7e",
28+
"ifname" : "PortChannel101,PortChannel102,PortChannel103,PortChannel104"
29+
},
30+
"ROUTE_TABLE:20c0:fe30:0:80::/64": {
31+
"nexthop": "",
32+
"ifname" : "PortChannel101,PortChannel102,PortChannel103,PortChannel104"
33+
}
34+
}

tests/fibshow_test.py

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import os
2+
3+
import pytest
4+
5+
from click.testing import CliRunner
6+
7+
from utilities_common import multi_asic
8+
from utilities_common import constants
9+
from .utils import get_result_and_return_code
10+
import show.main as show
11+
12+
from unittest.mock import patch
13+
14+
from sonic_py_common import device_info
15+
16+
show_ip_fib_v4 = """\
17+
No. Vrf Route Nexthop Ifname
18+
----- ----- ------------------ --------------------------------------- -----------------------------------------------------------
19+
1 192.168.104.0/25 10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63 PortChannel101,PortChannel102,PortChannel103,PortChannel104
20+
2 192.168.104.128/25 PortChannel101,PortChannel102,PortChannel103,PortChannel104
21+
3 192.168.112.0/25 10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63
22+
4 192.168.120.0/25 10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63 PortChannel101,PortChannel102,PortChannel103,PortChannel104
23+
5 Red 192.168.112.128/25 10.0.0.57,10.0.0.59,10.0.0.61,10.0.0.63 PortChannel101,PortChannel102,PortChannel103,PortChannel104
24+
Total number of entries 5
25+
"""
26+
27+
show_ip_fib_v6 = """\
28+
No. Vrf Route Nexthop Ifname
29+
----- ----- ------------------- ----------------------------------- -----------------------------------------------------------
30+
1 20c0:fe28:0:80::/64 fc00::72,fc00::76,fc00::7a,fc00::7e PortChannel101,PortChannel102,PortChannel103,PortChannel104
31+
2 20c0:fe28::/64 fc00::72,fc00::76,fc00::7a,fc00::7e PortChannel101,PortChannel102,PortChannel103,PortChannel104
32+
3 20c0:fe30:0:80::/64 PortChannel101,PortChannel102,PortChannel103,PortChannel104
33+
Total number of entries 3
34+
"""
35+
36+
root_path = os.path.dirname(os.path.abspath(__file__))
37+
modules_path = os.path.dirname(root_path)
38+
scripts_path = os.path.join(modules_path, "scripts")
39+
40+
41+
class TestFibshow():
42+
@pytest.fixture(scope="class", autouse=True)
43+
def setup_class(cls):
44+
print("SETUP")
45+
os.environ["PATH"] += os.pathsep + scripts_path
46+
os.environ["UTILITIES_UNIT_TESTING"] = "1"
47+
yield
48+
print("TEARDOWN")
49+
os.environ["PATH"] = os.pathsep.join(os.environ["PATH"].split(os.pathsep)[:-1])
50+
os.environ["UTILITIES_UNIT_TESTING"] = "0"
51+
52+
@pytest.fixture(scope="function", autouse=True)
53+
def setUp(self):
54+
self.runner = CliRunner()
55+
yield
56+
del os.environ["FIBSHOW_MOCK"]
57+
58+
def set_mock_variant(self, variant: str):
59+
os.environ["FIBSHOW_MOCK"] = variant
60+
61+
def test_show_ip_fib(self):
62+
self.set_mock_variant("1")
63+
from .mock_tables import dbconnector
64+
modules_path = os.path.join(os.path.dirname(__file__), "..")
65+
test_path = os.path.join(modules_path, "tests")
66+
mock_db_path = os.path.join(test_path, "fibshow_input")
67+
jsonfile_appl = os.path.join(mock_db_path, 'appl_db')
68+
dbconnector.dedicated_dbs['APPL_DB'] = jsonfile_appl
69+
print(dbconnector.load_database_config())
70+
result = self.runner.invoke(show.cli.commands["ip"].commands["fib"], [])
71+
dbconnector.dedicated_dbs['APPL_DB'] = None
72+
print(result.exit_code)
73+
print(result.output)
74+
assert result.exit_code == 0
75+
assert result.output == show_ip_fib_v4
76+
77+
def test_show_ipv6_fib(self):
78+
self.set_mock_variant("1")
79+
from .mock_tables import dbconnector
80+
modules_path = os.path.join(os.path.dirname(__file__), "..")
81+
test_path = os.path.join(modules_path, "tests")
82+
mock_db_path = os.path.join(test_path, "fibshow_input")
83+
jsonfile_appl = os.path.join(mock_db_path, 'appl_db')
84+
dbconnector.dedicated_dbs['APPL_DB'] = jsonfile_appl
85+
print(dbconnector.load_database_config())
86+
result = self.runner.invoke(show.cli.commands["ipv6"].commands["fib"], [])
87+
dbconnector.dedicated_dbs['APPL_DB'] = None
88+
print(result.exit_code)
89+
print(result.output)
90+
assert result.exit_code == 0
91+
assert result.output == show_ip_fib_v6
92+

0 commit comments

Comments
 (0)