Skip to content

Commit

Permalink
Use JSON for fetching LLDP information to avoid character encoding is…
Browse files Browse the repository at this point in the history
…sues
  • Loading branch information
lukasstockner committed Oct 30, 2023
1 parent b0851f1 commit 3662ee7
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 64 deletions.
55 changes: 26 additions & 29 deletions scripts/lldpshow
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import argparse
import re
import subprocess
import sys
from lxml import etree as ET
import json

from sonic_py_common import device_info
from swsscommon.swsscommon import ConfigDBConnector
Expand Down Expand Up @@ -79,15 +79,10 @@ class Lldpshow(object):
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
if not lldp_detail_info:
lldp_args = ['-f', 'xml']
elif lldp_interface_list == '':
lldp_args = []
else:
lldp_args = [lldp_interface_list]
lldp_cmd = ['sudo', 'docker', 'exec', '-i', 'lldp{}'.format(self.lldp_instance[lldp_instace_num]), 'lldpctl'] + lldp_args
p = subprocess.Popen(lldp_cmd, stdout=subprocess.PIPE, text=True)
# and in table format we will get json output
lldp_cmd = 'sudo docker exec -i lldp{} lldpctl '.format(self.lldp_instance[lldp_instace_num]) + (
'-f json' if not lldp_detail_info else lldp_interface_list)
p = subprocess.Popen(lldp_cmd, stdout=subprocess.PIPE, shell=True, text=True)
(output, err) = p.communicate()
## Wait for end of command. Get return returncode ##
returncode = p.wait()
Expand All @@ -111,8 +106,8 @@ class Lldpshow(object):
"""
capability = ""
for cap in capabs:
if cap.attrib['enabled'] == 'on':
captype = cap.attrib['type']
if cap['enabled']:
captype = cap['type']
if captype in self.ctags.keys():
capability += self.ctags[captype]
else:
Expand All @@ -126,31 +121,33 @@ class Lldpshow(object):
if lldp_detail_info:
return
for lldpraw in self.lldpraw:
neis = ET.fromstring(lldpraw.encode())
intfs = neis.findall('interface')
neis = json.loads(lldpraw)
intfs = neis['lldp']['interface']
for intf in intfs:
l_intf = intf.attrib['name']
l_intf = next(iter(intf.keys()))
if l_intf.startswith(BACKEND_ASIC_INTERFACE_NAME_PREFIX):
continue
remote_port = intf.find('port')
r_portid = remote_port.find('id').text
intf = intf[l_intf]

remote_port = intf['port']
r_portid = remote_port['id']['value']
key = l_intf + "#" + r_portid
self.lldpsum[key] = {}
self.lldpsum[key]['l_intf'] = l_intf
self.lldpsum[key]['r_portid'] = r_portid
chassis = intf.find('chassis')
capabs = chassis.findall('capability')
capab = self.parse_cap(capabs)
rmt_name = chassis.find('name')
if rmt_name is not None:
self.lldpsum[key]['r_name'] = rmt_name.text
else:
self.lldpsum[key]['r_name'] = ''
rmt_desc = remote_port.find('descr')
if rmt_desc is not None:
self.lldpsum[key]['r_portname'] = rmt_desc.text

chassis = intf['chassis']
if len(chassis) == 1:
rmt_name = next(iter(chassis.keys()))
chassis = chassis[rmt_name]
else:
self.lldpsum[key]['r_portname'] = ''
rmt_name = ''
capabs = chassis['capability']
if isinstance(capabs, dict):
capabs = [capabs]
capab = self.parse_cap(capabs)
self.lldpsum[key]['r_name'] = rmt_name
self.lldpsum[key]['r_portname'] = remote_port['descr']
self.lldpsum[key]['capability'] = capab

def sort_sum(self, summary):
Expand Down
113 changes: 78 additions & 35 deletions tests/lldp_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,41 +23,84 @@
'--------------------------------------------------\n'
'Total entries displayed: 2')

expected_lldpctl_xml_output = \
['<?xml version="1.0" encoding="UTF-8"?>\n\
<lldp label="LLDP neighbors">\n\
<interface label="Interface" name="Ethernet0" via="LLDP" rid="2" age="7 days, 22:11:33">\n\
<chassis label="Chassis">\n\
<id label="ChassisID" type="mac">00:00:00:00:00:01</id>\n\
<name label="SysName">dummy</name>\n\
<descr label="SysDescr">NA</descr>\n\
<mgmt-ip label="MgmtIP">00:00:00:00:00:00</mgmt-ip>\n\
<capability label="Capability" type="Bridge" enabled="on"/>\n\
<capability label="Capability" type="Router" enabled="on"/>\n\
<capability label="Capability" type="Wlan" enabled="off"/>\n\
<capability label="Capability" type="Station" enabled="off"/>\n\
</chassis>\n\
<port label="Port">\n\
<id label="PortID" type="mac">00:00:00:00:00:01</id>\n\
<descr label="PortDescr">First MAC</descr>\n\
<ttl label="TTL">120</ttl>\n\
</port>\n\
</interface>\n\
<interface label="Interface" name="Ethernet0" via="LLDP" rid="4" age="7 days, 22:11:34">\n\
<chassis label="Chassis">\n\
<id label="ChassisID" type="mac">00:00:00:00:00:02</id>\n\
<name label="SysName">dummy</name>\n\
<descr label="SysDescr">NA</descr>\n\
<mgmt-ip label="MgmtIP">00:00:00:00:00:00</mgmt-ip>\n\
<capability label="Capability" type="Router" enabled="on"/>\n\
</chassis>\n\
<port label="Port">\n\
<id label="PortID" type="mac">00:00:00:00:00:02</id>\n\
<descr label="PortDescr">Second MAC</descr>\n\
<ttl label="TTL">120</ttl>\n\
</port>\n\
</interface>\n\
</lldp>\n']
expected_lldpctl_xml_output = ['''
{
"lldp": {
"interface": [
{
"Ethernet0": {
"via": "LLDP",
"rid": "2",
"age": "7 days, 22:11:33",
"chassis": {
"dummy": {
"id": {
"type": "mac",
"value": "00:00:00:00:00:01"
},
"descr": "NA",
"mgmt-ip": "192.0.2.1",
"capability": [
{
"type": "Bridge",
"enabled": true
},
{
"type": "Router",
"enabled": true
},
{
"type": "Wlan",
"enabled": false
},
{
"type": "Station",
"enabled": false
}
]
}
},
"port": {
"id": {
"type": "mac",
"value": "00:00:00:00:00:01"
},
"descr": "First MAC",
"ttl": "120"
}
}
},
{
"Ethernet0": {
"via": "LLDP",
"rid": "4",
"age": "7 days, 22:11:34",
"chassis": {
"dummy": {
"id": {
"type": "mac",
"value": "00:00:00:00:00:02"
},
"descr": "NA",
"capability": {
"type": "Router",
"enabled": true
}
}
},
"port": {
"id": {
"type": "mac",
"value": "00:00:00:00:00:02"
},
"descr": "Second MAC",
"ttl": "120"
}
}
}
]
}
}''']

class TestLldp(object):
@classmethod
Expand Down

0 comments on commit 3662ee7

Please sign in to comment.