Skip to content

Commit 5eb266a

Browse files
authored
[chassis] Modify the show ip route to hide the Ethernet-IB port in the output (#3537)
* update show ip route for voq chassis Signed-off-by: Arvindsrinivasan Lakshmi Narasimhan <[email protected]> * add UT * add more UT * Fix linter errors * fix UT * make linter happy --------- Signed-off-by: Arvindsrinivasan Lakshmi Narasimhan <[email protected]>
1 parent b82115c commit 5eb266a

11 files changed

+698
-10
lines changed

show/bgp_common.py

+18-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import json
44

55
import utilities_common.multi_asic as multi_asic_util
6-
from sonic_py_common import multi_asic
6+
from sonic_py_common import device_info, multi_asic
77
from utilities_common import constants
88

99
'''
@@ -60,10 +60,12 @@ def get_nexthop_info_str(nxhp_info, filterByIp):
6060
else:
6161
str_2_return = " via {},".format(nxhp_info['ip'])
6262
if "interfaceName" in nxhp_info:
63+
intfs = nxhp_info['interfaceName']
6364
if filterByIp:
64-
str_2_return += ", via {}".format(nxhp_info['interfaceName'])
65+
str_2_return += ", via {}".format(intfs)
6566
else:
66-
str_2_return += " {},".format(nxhp_info['interfaceName'])
67+
str_2_return += " {},".format(intfs)
68+
6769
elif "directlyConnected" in nxhp_info:
6870
str_2_return = " is directly connected,"
6971
if "interfaceName" in nxhp_info:
@@ -80,10 +82,13 @@ def get_nexthop_info_str(nxhp_info, filterByIp):
8082
str_2_return += "(vrf {}, {},".format(nxhp_info['vrf'], nxhp_info['interfaceName'])
8183
if "active" not in nxhp_info:
8284
str_2_return += " inactive"
85+
if "recursive" in nxhp_info:
86+
if device_info.is_voq_chassis():
87+
str_2_return = " " + str_2_return + " recursive via iBGP"
88+
else:
89+
str_2_return += " (recursive)"
8390
if "onLink" in nxhp_info:
8491
str_2_return += " onlink"
85-
if "recursive" in nxhp_info:
86-
str_2_return += " (recursive)"
8792
if "source" in nxhp_info:
8893
str_2_return += ", src {}".format(nxhp_info['source'])
8994
if "labels" in nxhp_info:
@@ -220,6 +225,12 @@ def merge_to_combined_route(combined_route, route, new_info_l):
220225
if nh['interfaceName'] == combined_route[route][j]['nexthops'][y]['interfaceName']:
221226
found = True
222227
break
228+
if device_info.is_voq_chassis():
229+
if nh['ip'] == combined_route[route][j]['nexthops'][y]['ip']:
230+
if 'interfaceName' not in combined_route[route][j]['nexthops'][y]:
231+
combined_route[route][j]['nexthops'][y] = nh
232+
found = True
233+
break
223234
elif "active" not in nh and "active" not in combined_route[route][j]['nexthops'][y]:
224235
if nh['ip'] == combined_route[route][j]['nexthops'][y]['ip']:
225236
found = True
@@ -253,7 +264,7 @@ def process_route_info(route_info, device, filter_back_end, print_ns_str, asic_c
253264
while len(new_info['nexthops']):
254265
nh = new_info['nexthops'].pop()
255266
if filter_back_end and back_end_intf_set != None and "interfaceName" in nh:
256-
if nh['interfaceName'] in back_end_intf_set:
267+
if nh['interfaceName'] in back_end_intf_set or nh['interfaceName'].startswith('Ethernet-IB'):
257268
del_cnt += 1
258269
else:
259270
new_nhop_l.append(copy.deepcopy(nh))
@@ -327,6 +338,7 @@ def show_routes(args, namespace, display, verbose, ipver):
327338
if display not in ['frontend', 'all']:
328339
print("dislay option '{}' is not a valid option.".format(display))
329340
return
341+
330342
device = multi_asic_util.MultiAsic(display, namespace)
331343
arg_strg = ""
332344
found_json = 0
@@ -376,7 +388,6 @@ def show_routes(args, namespace, display, verbose, ipver):
376388
# Need to add "ns" to form bgpX so it is sent to the correct bgpX docker to handle the request
377389
cmd = "show {} route {}".format(ipver, arg_strg)
378390
output = bgp_util.run_bgp_show_command(cmd, ns)
379-
380391
# in case no output or something went wrong with user specified cmd argument(s) error it out
381392
# error from FRR always start with character "%"
382393
if output == "":

tests/conftest.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,11 @@ def setup_single_bgp_instance(request):
194194
elif request.param == 'ipv6_route':
195195
bgp_mocked_json = 'ipv6_route.json'
196196
elif request.param == 'ip_special_route':
197-
bgp_mocked_json = 'ip_special_route.json'
197+
bgp_mocked_json = 'ip_special_route.json'
198+
elif request.param == 'ip_route_lc':
199+
bgp_mocked_json = 'ip_route_lc.json'
200+
elif request.param == 'ip_route_remote_lc':
201+
bgp_mocked_json = 'ip_route_remote_lc.json'
198202
else:
199203
bgp_mocked_json = os.path.join(
200204
test_path, 'mock_tables', 'dummy.json')
@@ -240,7 +244,8 @@ def mock_run_bgp_route_command(vtysh_cmd, bgp_namespace, vtysh_shell_cmd=constan
240244
_old_run_bgp_command = bgp_util.run_bgp_command
241245
if any([request.param == 'ip_route',
242246
request.param == 'ip_specific_route', request.param == 'ip_special_route',
243-
request.param == 'ipv6_route', request.param == 'ipv6_specific_route']):
247+
request.param == 'ipv6_route', request.param == 'ipv6_specific_route',
248+
request.param == 'ip_route_lc', request.param == 'ip_route_remote_lc']):
244249
bgp_util.run_bgp_command = mock.MagicMock(
245250
return_value=mock_run_bgp_route_command("", ""))
246251
elif request.param.startswith('ipv6_route_err'):
@@ -303,6 +308,12 @@ def setup_multi_asic_bgp_instance(request):
303308
request.param.startswith('bgp_v4_neighbor') or \
304309
request.param.startswith('bgp_v6_neighbor'):
305310
m_asic_json_file = request.param
311+
elif request.param == 'ip_route_lc':
312+
m_asic_json_file = 'ip_route_lc.json'
313+
elif request.param == 'ip_route_remote_lc':
314+
m_asic_json_file = 'ip_route_remote_lc.json'
315+
elif request.param == 'ip_route_lc_2':
316+
m_asic_json_file = 'ip_route_lc_2.json'
306317
else:
307318
m_asic_json_file = os.path.join(
308319
test_path, 'mock_tables', 'dummy.json')

tests/ip_show_routes_multi_asic_test.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import os
22
from importlib import reload
3-
43
import pytest
54

5+
66
from . import show_ip_route_common
77
from click.testing import CliRunner
8+
89
test_path = os.path.dirname(os.path.abspath(__file__))
910
modules_path = os.path.dirname(test_path)
1011
scripts_path = os.path.join(modules_path, "scripts")
+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import os
2+
from importlib import reload
3+
import pytest
4+
from unittest import mock
5+
6+
import show.main as show
7+
from . import show_ip_route_common
8+
import utilities_common.multi_asic as multi_asic_util
9+
from click.testing import CliRunner
10+
11+
test_path = os.path.dirname(os.path.abspath(__file__))
12+
modules_path = os.path.dirname(test_path)
13+
scripts_path = os.path.join(modules_path, "scripts")
14+
15+
16+
class TestMultiAsicVoqLcShowIpRouteDisplayAllCommands(object):
17+
@classmethod
18+
def setup_class(cls):
19+
print("SETUP")
20+
os.environ["PATH"] += os.pathsep + scripts_path
21+
os.environ["UTILITIES_UNIT_TESTING"] = "2"
22+
os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = "multi_asic"
23+
from .mock_tables import mock_multi_asic
24+
reload(mock_multi_asic)
25+
from .mock_tables import dbconnector
26+
dbconnector.load_namespace_config()
27+
28+
@pytest.mark.parametrize('setup_multi_asic_bgp_instance',
29+
['ip_route_lc'], indirect=['setup_multi_asic_bgp_instance'])
30+
@mock.patch("sonic_py_common.device_info.is_voq_chassis", mock.MagicMock(return_value=True))
31+
def test_voq_chassis_lc(
32+
self,
33+
setup_ip_route_commands,
34+
setup_multi_asic_bgp_instance):
35+
36+
runner = CliRunner()
37+
result = runner.invoke(
38+
show.cli.commands["ip"].commands["route"], ["-dfrontend"])
39+
print("{}".format(result.output))
40+
assert result.exit_code == 0
41+
assert result.output == show_ip_route_common.SHOW_IP_ROUTE_LC
42+
43+
@pytest.mark.parametrize('setup_multi_asic_bgp_instance',
44+
['ip_route_remote_lc'], indirect=['setup_multi_asic_bgp_instance'])
45+
@mock.patch("sonic_py_common.device_info.is_voq_chassis", mock.MagicMock(return_value=True))
46+
def test_voq_chassis_remote_lc(
47+
self,
48+
setup_ip_route_commands,
49+
setup_multi_asic_bgp_instance):
50+
51+
runner = CliRunner()
52+
result = runner.invoke(
53+
show.cli.commands["ip"].commands["route"], ["-dfrontend"])
54+
print("{}".format(result.output))
55+
assert result.exit_code == 0
56+
assert result.output == show_ip_route_common.SHOW_IP_ROUTE_REMOTE_LC
57+
58+
@pytest.mark.parametrize('setup_multi_asic_bgp_instance',
59+
['ip_route_lc'], indirect=['setup_multi_asic_bgp_instance'])
60+
@mock.patch("sonic_py_common.device_info.is_voq_chassis", mock.MagicMock(return_value=True))
61+
def test_voq_chassis_lc_def_route(
62+
self,
63+
setup_ip_route_commands,
64+
setup_multi_asic_bgp_instance):
65+
66+
runner = CliRunner()
67+
result = runner.invoke(
68+
show.cli.commands["ip"].commands["route"], ["0.0.0.0/0"])
69+
print("{}".format(result.output))
70+
assert result.exit_code == 0
71+
assert result.output == show_ip_route_common.SHOW_IP_ROUTE_LC_DEFAULT_ROUTE
72+
73+
@pytest.mark.parametrize('setup_multi_asic_bgp_instance',
74+
['ip_route_remote_lc'], indirect=['setup_multi_asic_bgp_instance'])
75+
@mock.patch("sonic_py_common.device_info.is_voq_chassis", mock.MagicMock(return_value=True))
76+
def test_voq_chassis_remote_lc_default_route(
77+
self,
78+
setup_ip_route_commands,
79+
setup_multi_asic_bgp_instance):
80+
81+
runner = CliRunner()
82+
result = runner.invoke(
83+
show.cli.commands["ip"].commands["route"], ["0.0.0.0/0"])
84+
print("{}".format(result.output))
85+
assert result.exit_code == 0
86+
assert result.output == show_ip_route_common.SHOW_IP_ROUTE_REMOTE_LC_DEFAULT_ROUTE
87+
88+
@pytest.mark.parametrize('setup_multi_asic_bgp_instance',
89+
['ip_route_lc_2'], indirect=['setup_multi_asic_bgp_instance'])
90+
@mock.patch("sonic_py_common.device_info.is_voq_chassis", mock.MagicMock(return_value=True))
91+
@mock.patch.object(multi_asic_util.MultiAsic, "get_ns_list_based_on_options",
92+
mock.MagicMock(return_value=["asic0", "asic1"]))
93+
def test_voq_chassis_lc_def_route_2(
94+
self,
95+
setup_ip_route_commands,
96+
setup_multi_asic_bgp_instance):
97+
98+
runner = CliRunner()
99+
result = runner.invoke(
100+
show.cli.commands["ip"].commands["route"], ["0.0.0.0/0"])
101+
print("{}".format(result.output))
102+
assert result.exit_code == 0
103+
assert result.output == show_ip_route_common.SHOW_IP_ROUTE_LC_DEFAULT_ROUTE_2
104+
105+
@classmethod
106+
def teardown_class(cls):
107+
print("TEARDOWN")
108+
os.environ["PATH"] = os.pathsep.join(os.environ["PATH"].split(os.pathsep)[:-1])
109+
os.environ["UTILITIES_UNIT_TESTING"] = "0"
110+
os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = ""
111+
from .mock_tables import mock_single_asic
112+
reload(mock_single_asic)
+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"0.0.0.0/0": [
3+
{
4+
"prefix": "0.0.0.0/0",
5+
"prefixLen": 0,
6+
"protocol": "bgp",
7+
"vrfId": 0,
8+
"vrfName": "default",
9+
"selected": true,
10+
"destSelected": true,
11+
"distance": 20,
12+
"metric": 0,
13+
"installed": true,
14+
"table": 254,
15+
"internalStatus": 16,
16+
"internalFlags": 8,
17+
"internalNextHopNum": 4,
18+
"internalNextHopActiveNum": 4,
19+
"nexthopGroupId": 566,
20+
"installedNexthopGroupId": 566,
21+
"uptime": "04w0d11h",
22+
"nexthops": [
23+
{
24+
"flags": 3,
25+
"fib": true,
26+
"ip": "20.1.0.128",
27+
"afi": "ipv4",
28+
"interfaceIndex": 2,
29+
"interfaceName": "PortChannel1",
30+
"active": true,
31+
"weight": 1
32+
},
33+
{
34+
"flags": 3,
35+
"fib": true,
36+
"ip": "20.1.8.128",
37+
"afi": "ipv4",
38+
"interfaceIndex": 4,
39+
"interfaceName": "PortChannel5",
40+
"active": true,
41+
"weight": 1
42+
},
43+
{
44+
"flags": 3,
45+
"fib": true,
46+
"ip": "20.1.16.128",
47+
"afi": "ipv4",
48+
"interfaceIndex": 5,
49+
"interfaceName": "PortChannel9",
50+
"active": true,
51+
"weight": 1
52+
},
53+
{
54+
"flags": 3,
55+
"fib": true,
56+
"ip": "20.1.24.128",
57+
"afi": "ipv4",
58+
"interfaceIndex": 3,
59+
"interfaceName": "PortChannel13",
60+
"active": true,
61+
"weight": 1
62+
}
63+
]
64+
}
65+
]
66+
}
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"0.0.0.0/0": [
3+
{
4+
"prefix": "0.0.0.0/0",
5+
"prefixLen": 0,
6+
"protocol": "bgp",
7+
"vrfId": 0,
8+
"vrfName": "default",
9+
"selected": true,
10+
"destSelected": true,
11+
"distance": 20,
12+
"metric": 0,
13+
"installed": true,
14+
"table": 254,
15+
"internalStatus": 16,
16+
"internalFlags": 9,
17+
"internalNextHopNum": 3,
18+
"internalNextHopActiveNum": 3,
19+
"nexthopGroupId": 2122,
20+
"installedNexthopGroupId": 2122,
21+
"uptime": "01:01:51",
22+
"nexthops": [
23+
{
24+
"flags": 3,
25+
"fib": true,
26+
"ip": "10.0.0.1",
27+
"afi": "ipv4",
28+
"interfaceIndex": 29,
29+
"interfaceName": "PortChannel102",
30+
"active": true,
31+
"weight": 1
32+
},
33+
{
34+
"flags": 5,
35+
"ip": "10.0.0.7",
36+
"afi": "ipv4",
37+
"active": true,
38+
"recursive": true,
39+
"weight": 1
40+
},
41+
{
42+
"flags": 11,
43+
"fib": true,
44+
"ip": "10.0.0.7",
45+
"afi": "ipv4",
46+
"interfaceIndex": 52,
47+
"interfaceName": "Ethernet-IB0",
48+
"resolver": true,
49+
"active": true,
50+
"onLink": true,
51+
"weight": 1
52+
}
53+
]
54+
}
55+
]
56+
}

0 commit comments

Comments
 (0)