From 50150768e14e85fbae1b4cd3c253e8ab68bde906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Jonas=20S=C3=A4mann?= Date: Wed, 20 Jan 2021 05:22:40 +0100 Subject: [PATCH] Add method get_lldp_neighbors_detail() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provide a show lldp neighbors detail parser for gathering neighbor data from VyOS and EdgeOS routers using NAPALM Signed-off-by: Jan-Jonas Sämann --- napalm_vyos/vyos.py | 64 +++++++++++++++++++ .../normal/expected_result.json | 1 + .../normal/show_lldp_neighbors_detail.text | 38 +++++++++++ 3 files changed, 103 insertions(+) create mode 100644 test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors_detail.text diff --git a/napalm_vyos/vyos.py b/napalm_vyos/vyos.py index 23e3bde..021d0fe 100644 --- a/napalm_vyos/vyos.py +++ b/napalm_vyos/vyos.py @@ -608,6 +608,70 @@ def _get_interface(match): for match in re.finditer(pattern, output) } + def get_lldp_neighbors_detail(self, interface=''): + """ + Parse LLDP neighbors + 'show lldp neighbor detail' output example: See unit tests + """ + output = self.device.send_command("show lldp neighbors detail") + + if 'Invalid command' in output: + raise ValueError("Command not supported by network device") + + ifiter = re.finditer(r'(?s)Interface: +(?P\S+), [^\n]+\n(?P.+?)\n--', output) + neighbor_data = [ + {'parent_interface': ifi.group('name'), 'raw': ifi.group('raw')} + for ifi in ifiter if not interface or interface == ifi.group('name') + ] + del ifiter, output + + n_pattern = r'''(?s) +ChassisID: +mac +(?P\S+) + +SysName: +(?P\S+) + +SysDescr: +(?P.+?) + .+? + +PortID: +(?Pmac|ifname) +(?P\S+) + +PortDescr: +(?P.+?) + .+?''' + caps_pattern = r' +Capability: +(?P\S+)(?:, +(?P\S+))?\n' + + for neigh in neighbor_data: + nb_data = re.search(n_pattern, neigh['raw']) + if not nb_data: + continue + neigh['remote_chassis_id'] = nb_data.group('chassisid') + neigh['remote_system_name'] = nb_data.group('sysname') + neigh['remote_system_description'] = nb_data.group('sysdescr') + + # Neighbors with PortID type mac tend to have ifname in PortDescr + if nb_data.group('porttype') == 'mac': + neigh['remote_port'] = nb_data.group('portdescr') + neigh['remote_port_description'] = nb_data.group('portid') + else: + neigh['remote_port'] = nb_data.group('portid') + neigh['remote_port_description'] = nb_data.group('portdescr') + + + nb_data = list(re.finditer(caps_pattern, neigh['raw'])) + if nb_data: + neigh['remote_system_capab'] = [ + str(nb_item.group('capab')).lower() + for nb_item in nb_data + ] + neigh['remote_system_enable_capab'] = [ + str(nb_item.group('capab')).lower() + for nb_item in nb_data if nb_item.group('state') == 'on' + ] + del neigh['raw'] + + # Neighbors, grouped by interface, filtered by interface arg + return { + ifneigh['parent_interface']: [ + neigh for neigh in neighbor_data + if ifneigh['parent_interface'] == neigh['parent_interface'] + ] + for ifneigh in neighbor_data + } + def get_interfaces_counters(self): # 'rx_unicast_packet', 'rx_broadcast_packets', 'tx_unicast_packets', # 'tx_multicast_packets' and 'tx_broadcast_packets' are not implemented yet diff --git a/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/expected_result.json b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/expected_result.json new file mode 100644 index 0000000..b084df7 --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/expected_result.json @@ -0,0 +1 @@ +{"eth1": [{"parent_interface": "eth1", "remote_chassis_id": "56:98:09:09:09:09", "remote_system_name": "pve", "remote_system_description": "Debian GNU/Linux 10 (buster) Linux 5.4.78-2-pve #1 SMP PVE 5.4.78-2 (Thu, 03 Dec 2020 14:26:17 +0100) x86_64", "remote_port": "vmbr1", "remote_port_description": "16:44:c2:e1:7e:cf", "remote_system_capab": ["bridge", "router", "wlan", "station"], "remote_system_enable_capab": ["bridge"]}], "eth5": [{"parent_interface": "eth5", "remote_chassis_id": "50:f7:22:01:01:00", "remote_system_name": "cisco.switch", "remote_system_description": "Cisco IOS Software, C2960L Software (C2960L-UNIVERSALK9-M), Version 15.2(5c)E, RELEASE SOFTWARE (fc1)\nTechnical Support: http://www.cisco.com/techsupport\nCopyright (c) 1986-2016 by Cisco Systems, Inc.\nCompiled Tue 18-Oct-16 23:59 by prod_rel_team", "remote_port": "Gi0/25", "remote_port_description": "GigabitEthernet0/25", "remote_system_capab": ["bridge", "router"], "remote_system_enable_capab": ["bridge"]}]} diff --git a/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors_detail.text b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors_detail.text new file mode 100644 index 0000000..91cb541 --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors_detail.text @@ -0,0 +1,38 @@ +------------------------------------------------------------------------------- +LLDP neighbors: +------------------------------------------------------------------------------- +Interface: eth1, via: LLDP, RID: 1, Time: 0 day, 00:00:14 + Chassis: + ChassisID: mac 56:98:09:09:09:09 + SysName: pve + SysDescr: Debian GNU/Linux 10 (buster) Linux 5.4.78-2-pve #1 SMP PVE 5.4.78-2 (Thu, 03 Dec 2020 14:26:17 +0100) x86_64 + MgmtIP: 10.0.0.2 + MgmtIP: fe80::baac:6fff:fefe:1337 + Capability: Bridge, on + Capability: Router, off + Capability: Wlan, off + Capability: Station, off + Port: + PortID: mac 16:44:c2:e1:7e:cf + PortDescr: vmbr1 + TTL: 120 +------------------------------------------------------------------------------- +Interface: eth5, via: LLDP, RID: 1, Time: 4 days, 04:46:13 + Chassis: + ChassisID: mac 50:f7:22:01:01:00 + SysName: cisco.switch + SysDescr: Cisco IOS Software, C2960L Software (C2960L-UNIVERSALK9-M), Version 15.2(5c)E, RELEASE SOFTWARE (fc1) +Technical Support: http://www.cisco.com/techsupport +Copyright (c) 1986-2016 by Cisco Systems, Inc. +Compiled Tue 18-Oct-16 23:59 by prod_rel_team + MgmtIP: 10.0.0.3 + Capability: Bridge, on + Capability: Router, off + Port: + PortID: ifname Gi0/25 + PortDescr: GigabitEthernet0/25 + PMD autoneg: supported: no, enabled: yes + Adv: 100Base-X, HD: no, FD: yes + MAU oper type: 1000BaseSXFD - Fiber over short-wavelength laser, full duplex mode + VLAN: 1, pvid: yes +-------------------------------------------------------------------------------