Repository navigation
(17a) net: LLDP TLV framing and the mandatory TLVs - #1906
Draft
daniel-noland wants to merge 2 commits into
Draft
daniel-noland wants to merge 2 commits into
daniel-noland wants to merge 2 commits into
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Comment |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
daniel-noland
force-pushed
the
pr/daniel-noland/lldp
branch
from
October 16, 2026 04:23
18c3a91 to
acc9d42
Compare
This was referenced Oct 16, 2026
daniel-noland
force-pushed
the
pr/daniel-noland/capture
branch
from
October 16, 2026 05:47
ef57775 to
c7bc0e6
Compare
daniel-noland
force-pushed
the
pr/daniel-noland/lldp
branch
from
October 16, 2026 05:47
acc9d42 to
8ad4269
Compare
The first of three changes adding `net::lldp`: the TLV framing, the octet strings and network addresses the identifiers are built from, and the three records every LLDPDU starts with (chassis ID, port ID, time to live), plus the end marker. The optional TLVs and the LLDPDU itself follow. `net::lldp` is a type safe parser and builder for LLDP data units, so that reading what a neighbour advertises and crafting what we advertise back does not come down to hand rolled offsets over a TLV stream. This lives in `net` rather than in a crate of its own because it needs pieces that are deliberately crate private: `LengthError`'s fields have no public constructor, so an out of crate `Parse` impl cannot report a truncated buffer at all. It also reuses `Mac`, the IP address types, `Vid` and the bolero scaffolding instead of duplicating them. Splitting it out later is mechanical; starting outside would have forced `net` to widen its public API first. The shape of an LLDPDU is encoded in the types rather than checked at run time, per the "enforce invariants at compile time" guidance in development/code/README.md. 802.1AB requires a chassis ID, a port ID and a time to live, in that order, then optional TLVs, then an end marker, so `Lldpdu` holds the mandatory three in named fields and emits the marker itself. Likewise a subtype is implied by the enum variant rather than stored beside the value it describes, `Octets<MIN, MAX>` carries each field's length bounds in its type, and the escape hatches for unmodelled TLVs refuse anything with a structured representation. That last point is what keeps the mapping between octets and values one to one in both directions. Every level property tests it; the LLDPDU level does so both for arbitrary input and for single octet mutations of a valid frame, since random bytes rarely reach past the first TLV. Reserved values are rejected, following `InvalidVni::ReservedZero`, but where the standard is soft the parser stays permissive: unknown TLV types, address families and OUIs round trip verbatim, and reserved capability bits are preserved rather than masked. Serde routes through the checked constructors, so deserialization is not a back door around the invariants parsing enforces. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Show chassis and port IDs, network addresses and LLDP octet strings in a form a person can read: octets as text when they are printable UTF-8 and as colon-separated hex otherwise, since LLDP carries both names meant to be read and identifiers that are not, often under the same TLV type; addresses as IPs; identifiers as their value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Daniel Noland <daniel@githedgehog.com>
daniel-noland
force-pushed
the
pr/daniel-noland/lldp
branch
from
October 16, 2026 08:43
8ad4269 to
7897c2f
Compare
daniel-noland
force-pushed
the
pr/daniel-noland/capture
branch
from
October 16, 2026 08:43
c7bc0e6 to
4207243
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.
Native LLDP for the gateway. The dataplane owns its NICs, so nothing else can speak LLDP for them, and
lldpd/lldpadare hostile to automation. LLDP itself is small, so the dataplane transmits and receives it.This used to be one PR. It is now a stack of seven, each building on the one before:
net: TLV framing and the mandatory TLVs ← this PRnet: the optional TLVsnet: the LLDPDU andHeaders::parselldp: the transmitter and the neighbour tabledataplane: advertise on every portdataplane: hear neighbours,show lldp neighbors, all-multicastStacked on (16) #1905, capture. (18) #1907, rate limiting, and (19) #1919, traffic protection, build on top.
This PR: TLV framing and the mandatory TLVs
The first of three PRs adding
net::lldp, a type-safe, byte-lossless parser and builder for LLDP data units.tlv): the 7-bit type and 9-bit length header, andRawTlv.octets):Octets<MIN, MAX>carries each field's length bounds in its type.address), shared by the chassis ID, port ID and management address.Displayfor the identifiers, whichshow lldp neighborsuses later.The design rules, which hold for the whole module:
It lives in
netrather than a crate of its own because it needs crate-private pieces (LengthErrorhas no public constructor) and reusesMac, the IP types and the bolero scaffolding.Doc comments that mention
Lldpduare plain code spans here.Lldpduarrives in the third PR, which turns them into links.Testing
Property tests for every type: round trip, parse ∘ deparse = identity, and rejection of reserved values.
🤖 Generated with Claude Code