Skip to content

RFC conformance

Abdul Wasey edited this page Oct 2, 2026 · 5 revisions

RFC conformance

"Full BFD support" is not a single target: the BFD RFC family covers transports and deployments that are different protocols in practice. The honest deliverable is this matrix, with every deviation named. What this project aims to be complete for is everything bfdd can offload over the bffdp data-plane protocol, tested, with deviations justified. Today that is 5880 / 5881 / 5883 plus echo, demand mode and authentication with key rollover. Reviewed against the code on 2026-10-02.

RFC Title Status Notes
5880 BFD base implemented, four deviations, four notes Async mode, full state machine, poll/final, demand mode (with the s6.6 verification poll the RFC leaves optional), echo. Passive role, AdminDown and diag codes present. Authentication: simple password and keyed / meticulous keyed SHA1, with every key bfdd sends and its send and accept lifetimes, so a rollover happens in the data plane (s6.7.1); the replay window is forgotten after twice the detection time (s6.7). Deviation 1: keyed SHA1 computes an HMAC as bfdd does, not the RFC's plain SHA1 with the embedded key (FRR issue 23274). Deviation 2: keyed MD5 (types 2, 3) not implemented; bfdd maps no keychain to them. Deviation 4: a Final answers every Poll within a budget. Deviation 5: authenticated packets past a verify budget are dropped before the digest. Notes: fast-path replies go at the peer's pace; packets faster than the peer may send are dropped; echo is reflected within a budget per peer; demultiplexing on Your Discriminator alone is budgeted. See below.
5881 Single-hop IPv4/IPv6 implemented, one deviation GTSM on both planes, the control ports bound to the session type, one source port per session in 49152-65535 on both planes, demultiplexing on Your Discriminator once it is known, echo on 3785. Every control and echo packet is marked CS6, which no RFC requires and bfdd also does, so a switch that queues by DSCP keeps it out of a congested queue. Deviation 3: echo is sourced from the session's own address. See below.
5882 Generic application of BFD n/a Guidance for BFD clients; that is bfdd's side.
5883 Multihop implemented Port 4784, per-session minimum TTL, TTL restored on the reflected reply.
5884 BFD for MPLS LSPs not implemented Different encapsulation (MPLS echo bootstrap); not in bfdd's data plane.
5885 BFD for VCCV / pseudowires not implemented Same.
7130 micro-BFD on LAG members not implemented Would need per-member sessions on one address pair; the map key is address-only. Feasible later by keying on ifindex too.
7419 Common interval support partial The engine honours any interval; shipping the RFC's recommended set as presets is a configuration item, not an engine one.
7880 / 7881 / 7882 Seamless BFD (S-BFD) not implemented Reflector/initiator model with fixed discriminators. The XDP reflector is a natural fit for the S-BFD reflector role and is the first extension worth considering once bfdd's data plane can carry it.
8562 / 8563 Multipoint BFD not implemented, rejected on the wire The M bit is dropped (s6.8.6), multipoint being a different protocol.
8971 BFD for VXLAN not implemented Encapsulation.
9127 BFD YANG n/a Management; bfdd's.
9468 Unsolicited BFD not implemented Would need "accept a session from an unknown peer", which is exactly what the unknown-session drop removes by default. If wanted it is a per-interface allow rule, never a default.
6428 MPLS-TP CC/CV/RDI not implemented Different profile.
9355 OSPF BFD strict mode n/a A client behaviour (OSPF waits for BFD Up); ospfd's and bfdd's side.
9521 BFD for Geneve not implemented Encapsulation, as VXLAN.
9747 Unaffiliated BFD echo not implemented Echo with no control session behind it. The reflector answers echo only for a peer of an echo-active session (declined otherwise), which is what keeps it from being an open reflector; unaffiliated echo would need an explicit allow list, never a default.
9764 BFD encapsulated in large packets not implemented Padding a session's packets to probe path MTU. Padded packets are not tested here; the fast path's reply is the control packet's own length.

Deviation 1: keyed SHA1 is an HMAC

RFC 5880 s6.7.4 specifies keyed SHA1 as SHA1(packet with the key bytes embedded in the auth section). bfdd instead computes an HMAC-SHA1 over the packet with the auth digest zeroed. This engine matches bfdd, because bfdd is the control plane it serves and interop with it is the requirement that matters; a packet this engine accepts is exactly one bfdd would. The divergence from the letter of the RFC is bfdd's, and is filed upstream as FRR issue 23274.

Deviation 2: no keyed MD5

Types 2 (keyed MD5) and 3 (meticulous keyed MD5) exist in the RFC and in bfdd's enum, but bfdd maps no keychain algorithm to them, so nothing can drive them over the data plane. They are not implemented here. Simple password (type 1) and keyed / meticulous keyed SHA1 (types 4, 5) are.

Deviation 5: authenticated packets past a verify budget

RFC 5880 s6.7 has every authenticated packet verified. The program verifies at most one per half the session's Required Min RX, twice the rate the peer may legally send, with a burst of two so a Final that closely follows a regular packet still gets through. Past that, a packet is dropped before the digest and counted verify-limited, not counted for liveness. The budget reads only arrival time, never Poll or Final, which are not yet authenticated, and a failed verify gives its token back. A real peer never meets it: on the testbed, 2.76M authenticated packets in five minutes moved it by zero. It exists because the failure budget counts only bad digests, so without it a neighbour holding the key could make the program run a full HMAC per packet (see Security model).

Note: fast-path replies go at the peer's pace

The XDP program answers each control packet as it arrives, so it transmits at the peer's pace rather than on a timer of its own. RFC 5880 s6.8.7 bounds our rate by max(our Desired Min TX, the peer's Required Min RX), so the engine arms the fast path only while the peer's pace, max(its Desired Min TX, our Required Min RX), is no faster than that bound. Otherwise userspace transmits on its own jittered timer. The replies carry the peer's jitter rather than ours.

Deviation 3: echo is sourced from the session's own address

RFC 5881 s4 says the source of an echo packet MUST NOT be on the subnet of the interface it leaves by, so the neighbour's forwarding does not answer with a redirect. The engine sends a self-addressed echo from the session's local address, as bfdd does. Echo is sent only while the peer advertises a nonzero Required Min Echo RX (RFC 5880 s6.8.9), and never on multihop sessions.

Deviation 4: Finals within a budget

RFC 5880 s6.8.7 says a Final answers a Poll "without respect to the transmission timer or any other transmission limitations". The program answers every Poll, however closely they follow each other, up to 32 per session per 100ms; past that it drops them. A real Poll sequence is a handful of packets at the peer's interval, so this only ever meets a forger, who could otherwise have us transmit one Final per frame of a flood.

Note: packets faster than the peer may send

RFC 5880 s6.8.7 bars the peer from sending faster than our Required Min RX. The program takes a session's packets at most twice that fast: a packet closer than half the interval to the last one taken still counts for liveness, but is neither answered nor passed up, and counts as too-fast. The peer's jitter can shorten an interval by a quarter at most, so a real peer never meets this. Poll and Final packets are exempt, within the budget above. On an authenticated session the verify budget (Deviation 5) comes first, so there a packet that fast is dropped before the digest and not counted for liveness, Poll and Final included past the burst of two.

Note: echo within a budget per peer

RFC 5880 s6.8.9 bars a peer from sending echo faster than our Required Min Echo RX. The program reflects a known peer's echo up to four times that rate plus 16 per 100ms, and drops the rest (echo-ratelimited), so a forger cannot overflow the transmit ring through the reflector. UDP/3785 from anyone not a peer of an echo-active session is never reflected (declined).

Note: demultiplexing on Your Discriminator is budgeted

RFC 5880 s6.3 has a packet from an unknown address pair matched to its session by Your Discriminator, for a peer whose address changed. The program hands such packets to the engine at most 256 per 100ms per CPU (moved-ratelimited); past that, a forger who has seen a discriminator could otherwise run the engine flat. A real address move is a handful of packets.

Clone this wiki locally