Skip to content

Commit

Permalink
[chassis] Modify the show ip route to hide the Ethernet-IB port in th…
Browse files Browse the repository at this point in the history
…e 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]>
  • Loading branch information
arlakshm authored Sep 9, 2024
1 parent b82115c commit 5eb266a
Show file tree
Hide file tree
Showing 11 changed files with 698 additions and 10 deletions.
25 changes: 18 additions & 7 deletions show/bgp_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import json

import utilities_common.multi_asic as multi_asic_util
from sonic_py_common import multi_asic
from sonic_py_common import device_info, multi_asic
from utilities_common import constants

'''
Expand Down Expand Up @@ -60,10 +60,12 @@ def get_nexthop_info_str(nxhp_info, filterByIp):
else:
str_2_return = " via {},".format(nxhp_info['ip'])
if "interfaceName" in nxhp_info:
intfs = nxhp_info['interfaceName']
if filterByIp:
str_2_return += ", via {}".format(nxhp_info['interfaceName'])
str_2_return += ", via {}".format(intfs)
else:
str_2_return += " {},".format(nxhp_info['interfaceName'])
str_2_return += " {},".format(intfs)

elif "directlyConnected" in nxhp_info:
str_2_return = " is directly connected,"
if "interfaceName" in nxhp_info:
Expand All @@ -80,10 +82,13 @@ def get_nexthop_info_str(nxhp_info, filterByIp):
str_2_return += "(vrf {}, {},".format(nxhp_info['vrf'], nxhp_info['interfaceName'])
if "active" not in nxhp_info:
str_2_return += " inactive"
if "recursive" in nxhp_info:
if device_info.is_voq_chassis():
str_2_return = " " + str_2_return + " recursive via iBGP"
else:
str_2_return += " (recursive)"
if "onLink" in nxhp_info:
str_2_return += " onlink"
if "recursive" in nxhp_info:
str_2_return += " (recursive)"
if "source" in nxhp_info:
str_2_return += ", src {}".format(nxhp_info['source'])
if "labels" in nxhp_info:
Expand Down Expand Up @@ -220,6 +225,12 @@ def merge_to_combined_route(combined_route, route, new_info_l):
if nh['interfaceName'] == combined_route[route][j]['nexthops'][y]['interfaceName']:
found = True
break
if device_info.is_voq_chassis():
if nh['ip'] == combined_route[route][j]['nexthops'][y]['ip']:
if 'interfaceName' not in combined_route[route][j]['nexthops'][y]:
combined_route[route][j]['nexthops'][y] = nh
found = True
break
elif "active" not in nh and "active" not in combined_route[route][j]['nexthops'][y]:
if nh['ip'] == combined_route[route][j]['nexthops'][y]['ip']:
found = True
Expand Down Expand Up @@ -253,7 +264,7 @@ def process_route_info(route_info, device, filter_back_end, print_ns_str, asic_c
while len(new_info['nexthops']):
nh = new_info['nexthops'].pop()
if filter_back_end and back_end_intf_set != None and "interfaceName" in nh:
if nh['interfaceName'] in back_end_intf_set:
if nh['interfaceName'] in back_end_intf_set or nh['interfaceName'].startswith('Ethernet-IB'):
del_cnt += 1
else:
new_nhop_l.append(copy.deepcopy(nh))
Expand Down Expand Up @@ -327,6 +338,7 @@ def show_routes(args, namespace, display, verbose, ipver):
if display not in ['frontend', 'all']:
print("dislay option '{}' is not a valid option.".format(display))
return

device = multi_asic_util.MultiAsic(display, namespace)
arg_strg = ""
found_json = 0
Expand Down Expand Up @@ -376,7 +388,6 @@ def show_routes(args, namespace, display, verbose, ipver):
# Need to add "ns" to form bgpX so it is sent to the correct bgpX docker to handle the request
cmd = "show {} route {}".format(ipver, arg_strg)
output = bgp_util.run_bgp_show_command(cmd, ns)

# in case no output or something went wrong with user specified cmd argument(s) error it out
# error from FRR always start with character "%"
if output == "":
Expand Down
15 changes: 13 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,11 @@ def setup_single_bgp_instance(request):
elif request.param == 'ipv6_route':
bgp_mocked_json = 'ipv6_route.json'
elif request.param == 'ip_special_route':
bgp_mocked_json = 'ip_special_route.json'
bgp_mocked_json = 'ip_special_route.json'
elif request.param == 'ip_route_lc':
bgp_mocked_json = 'ip_route_lc.json'
elif request.param == 'ip_route_remote_lc':
bgp_mocked_json = 'ip_route_remote_lc.json'
else:
bgp_mocked_json = os.path.join(
test_path, 'mock_tables', 'dummy.json')
Expand Down Expand Up @@ -240,7 +244,8 @@ def mock_run_bgp_route_command(vtysh_cmd, bgp_namespace, vtysh_shell_cmd=constan
_old_run_bgp_command = bgp_util.run_bgp_command
if any([request.param == 'ip_route',
request.param == 'ip_specific_route', request.param == 'ip_special_route',
request.param == 'ipv6_route', request.param == 'ipv6_specific_route']):
request.param == 'ipv6_route', request.param == 'ipv6_specific_route',
request.param == 'ip_route_lc', request.param == 'ip_route_remote_lc']):
bgp_util.run_bgp_command = mock.MagicMock(
return_value=mock_run_bgp_route_command("", ""))
elif request.param.startswith('ipv6_route_err'):
Expand Down Expand Up @@ -303,6 +308,12 @@ def setup_multi_asic_bgp_instance(request):
request.param.startswith('bgp_v4_neighbor') or \
request.param.startswith('bgp_v6_neighbor'):
m_asic_json_file = request.param
elif request.param == 'ip_route_lc':
m_asic_json_file = 'ip_route_lc.json'
elif request.param == 'ip_route_remote_lc':
m_asic_json_file = 'ip_route_remote_lc.json'
elif request.param == 'ip_route_lc_2':
m_asic_json_file = 'ip_route_lc_2.json'
else:
m_asic_json_file = os.path.join(
test_path, 'mock_tables', 'dummy.json')
Expand Down
3 changes: 2 additions & 1 deletion tests/ip_show_routes_multi_asic_test.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import os
from importlib import reload

import pytest


from . import show_ip_route_common
from click.testing import CliRunner

test_path = os.path.dirname(os.path.abspath(__file__))
modules_path = os.path.dirname(test_path)
scripts_path = os.path.join(modules_path, "scripts")
Expand Down
112 changes: 112 additions & 0 deletions tests/ip_show_routes_voq_chassis_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import os
from importlib import reload
import pytest
from unittest import mock

import show.main as show
from . import show_ip_route_common
import utilities_common.multi_asic as multi_asic_util
from click.testing import CliRunner

test_path = os.path.dirname(os.path.abspath(__file__))
modules_path = os.path.dirname(test_path)
scripts_path = os.path.join(modules_path, "scripts")


class TestMultiAsicVoqLcShowIpRouteDisplayAllCommands(object):
@classmethod
def setup_class(cls):
print("SETUP")
os.environ["PATH"] += os.pathsep + scripts_path
os.environ["UTILITIES_UNIT_TESTING"] = "2"
os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = "multi_asic"
from .mock_tables import mock_multi_asic
reload(mock_multi_asic)
from .mock_tables import dbconnector
dbconnector.load_namespace_config()

@pytest.mark.parametrize('setup_multi_asic_bgp_instance',
['ip_route_lc'], indirect=['setup_multi_asic_bgp_instance'])
@mock.patch("sonic_py_common.device_info.is_voq_chassis", mock.MagicMock(return_value=True))
def test_voq_chassis_lc(
self,
setup_ip_route_commands,
setup_multi_asic_bgp_instance):

runner = CliRunner()
result = runner.invoke(
show.cli.commands["ip"].commands["route"], ["-dfrontend"])
print("{}".format(result.output))
assert result.exit_code == 0
assert result.output == show_ip_route_common.SHOW_IP_ROUTE_LC

@pytest.mark.parametrize('setup_multi_asic_bgp_instance',
['ip_route_remote_lc'], indirect=['setup_multi_asic_bgp_instance'])
@mock.patch("sonic_py_common.device_info.is_voq_chassis", mock.MagicMock(return_value=True))
def test_voq_chassis_remote_lc(
self,
setup_ip_route_commands,
setup_multi_asic_bgp_instance):

runner = CliRunner()
result = runner.invoke(
show.cli.commands["ip"].commands["route"], ["-dfrontend"])
print("{}".format(result.output))
assert result.exit_code == 0
assert result.output == show_ip_route_common.SHOW_IP_ROUTE_REMOTE_LC

@pytest.mark.parametrize('setup_multi_asic_bgp_instance',
['ip_route_lc'], indirect=['setup_multi_asic_bgp_instance'])
@mock.patch("sonic_py_common.device_info.is_voq_chassis", mock.MagicMock(return_value=True))
def test_voq_chassis_lc_def_route(
self,
setup_ip_route_commands,
setup_multi_asic_bgp_instance):

runner = CliRunner()
result = runner.invoke(
show.cli.commands["ip"].commands["route"], ["0.0.0.0/0"])
print("{}".format(result.output))
assert result.exit_code == 0
assert result.output == show_ip_route_common.SHOW_IP_ROUTE_LC_DEFAULT_ROUTE

@pytest.mark.parametrize('setup_multi_asic_bgp_instance',
['ip_route_remote_lc'], indirect=['setup_multi_asic_bgp_instance'])
@mock.patch("sonic_py_common.device_info.is_voq_chassis", mock.MagicMock(return_value=True))
def test_voq_chassis_remote_lc_default_route(
self,
setup_ip_route_commands,
setup_multi_asic_bgp_instance):

runner = CliRunner()
result = runner.invoke(
show.cli.commands["ip"].commands["route"], ["0.0.0.0/0"])
print("{}".format(result.output))
assert result.exit_code == 0
assert result.output == show_ip_route_common.SHOW_IP_ROUTE_REMOTE_LC_DEFAULT_ROUTE

@pytest.mark.parametrize('setup_multi_asic_bgp_instance',
['ip_route_lc_2'], indirect=['setup_multi_asic_bgp_instance'])
@mock.patch("sonic_py_common.device_info.is_voq_chassis", mock.MagicMock(return_value=True))
@mock.patch.object(multi_asic_util.MultiAsic, "get_ns_list_based_on_options",
mock.MagicMock(return_value=["asic0", "asic1"]))
def test_voq_chassis_lc_def_route_2(
self,
setup_ip_route_commands,
setup_multi_asic_bgp_instance):

runner = CliRunner()
result = runner.invoke(
show.cli.commands["ip"].commands["route"], ["0.0.0.0/0"])
print("{}".format(result.output))
assert result.exit_code == 0
assert result.output == show_ip_route_common.SHOW_IP_ROUTE_LC_DEFAULT_ROUTE_2

@classmethod
def teardown_class(cls):
print("TEARDOWN")
os.environ["PATH"] = os.pathsep.join(os.environ["PATH"].split(os.pathsep)[:-1])
os.environ["UTILITIES_UNIT_TESTING"] = "0"
os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = ""
from .mock_tables import mock_single_asic
reload(mock_single_asic)
66 changes: 66 additions & 0 deletions tests/mock_tables/asic0/ip_route_lc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"0.0.0.0/0": [
{
"prefix": "0.0.0.0/0",
"prefixLen": 0,
"protocol": "bgp",
"vrfId": 0,
"vrfName": "default",
"selected": true,
"destSelected": true,
"distance": 20,
"metric": 0,
"installed": true,
"table": 254,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 4,
"internalNextHopActiveNum": 4,
"nexthopGroupId": 566,
"installedNexthopGroupId": 566,
"uptime": "04w0d11h",
"nexthops": [
{
"flags": 3,
"fib": true,
"ip": "20.1.0.128",
"afi": "ipv4",
"interfaceIndex": 2,
"interfaceName": "PortChannel1",
"active": true,
"weight": 1
},
{
"flags": 3,
"fib": true,
"ip": "20.1.8.128",
"afi": "ipv4",
"interfaceIndex": 4,
"interfaceName": "PortChannel5",
"active": true,
"weight": 1
},
{
"flags": 3,
"fib": true,
"ip": "20.1.16.128",
"afi": "ipv4",
"interfaceIndex": 5,
"interfaceName": "PortChannel9",
"active": true,
"weight": 1
},
{
"flags": 3,
"fib": true,
"ip": "20.1.24.128",
"afi": "ipv4",
"interfaceIndex": 3,
"interfaceName": "PortChannel13",
"active": true,
"weight": 1
}
]
}
]
}
56 changes: 56 additions & 0 deletions tests/mock_tables/asic0/ip_route_lc_2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"0.0.0.0/0": [
{
"prefix": "0.0.0.0/0",
"prefixLen": 0,
"protocol": "bgp",
"vrfId": 0,
"vrfName": "default",
"selected": true,
"destSelected": true,
"distance": 20,
"metric": 0,
"installed": true,
"table": 254,
"internalStatus": 16,
"internalFlags": 9,
"internalNextHopNum": 3,
"internalNextHopActiveNum": 3,
"nexthopGroupId": 2122,
"installedNexthopGroupId": 2122,
"uptime": "01:01:51",
"nexthops": [
{
"flags": 3,
"fib": true,
"ip": "10.0.0.1",
"afi": "ipv4",
"interfaceIndex": 29,
"interfaceName": "PortChannel102",
"active": true,
"weight": 1
},
{
"flags": 5,
"ip": "10.0.0.7",
"afi": "ipv4",
"active": true,
"recursive": true,
"weight": 1
},
{
"flags": 11,
"fib": true,
"ip": "10.0.0.7",
"afi": "ipv4",
"interfaceIndex": 52,
"interfaceName": "Ethernet-IB0",
"resolver": true,
"active": true,
"onLink": true,
"weight": 1
}
]
}
]
}
Loading

0 comments on commit 5eb266a

Please sign in to comment.