Skip to content

Commit 9d206af

Browse files
authored
[chassis][mutli-asic][lldp] "show lldp table/neighbors" displays error message in output on multi-asis linecard. (sonic-net#3358)
Modify the lldpshow script to fix the output of the "show lldp table" and "show lldp neighbors" on the multi-asic Linecard. Fixes sonic-net#19209 * [mutli-asic][lldp] "show lldp table" displays error message in output on multi-asic linecard * Added code coverage UT Signed-off-by: mlok <[email protected]>
1 parent 515265a commit 9d206af

File tree

4 files changed

+56
-7
lines changed

4 files changed

+56
-7
lines changed

scripts/lldpshow

+9-4
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ import sys
2626
from lxml import etree as ET
2727

2828
from sonic_py_common import device_info
29+
from utilities_common import constants
2930
from swsscommon.swsscommon import ConfigDBConnector
30-
from utilities_common.general import load_db_config
31+
from utilities_common.general import load_db_config, get_feature_state_data
3132
from tabulate import tabulate
3233

3334
BACKEND_ASIC_INTERFACE_NAME_PREFIX = 'Ethernet-BP'
@@ -69,8 +70,12 @@ class Lldpshow(object):
6970
self.lldp_interface[instance_num] += key + SPACE_TOKEN
7071

7172
# LLDP running in host namespace
72-
self.lldp_instance.append(LLDP_INSTANCE_IN_HOST_NAMESPACE)
73-
self.lldp_interface.append(LLDP_INTERFACE_LIST_IN_HOST_NAMESPACE)
73+
config_db = ConfigDBConnector(use_unix_socket_path=True, namespace=constants.DEFAULT_NAMESPACE)
74+
config_db.connect()
75+
global_scope, asic_scope = get_feature_state_data(config_db, "lldp")
76+
if global_scope == "True":
77+
self.lldp_instance.append(LLDP_INSTANCE_IN_HOST_NAMESPACE)
78+
self.lldp_interface.append(LLDP_INTERFACE_LIST_IN_HOST_NAMESPACE)
7479

7580
def get_info(self, lldp_detail_info, lldp_port):
7681
"""
@@ -85,7 +90,7 @@ class Lldpshow(object):
8590
elif lldp_interface_list == '':
8691
lldp_args = []
8792
else:
88-
lldp_args = [lldp_interface_list]
93+
lldp_args = lldp_interface_list.split(' ')
8994
lldp_cmd = ['sudo', 'docker', 'exec', '-i', 'lldp{}'.format(self.lldp_instance[lldp_instace_num]), 'lldpctl'] + lldp_args
9095
p = subprocess.Popen(lldp_cmd, stdout=subprocess.PIPE, text=True)
9196
(output, err) = p.communicate()

tests/lldp_test.py

+17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from click.testing import CliRunner
44
from utilities_common.general import load_module_from_source
5+
from importlib import reload
56

67
test_path = os.path.dirname(os.path.abspath(__file__))
78
modules_path = os.path.dirname(test_path)
@@ -83,6 +84,22 @@ def test_get_info(self):
8384
output = lldp.get_summary_output(lldp_detail_info=True)
8485
assert output.strip('\n') == expected_lldpctl_xml_output[0].strip('\n')
8586

87+
def test_get_info_multi_asic(self):
88+
from .mock_tables import mock_multi_asic
89+
from .mock_tables import dbconnector
90+
reload(mock_multi_asic)
91+
dbconnector.load_namespace_config()
92+
lldp = lldpshow.Lldpshow()
93+
from .mock_tables import mock_single_asic
94+
reload(mock_single_asic)
95+
dbconnector.load_namespace_config()
96+
lldp.lldp_instance = ['']
97+
lldp.lldpraw = expected_lldpctl_xml_output
98+
lldp.get_info(lldp_detail_info=True, lldp_port='Ethernet0')
99+
lldp.parse_info(lldp_detail_info=True)
100+
output = lldp.get_summary_output(lldp_detail_info=True)
101+
assert output.strip('\n') == expected_lldpctl_xml_output[0].strip('\n')
102+
86103
@classmethod
87104
def teardown_class(cls):
88105
print("TEARDOWN")

tests/mock_tables/config_db.json

+2
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,8 @@
848848
"FEATURE|lldp": {
849849
"state": "enabled",
850850
"auto_restart": "enabled",
851+
"has_global_scope": "False",
852+
"has_per_asic_scope": "True",
851853
"high_mem_alert": "disabled",
852854
"set_owner": "kube"
853855
},

utilities_common/general.py

+28-3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22
import importlib.util
33
import sys
44

5-
from sonic_py_common.multi_asic import is_multi_asic
5+
from sonic_py_common import multi_asic
66
from swsscommon import swsscommon
7+
FEATURE_TABLE = "FEATURE"
8+
FEATURE_HAS_PER_ASIC_SCOPE = 'has_per_asic_scope'
9+
FEATURE_HAS_GLOBAL_SCOPE = 'has_global_scope'
710

811
def load_module_from_source(module_name, file_path):
912
"""
@@ -25,7 +28,7 @@ def load_db_config():
2528
- database_global.json for multi asic
2629
- database_config.json for single asic
2730
'''
28-
if is_multi_asic():
31+
if multi_asic.is_multi_asic():
2932
if not swsscommon.SonicDBConfig.isGlobalInit():
3033
swsscommon.SonicDBConfig.load_sonic_global_db_config()
3134
else:
@@ -39,6 +42,28 @@ def get_optional_value_for_key_in_config_tbl(config_db, port, key, table):
3942
return None
4043

4144
value = info_dict.get(key, None)
42-
4345
return value
4446

47+
48+
def get_feature_state_data(config_db, feature):
49+
'''
50+
Get feature state from FEATURE table from CONFIG_DB.
51+
return global_scope, per_asic_scope
52+
- if feature state is disabled, return "False" for both global_scope and per_asic_scope
53+
- if is not a multi-asic, return feature state for global_scope ("True/False") and
54+
"False" for asic_scope
55+
'''
56+
global_scope = "False"
57+
asic_scope = "False"
58+
info_dict = {}
59+
info_dict = config_db.get_entry(FEATURE_TABLE, feature)
60+
if info_dict is None:
61+
return global_scope, asic_scope
62+
if multi_asic.is_multi_asic():
63+
if info_dict['state'].lower() == "enabled":
64+
global_scope = info_dict[FEATURE_HAS_GLOBAL_SCOPE]
65+
asic_scope = info_dict[FEATURE_HAS_PER_ASIC_SCOPE]
66+
else:
67+
if info_dict['state'].lower() == "enabled":
68+
global_scope = "True"
69+
return global_scope, asic_scope

0 commit comments

Comments
 (0)