Repository navigation
Conversation
7 tasks
berendt
force-pushed
the
implement/issue-2877-report-lldp-cabling-check
branch
from
November 13, 2026 13:08
448fd30 to
cf6b4e8
Compare
The cabling check needs the neighbours of the switches as well as those of the nodes. The SONiC collector gains the section lldp. It dumps LLDP_ENTRY_TABLE from APPL_DB. On Enterprise SONiC 4.4 and 4.5 the table lists the management port next to the front-panel ports. lldpctl inside the lldp container is only run when the table does not list eth0: it is the fallback for a switch without the table, or with one that only has front-panel ports. The key of an entry is the port name on Enterprise SONiC 4.4 and the port name followed by the source MAC address of the neighbour on 4.5, which keeps several neighbours per port. Both are read, in the collector and in the parser. parse_lldp turns the table into the same neighbour records as lldpctl JSON, translating the numeric LLDP-MIB subtypes into the names lldpctl uses. The records have no age: lldp_rem_time_mark is the uptime of lldpd at which the neighbour was learned on Enterprise SONiC, not the time since then. Ports the table does not list are filled in from lldpctl. A switch where neither source can be read raises an error with the reason, so that it is reported as a failed device and not as a switch without neighbours. The switch fixture gains its LLDP data, and a capture of the second leaf of the pair, running Enterprise SONiC 4.4.1, is added. Tests: the collector section with its fallbacks, and the parser for both key formats, the merge with lldpctl, the failure messages, and both ends of a captured cable. Part of #2877. Assisted-by: Claude:claude-fable-5-2 Signed-off-by: Christian Berendt <berendt@osism.tech>
Resolving an LLDP neighbour to NetBox needs devices the report did not select: the documented peers of the selected interfaces, and devices a neighbour announces by name. fetch_devices() loads devices by ID in chunks. find_devices() looks them up by name, ignoring case, and also tries the name without its domain, because a device can announce itself fully qualified while NetBox holds the short name. sonic_alias_index() maps the vendor aliases of a HWSKU port config to SONiC port names, for switches that advertise twentyFiveGigE1 instead of the NetBox name. Tests: chunking, the name variants, and the alias index against the port config files of the repository. Part of #2877. Assisted-by: Claude:claude-fable-5-2 Signed-off-by: Christian Berendt <berendt@osism.tech>
NetBox holds the intended cabling and the devices know their neighbours. cabling brings the two together, as a pure function over plain data without SSH or pynetbox. Directory resolves what a neighbour announces. The device is found by system name, case-insensitively and without the domain. A node does not always announce its device name: its host name can differ, it can still have the default name of its image, and the LLDP agent of a NIC can answer in place of the host, with the name of the NIC. The fallbacks are therefore the port ID when it is a MAC address, which is what lldpd sends and which names one interface, then the management addresses, then the chassis ID. A MAC address that NetBox documents on several devices identifies none of them: the USB host interface of a BMC has the same address on every node of a model, and lldpd uses it as chassis ID on some. The port is found by interface name or label, through the HWSKU port config for a SONiC port name or vendor alias, by MAC address, or through the live interfaces of a device that was queried as well. RouterOS announces a bridge port as bridge/ether9; it is compared by the name of the port. compare() then gives every port a result: ok, missing, no-lldp, wrong-port, wrong-device, unexpected, unmapped or stale. The expected peer is the far end of the cable path, so a cable through a patch panel is compared with the device behind it. A management interface without a live counterpart is the BMC of a node and is skipped; its cable is checked from the switch it is plugged into. Two passes look across devices. A port that sees its documented peer becomes one-sided when the peer was queried and sees something else. Mismatches are searched for exchanged cables: when the port that owns the cable seen here in turn sees a cable owned by another mismatch, and the chain leads back, all its members are swapped and name their partners. That covers two ports crossed on one node, the cables of two nodes crossed on a switch, and longer rotations. neighbour_listing() is the variant without NetBox. It keeps the two checks that need no source of truth, no-lldp and one-sided. Tests: the result matrix for single ports, swaps within one device, across devices and as a rotation, both passes with and without a queried peer, management interfaces, and every resolution rule. The captures of a node and of the two switches it is cabled to are compared from both ends. Part of #2877. Assisted-by: Claude:claude-fable-5-2 Signed-off-by: Christian Berendt <berendt@osism.tech>
Cabling errors are the most common fault after racking and after hardware replacement, and they are slow to find: two swapped cables still give link on both ports. osism report lldp printed the raw neighbours of the nodes, to be read next to NetBox by hand. The command now collects the neighbours of nodes and SONiC switches in parallel and compares them with the cabling in NetBox. Every port with a cable in NetBox or a live neighbour gets a result and a hint, so a missing cable, a cable in the wrong port and swapped cables are visible at a glance. Devices are selected with the options of report transceiver, and only selected devices are logged in to; documented peers outside the selection are read from NetBox. The management port of a switch is part of the check unless --no-mgmt is given. --problems, --result and --interface filter the rows, and the output is a table, CSV or JSON. --strict exits with 1 when a device failed or a port has a result other than ok, whatever the filters hide. --no-compare, and a setup without NetBox, give the neighbour listing with the columns the command had before, now also for switches. The command exits with 1 when nothing was selected, where it used to return success for an empty inventory. A node without a running lldpd is reported as a failed device instead of as a host without neighbours. Tests: the existing lldp tests run against the new collection path and keep their assertions; the failure summary names devices instead of hosts. New tests cover the comparison, the swap across nodes, the management port, the filters and formats, --strict, failed devices, the lookup of unknown neighbours and the listing without NetBox. Closes #2877 Assisted-by: Claude:claude-fable-5-2 Signed-off-by: Christian Berendt <berendt@osism.tech>
berendt
force-pushed
the
implement/issue-2877-report-lldp-cabling-check
branch
from
November 13, 2026 13:11
cf6b4e8 to
b358370
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request turns
osism report lldpinto a cabling check. The command collects the LLDP neighbours of nodes and SONiC switches live over SSH and compares them with the cabling documented in NetBox. Every port gets a result, so a missing cable, a cable in the wrong port and swapped cables are visible at a glance.It is the third of a stack of three and builds on #2880. The base branch of this pull request is the branch of #2880.
Commits
Collect LLDP neighbours on SONiC switches: the SONiC collector readsLLDP_ENTRY_TABLEfromAPPL_DBand falls back tolldpctlin thelldpcontainer. Both are normalised into the neighbour records already used for nodes.Add NetBox device lookups and the vendor alias index: lookups for the documented peers and for neighbours that announce a name NetBox knows, and the translation of vendor port aliases.Add the comparison of LLDP neighbours with NetBox cabling:osism/utils/hardware/cabling.py, a pure function over plain data. It resolves LLDP identities to NetBox devices and interfaces, gives every port a result, and findsone-sidedlinks and swapped cables across the whole selection.Extend report lldp into a cabling check: the reworkedLldpcommand.Behavior
ok,missing,no-lldp,wrong-port,wrong-device,swapped,unexpected,one-sided,unmappedandstale, each with a hint.swappedon both ports with the partner named, within one device and across devices. Longer rotations are found as well.--no-mgmtleaves allmgmt_onlyinterfaces out.--problems,--resultand--interfacefilter the rows.--strictexits with 1 when a device failed or a port has a result other thanok, whatever the filters hide.--no-compare, and a setup without NetBox, give the neighbour listing with the columns the command had before, now also for switches.no-lldpandone-sidedstay active there.Changes for existing users
--no-comparegives the previous listing.lldpdis reported as a failed device, not as a host without neighbours.Failed to query N device(s): name (reason)instead ofN host(s).Decisions taken while implementing
--long, also when its link is up. The USB NIC of a BMC is such a port and would show up in every run.unexpected. The issue lists such ports but names no result for them.unmapped.one-sided.Verification
The unit tests of this revision run in CI; they were not run locally. Every commit of the stack was checked with
black --checkandflake8, and all test modules import at every commit.mypy --ignore-missing-importsreports nothing in the new modules.The parsers were run against the complete captures before the fixtures were derived from them, and the expectations of the new tests were taken from those runs.
Checked against captures
The captures of #2884 hold both ends of several cables: nodes and the two leaf switches they are cabled to, the link between the leaf switches, and the management ports towards a RouterOS switch. The points the issue lists to confirm on real hardware:
local, also for breakout ports (Eth1/1/1). The port description is the SONiC name. The management port announceseth0.lldpdon the nodes: the MAC address of the port, with the name of the port as description. The chassis ID is the MAC address of some interface of the node.LLDP_ENTRY_TABLE: the field names are the ones the parser reads, and the neighbour ofeth0is listed. The key is the port name on Enterprise SONiC 4.4.1 and the port name followed by the source MAC address of the neighbour on 4.5.2. Both are read. Before this, every neighbour of a 4.5.2 switch was reported a second time, under a port name that does not exist.What the captures showed beyond that, and what changed because of it:
lldp_rem_time_markis not the age of a neighbour on Enterprise SONiC, but the uptime oflldpdat which it was learned. Neighbours read from the table have no age.docker0as management address. A MAC address that NetBox documents on several devices is not used to identify a device.bridge/ether9. It is compared by the name of the port.A test compares the captures of a node and of both leaf switches against a matching NetBox description: every cable is
okfrom both ends, including the management ports.Not verified
lldpdannounces for bond members is still open.lldpctlin thelldpcontainer was not needed on the captured switches. The capture of the 4.5.2 switch contains its output, which the parser reads.Closes #2877
Assisted-by: Claude:claude-fable-5-2