from .host import HOST from collections import defaultdict def operational(): """Retrieve LLDP neighbor information and store in remote-systems-data under the correct port.""" # https://www.ieee802.org/1/files/public/YANGs/ieee802-types.yang # and subtypes are not supported in # https://github.com/lldpd/lldpd until v1.0.19 chassis_id_subtype_mapping = { #"unhandled": "chassis-component", "ifalias": "interface-alias", #"unhandled": "port-component", "mac": "mac-address", "ip": "network-address", "ifname": "interface-name", "local": "local" } # https://www.ieee802.org/1/files/public/YANGs/ieee802-types.yang # and subtypes are not supported in # https://github.com/lldpd/lldpd until v1.0.19 port_id_subtype_mapping = { "ifalias": "interface-alias", #"unhandled": "port-component", "mac": "mac-address", "ip": "network-address", "ifname": "interface-name", #"unhandled": "agent-circuit-id" "local": "local" } LLDP_MULTICAST_MAC = "01:80:C2:00:00:0E" port_data = defaultdict(lambda: {"remote-systems-data": [], "dest-mac-address": LLDP_MULTICAST_MAC}) data = HOST.run_json(["lldpcli", "show", "neighbors", "-f", "json"], {}) interfaces = data.get("lldp", {}).get("interface", []) if isinstance(interfaces, dict): interfaces = [interfaces] for iface_entry in interfaces: for iface_name, iface_data in iface_entry.items(): remote_index = int(iface_data.get("rid", 0)) time_mark = parse_time(iface_data.get("age")) chassis = iface_data.get("chassis", {}) chassis_id_type, chassis_id_value = extract_chassis_id(chassis, chassis_id_subtype_mapping) port_info = iface_data.get("port", {}) port_id_type = port_id_subtype_mapping.get(port_info.get("id", {}).get("type"), "unknown") port_id_value = port_info.get("id", {}).get("value", "") remote_entry = { "time-mark": time_mark, "remote-index": remote_index, "chassis-id-subtype": chassis_id_type, "chassis-id": chassis_id_value, "port-id-subtype": port_id_type, "port-id": port_id_value } port_data[iface_name]["remote-systems-data"].append(remote_entry) formatted_output = { "ieee802-dot1ab-lldp:lldp": { "port": [ { "name": port_name, "dest-mac-address": port_info["dest-mac-address"], "remote-systems-data": port_info["remote-systems-data"] } for port_name, port_info in port_data.items() if port_info["remote-systems-data"] ] } } return formatted_output def extract_chassis_id(chassis_block, subtype_mapping): if "id" in chassis_block: id_info = chassis_block["id"] return subtype_mapping.get(id_info.get("type"), "unknown"), id_info.get("value", "") for _, value in chassis_block.items(): if isinstance(value, dict) and "id" in value: id_info = value["id"] return subtype_mapping.get(id_info.get("type"), "unknown"), id_info.get("value", "") return "unknown", "" def parse_time(time_str): """Convert LLDP time format to seconds""" import re if time_str: match = re.search(r"(\d+)\s*day[s]*,\s*(\d+):(\d+):(\d+)", time_str) if match: days, hours, minutes, seconds = map(int, match.groups()) return days * 86400 + hours * 3600 + minutes * 60 + seconds return 0