-
Notifications
You must be signed in to change notification settings - Fork 819
Changes to make lldp show command for multi-npu platforms. #914
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,30 +25,65 @@ import re | |
| import sys | ||
| import xml.etree.ElementTree as ET | ||
| from tabulate import tabulate | ||
| import argparse | ||
| import sonic_device_util | ||
| from swsssdk import ConfigDBConnector, SonicDBConfig | ||
| BACKEND_ASIC_INTERFACE_NAME_PREFIX = 'Ethernet-BP' | ||
|
|
||
| class Lldpshow(object): | ||
| def __init__(self): | ||
| self.lldpraw = None | ||
| self.lldpraw = [] | ||
| self.lldpsum = {} | ||
| self.lldp_interface = [] | ||
| self.lldp_instance = [] | ||
| self.err = None | ||
| ### So far only find Router and Bridge two capabilities in lldpctl, so any other capacility types will be read as Other | ||
| ### if further capability type is supported like WLAN, can just add the tag definition here | ||
| self.ctags = {'Router': 'R', 'Bridge': 'B'} | ||
| SonicDBConfig.load_sonic_global_db_config() | ||
|
|
||
| def get_info(self): | ||
| # For multi-npu platforms we will get only front-panel interface to display | ||
| namespaces = sonic_device_util.get_all_namespaces() | ||
| per_npu_configdb = {} | ||
| for instance_num, front_asic_namespaces in enumerate(namespaces['front_ns']): | ||
| per_npu_configdb[front_asic_namespaces] = ConfigDBConnector(use_unix_socket_path=True, namespace=front_asic_namespaces) | ||
| per_npu_configdb[front_asic_namespaces].connect() | ||
| self.lldp_interface.append('') | ||
| self.lldp_instance.append(instance_num) | ||
| keys = per_npu_configdb[front_asic_namespaces].get_keys("PORT") | ||
| for key in keys: | ||
| if key.startswith(BACKEND_ASIC_INTERFACE_NAME_PREFIX): | ||
| continue | ||
| self.lldp_interface[instance_num] += key + ' ' | ||
|
|
||
| # LLDP running in host namespace | ||
| self.lldp_instance.append('') | ||
| self.lldp_interface.append('') | ||
jleveque marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| def get_info(self, lldp_detail_info, lldp_port): | ||
| """ | ||
| use 'lldpctl -f xml' command to gather local lldp detailed information | ||
| use 'lldpctl' command to gather local lldp detailed information | ||
| """ | ||
| lldp_cmd = 'lldpctl -f xml' | ||
| p = subprocess.Popen(lldp_cmd, stdout=subprocess.PIPE, shell=True) | ||
| (output, err) = p.communicate() | ||
| ## Wait for end of command. Get return returncode ## | ||
| returncode = p.wait() | ||
| ### if no error, get the lldpctl result | ||
| if returncode == 0: | ||
| self.lldpraw = output | ||
| else: | ||
| self.err = err | ||
| for lldp_instace_num in range(len(self.lldp_instance)): | ||
| lldp_interface_list = lldp_port if lldp_port is not None else self.lldp_interface[lldp_instace_num] | ||
| # In detail mode we will pass interface list (only front ports) and get O/P as plain text | ||
| # and in table format we will get xml output | ||
| lldp_cmd = 'sudo docker exec -it lldp{} lldpctl '.format(self.lldp_instance[lldp_instace_num]) + ('-f xml' if not lldp_detail_info else lldp_interface_list) | ||
| p = subprocess.Popen(lldp_cmd, stdout=subprocess.PIPE, shell=True) | ||
| (output, err) = p.communicate() | ||
| ## Wait for end of command. Get return returncode ## | ||
| returncode = p.wait() | ||
| ### if no error, get the lldpctl result | ||
| if returncode == 0: | ||
| # ignore the output if given port is not present | ||
| if lldp_port is not None and lldp_port not in output: | ||
| continue | ||
| self.lldpraw.append(output) | ||
| else: | ||
| self.err = err | ||
|
|
||
| if self.err: | ||
| self.lldpraw = [] | ||
|
|
||
| def parse_cap(self, capabs): | ||
| """ | ||
|
|
@@ -64,15 +99,19 @@ class Lldpshow(object): | |
| capability += 'O' | ||
| return capability | ||
|
|
||
| def parse_info(self): | ||
| def parse_info(self, lldp_detail_info): | ||
| """ | ||
| Parse the lldp detailed infomation into dict | ||
| """ | ||
| if self.lldpraw is not None: | ||
| neis = ET.fromstring(self.lldpraw) | ||
| if lldp_detail_info: | ||
| return | ||
| for lldpraw in self.lldpraw: | ||
| neis = ET.fromstring(lldpraw) | ||
| intfs = neis.findall('interface') | ||
| for intf in intfs: | ||
| l_intf = intf.attrib['name'] | ||
| if l_intf.startswith(BACKEND_ASIC_INTERFACE_NAME_PREFIX): | ||
| continue | ||
| self.lldpsum[l_intf] = {} | ||
| chassis = intf.find('chassis') | ||
| capabs = chassis.findall('capability') | ||
|
|
@@ -97,11 +136,17 @@ class Lldpshow(object): | |
| return sorted(summary, key=alphanum_key) | ||
|
|
||
|
|
||
| def display_sum(self): | ||
| def display_sum(self, lldp_detail_info): | ||
| """ | ||
| print out summary result of lldp neighbors | ||
| """ | ||
| if self.lldpraw is not None: | ||
| # In detail mode output is plain text | ||
| if self.lldpraw and lldp_detail_info: | ||
| lldp_output = '' | ||
| for lldp_detail_output in self.lldpraw: | ||
| lldp_output += lldp_detail_output | ||
| print (lldp_output) | ||
| elif self.lldpraw: | ||
| lldpstatus = [] | ||
| print ('Capability codes: (R) Router, (B) Bridge, (O) Other') | ||
| header = ['LocalPort', 'RemoteDevice', 'RemotePortID', 'Capability', 'RemotePortDescr'] | ||
|
|
@@ -115,11 +160,31 @@ class Lldpshow(object): | |
| print ('Error:',self.err) | ||
|
|
||
| def main(): | ||
| parser = argparse.ArgumentParser(description='Display the LLDP neighbors', | ||
| version='1.0.0', | ||
| formatter_class=argparse.RawTextHelpFormatter, | ||
| epilog=""" | ||
| Examples: | ||
| lldpshow | ||
| lldpshow -d | ||
| lldpshow -d -p Ethernet0 | ||
| """) | ||
|
|
||
| parser.add_argument('-d', '--detail', action='store_true', help='LLDP neighbors detail information', default=False) | ||
| parser.add_argument('-p', '--port', type=str, help='LLDP neighbors detail information for given port', default=None) | ||
| args = parser.parse_args() | ||
|
|
||
| lldp_detail_info = args.detail | ||
| lldp_port = args.port | ||
|
|
||
| if lldp_port and not lldp_detail_info: | ||
| parser.error('-d is required when -p is set.') | ||
|
||
|
|
||
| try: | ||
| lldp = Lldpshow() | ||
| lldp.get_info() | ||
| lldp.parse_info() | ||
| lldp.display_sum() | ||
| lldp.get_info(lldp_detail_info, lldp_port) | ||
| lldp.parse_info(lldp_detail_info) | ||
| lldp.display_sum(lldp_detail_info) | ||
| except Exception as e: | ||
| print(e.message, file=sys.stderr) | ||
| sys.exit(1) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.