Repository navigation
bfd
Pre-Alpha. This page describes behavior that may change.
Ze includes a full BFD implementation (RFC 5880/5881/5882/5883) as a plugin. BFD detects forwarding failures in tens to hundreds of milliseconds, one or two orders of magnitude faster than BGP keepalives. BGP peers opt in by adding a bfd { } block in their connection config.
| Scenario | BFD value |
|---|---|
| eBGP transit session | Sub-second failure detection without waiting for BGP hold time (default 90 s). |
| iBGP over a loopback | Multi-hop BFD can accelerate route reconvergence if the IGP alone is too slow. |
| Static route to a gateway | Withdraw the route when the gateway stops forwarding, even if the physical link is up. |
Do not use BFD between two routers where the IGP already runs fast BFD. The redundant sessions double the packet rate and can amplify instability.
Profiles are named bundles of timer and feature parameters. Sessions reference a profile by name.
bfd {
profile fast-link {
desired-min-tx-us 50000; # 50 ms
required-min-rx-us 50000;
detect-multiplier 3; # 150 ms detection time
}
profile ibgp-loopback {
desired-min-tx-us 300000;
required-min-rx-us 300000;
detect-multiplier 5;
}
}
All interval fields are in microseconds (RFC 5880 convention).
| Leaf | Range | Default | Meaning |
|---|---|---|---|
desired-min-tx-us |
1 - 4294967295 | 300000 | Local target transmit rate. |
required-min-rx-us |
0 - 4294967295 | 300000 | Minimum inter-packet gap the local end can handle. |
detect-multiplier |
1 - 255 | 3 | Consecutive missed packets that trigger Down. |
passive |
boolean | false | Wait for the peer's first packet instead of transmitting from creation. A single-hop session using a passive profile is refused (RFC 5881 Section 3 requires both ends to be Active): a configured session at load, a BGP peer or static next-hop naming the profile at commit. |
Profiles can carry an auth { ... } block for RFC 5880 S6.7 authentication. Five types are supported: simple-password, keyed-md5, meticulous-keyed-md5, keyed-sha1, and meticulous-keyed-sha1.
For simple-password, RFC 5880 Section 6.7.2 bounds the password at 1 to 16 bytes, and Ze enforces that bound. The Auth Len field is the password length plus 3.
bfd {
persist-dir "/var/lib/ze/bfd";
profile authenticated-fast {
desired-min-tx-us 50000;
required-min-rx-us 50000;
detect-multiplier 3;
auth {
type meticulous-keyed-sha1;
key-id 7;
secret "BFD-SHARED-SECRET-V1";
}
}
}
A keyed secret is at most 16 bytes for keyed-md5 and meticulous-keyed-md5 (RFC 5880 Section 6.7.3) and at most 20 bytes for keyed-sha1 and meticulous-keyed-sha1 (Section 6.7.4). A longer secret is refused, never truncated.
The secret takes one of two forms, and a profile names exactly one. secret is an ASCII string whose bytes are the key. secret-hex is any binary string in hexadecimal, two digits per byte with no 0x prefix, so a key holding a zero byte or a byte above 0x7F can be configured. The length limits apply to the decoded bytes, so a 20-byte keyed-sha1 key is 40 hex digits. ze config validate refuses an odd digit count, a non-hex character, and a profile naming both forms or neither. Both forms are redacted from ze config show.
auth {
type keyed-sha1;
key-id 7;
secret-hex "00ff4142434445464748494a4b4c4d4e4f5051ff";
}
A received Sequence Number must lie within 3 x Detect Mult ahead of the last one accepted, and strictly ahead of it for the meticulous types; anything outside that window is discarded as a replay. The first packet of a session sets that floor before its digest is checked, in the order RFC 5880 Section 6.7.3 gives. Ze does not yet clear the floor after two Detection Times of silence (RFC 5880 Section 6.8.1), so a floor stays until the session is recreated.
A non-empty persist-dir turns on persistence of the last TX sequence per session. The value is stored under meta/bfd/auth/<session> in the daemon's database/ tree; the path itself is kept only as an opt-in switch and does not select a second directory. A Meticulous session then resumes above its saved sequence floor after a restart. Without it, the session re-synchronises with the peer's replay window.
Profiles may carry an echo { desired-min-echo-tx-us N } block for RFC 5880 S6.4 Echo mode. Echo mode is valid only on single-hop sessions (RFC 5883 Section 3). A configured multi-hop session using an echo profile is refused at load, and a multi-hop BGP peer naming one is refused at commit.
bfd {
profile fast-echo {
desired-min-tx-us 100000;
required-min-rx-us 100000;
echo {
desired-min-echo-tx-us 50000;
}
}
}
Add a bfd { } container inside a BGP peer's connection { } block:
bgp {
peer peer1 {
connection {
local { ip 192.0.2.1; }
remote { ip 192.0.2.2; }
bfd {
enabled true;
mode single-hop;
profile fast-link;
}
}
session {
asn { local 65001; remote 65002; }
router-id 192.0.2.1;
family { ipv4/unicast; }
}
}
}
On session Established, the reactor opens a BFD session. When BFD reports Down, the reactor tears the BGP session with RFC 9384 Cease NOTIFICATION subcode 10 ("BFD Down") without waiting for the hold timer.
A neighbour taking BFD to AdminDown (for maintenance, say) does NOT tear the BGP session down, in either mode. RFC 5882 Section 4.2 says a client "SHOULD NOT take any control protocol action" on that transition, because AdminDown says nothing about the data path.
OSPF and a BGP peer to the same neighbour over the same link share one BFD session (RFC 5882 Section 4.4), instead of opening two.
A reload or commit that adds, removes, disables or edits the opt-in of a peer without strict true keeps the BGP session: an Established peer opens its BFD session at once, a removed or disabled opt-in releases it, and an edited one (another profile or mode) releases it and opens one under the new request. The same holds for a dynamic group's template on every running dynamic peer of the group. A change with strict true before or after restarts the BGP session, because strict mode is announced in the OPEN.
RFC 5882 Section 10.2 says "BFD authentication SHOULD be used and is strongly encouraged" for a BFD session that advises an EBGP session. The peer's bfd container carries no key of its own: name a profile whose auth block configures authentication, and configure the neighbour with the same type, key ID and secret. A neighbour with a different secret, or one sending no authentication, never brings the session Up, so a strict-mode peer stays out of Established.
When an EBGP peer enables BFD with no profile, or with a profile that has no auth block, the commit is accepted and Ze logs one warning naming the peer (and the profile). Its fix field gives the auth { ... } block to add, or the connection { bfd { profile <name>; } } line naming an authenticated profile. IBGP peers and static next-hops draw no warning.
A BGP peer or a static next-hop that names a BFD profile is checked against the bfd block at startup, at commit and at SIGHUP reload. An undefined profile, a passive profile on a single-hop peer, and an echo profile on a multi-hop peer are each refused, naming the peer. An edit that touches only the bfd block is checked too, so deleting a profile a peer still names is refused. At startup the refusal stops the daemon.
ze config validate refuses an undefined profile on a BGP peer or a static next-hop and names the profiles that exist; the editor completes the same names. It does not run the passive and echo checks for a BGP peer: only the daemon refuses those.
A client that opts into BFD needs BFD running. A config where a BGP peer's connection bfd is enabled, a static next-hop names a bfd-profile, or an OSPF interface sets bfd { enabled true; }, while there is no top-level bfd block, bfd { enabled false; } is set, or the build carries no BFD, is refused at commit, at reload and at startup. The refusal names every client still opting in:
bfd: bfd { enabled false } is set, so no client may opt into BFD; remove the bfd opt-in of peer 192.0.2.1 first
So BFD cannot be removed from under a protected client: remove the opt-ins first, in the same commit or an earlier one. If a session is still refused at start for another reason, the peer logs it and runs without BFD unless it is in strict mode, where it stays down.
Plain BFD is a failure detector: it opens after BGP is up, so a peer whose control plane answers while its forwarding path is broken still establishes. Strict mode (draft-ietf-idr-bgp-bfd-strict-mode) holds the BGP session out of Established until the BFD session to that neighbour is Up.
bfd {
enabled true;
mode single-hop;
profile fast-link;
strict true;
hold-time 30;
}
| Leaf | Default | Meaning |
|---|---|---|
strict |
false | Advertise BGP capability 74 in every OPEN, open the BFD session before the BGP FSM starts and keep it across retries, and withhold KEEPALIVE while BFD is neither Up nor AdminDown: in OpenSent, or in Connect/Active when the OPEN arrived during DelayOpen. |
hold-down |
0 ms | How long BFD must stay Up before BGP may establish. Zero establishes on the first Up. A non-zero value damps a flapping link. |
hold-time |
30 s (1..65535) | Maximum wait for BFD after the peer's OPEN, used only when the negotiated BGP hold time is zero. On expiry Ze sends Cease subcode 10 (BFD Down) and returns to Idle. |
Both speakers must advertise capability 74. Against a peer that does not, Ze establishes normally and BFD stays a failure detector. With a non-zero BGP hold time, the ordinary hold timer ends a wait for a BFD session that never comes up. While held, show bgp peer list and show bgp peer detail carry a bfd-sub-state field. With timer { delay-open 5; } on the same peer, an early remote OPEN still makes Ze send its OPEN but not its KEEPALIVE while BFD is pending; the sub-state shows CONNECT-DELAYOPEN-BFD-UP-PENDING or ACTIVE-DELAYOPEN-BFD-UP-PENDING, and the same bounds apply.
Set the BGP hold time long enough to cover the hold-down (draft Section 10), and authenticate BFD (Section 12): anything that stops BFD coming Up now stops BGP too.
For iBGP between loopbacks:
bfd {
enabled true;
mode multi-hop;
min-ttl 250;
profile ibgp-loopback;
}
mode multi-hop uses UDP port 4784 and skips GTSM. min-ttl must be 256 - max-hops.
Sessions without a protocol client. local is the source address of every Control packet the session sends and must be an address the host holds; on Linux a send from any other address is refused and logged. Two sessions to the same peer from two local addresses stay two sessions (RFC 5883 Section 4.1), each sending from its own address.
bfd {
single-hop-session 192.0.2.254 {
local 192.0.2.1;
interface eth0;
profile gateway;
}
multi-hop-session 198.51.100.7 {
local 10.0.0.1;
profile gateway;
min-ttl 254;
}
}
A single-hop session to an IPv6 link-local peer (fe80::/10) must name its link in interface, in every VRF, because the same address can be in use on every link. One peer on two links is two entries:
bfd {
single-hop-session fe80::b { interface eth0; }
single-hop-session fe80::b { interface eth1; }
}
A link-local entry with no interface, and a peer or local written with a zone (fe80::b%eth0), are refused. Any IPv6 peer also needs bfd { bind-v6 true; } (default false): without it a protocol asking for an IPv6 session (OSPFv3, a BGP peer over IPv6) is refused with an error naming the leaf. An IPv4-mapped address travels on the IPv4 socket.
Several clients asking for a session to the same neighbour share one session. It runs the fastest timers among its clients (those giving the shortest Detection Time), chosen again whenever a client joins or leaves or any client's profile is edited.
One session carries one authentication configuration. A client whose profile resolves to a different authentication (another Auth Type, Key ID or secret, or authentication where the session has none, or the reverse) is refused rather than joined. The error names the peer, interface and VRF, what differs, and one fix that changes the refused client alone (naming a profile on it, or copying an auth block into a profile only it names); no suggested fix edits a shared profile. A refused BGP peer runs without BFD, a strict-mode one is held down, a static next-hop runs without BFD, a pinned session fails the apply of its commit, and an OSPF neighbour runs on its Hello and Dead timers. Two profiles with the same auth block under different names share the session.
OSPF BFD runs unauthenticated: an OSPF interface's bfd block takes timers only. OSPF shares a session with another client only when that session runs no authentication; otherwise take OSPF out of BFD on that interface with bfd { enabled false; }.
A released session that has heard from its peer stays in show bfd sessions as admin-down for three Detection Times (RFC 5880 Sections 6.8.1 and 6.8.16). A client that asks for the same session inside that window revives it, discriminator included.
On commit the plugin applies the new bfd section. A new pinned session starts, a removed one is released, and a pinned session's shutdown takes effect at once. An edit to a profile reaches every live session a client holds under it, in place: the session keeps its discriminator and takes the edited timers (an Up session through a Poll Sequence, so it stays Up), an edited passive, an edited echo interval, and an edited auth block when every client of the session asks for the same authentication after the edit. When one does not, the commit is refused, none of its bfd changes is applied, and the error names the two clients by profile.
To make an edit reach a session that no longer follows its profile, release the session from every client that holds it, then let them ask again:
| Client | Releases the session when | Asks again when |
|---|---|---|
| Pinned session | It is removed and committed | It is added back and committed |
| BGP peer | It leaves Established, for instance after request peer <address> teardown 4
|
It next reaches Established |
| Strict-mode BGP peer | It is removed, or deleted with delete bgp peer <address>
|
It is added back, at its first connection attempt |
| Static route next-hop | Its route is removed or changed | Its route is added back, or at once when changed |
| OSPF interface |
bfd { enabled false; } is set or its bfd block deleted, and committed |
BFD is enabled again, or the neighbour next reaches Full |
Release BGP peers last: a non-strict peer reconnects by itself and can rejoin the old session before the other clients let go.
| Command | Description |
|---|---|
show bfd sessions |
All sessions with state, timers, packet counts. |
show bfd session address <peer> |
Single session detail with transition history. |
show bfd profile |
Resolved profiles. |
| Metric | Type | Meaning |
|---|---|---|
ze_bfd_sessions |
gauge | Live session count by state, mode, VRF. |
ze_bfd_transitions_total |
counter | State changes by from/to/diag/mode. |
ze_bfd_detection_expired_total |
counter | Detection-timer expirations. |
ze_bfd_tx_packets_total |
counter | Control packets transmitted. |
ze_bfd_rx_packets_total |
counter | Control packets received. |
Single-hop BFD enforces GTSM (RFC 5082): packets are sent with TTL=255 and received packets with any other TTL are silently discarded. Multi-hop sessions use min-ttl as a weaker replacement. TX jitter per RFC 5880 S6.8.7 is applied automatically.
One socket serves every session of a (VRF, mode) pair. Only a session pinned in the bfd block binds that socket to a device (SO_BINDTODEVICE); a session a protocol asks for at runtime (every BGP peer and OSPF neighbour) never does. A running loop cannot be rebound: a reload asking for a different device logs a warning naming both devices, and the sessions keep transmitting from the original one until Ze restarts. A session's interface leaf still keys the session and still drives the per-session RFC 5881 Section 5 TTL check.
On Linux the socket requests IP_PKTINFO and IPV6_RECVPKTINFO, which is how a Control packet carrying no discriminator finds its session (RFC 5880 Section 6.8.6).
| Feature | RFC | Status |
|---|---|---|
| Demand mode | 5880 S6.6 | Not implemented. Rarely deployed. |
| Seamless BFD (S-BFD) | 7880, 7881 | Not implemented. |
| Micro-BFD on LAG | 7130 | Not implemented. |
| Multipoint BFD | 8562 | Not implemented. |
- In-tree BFD guide for the full reference.
- Plugins for the plugin list.
Adapted from main/docs/guide/bfd.md.
Unreviewed draft. This wiki was authored in bulk and has not been reviewed. File corrections on the issue tracker.
- Overview
- YANG Model
- Editor Workflow
- Archive and Rollback
- Backup and Restore
- System
- Interfaces
- VRRP
- BFD
- FIB
- OSPF
- IS-IS
- MPLS / LDP / RSVP-TE
- RSVP-TE
- SRv6
- Static Routes
- Policy Routing
- Firewall
- Traffic Control
- Class of Service
- L2TP/PPP
- PPPoE
- VPP Data Plane
- RPKI
- IPsec VPN
- Path MTU
- TACACS+ AAA
- RADIUS AAA
- AS112 DNS
- DNS
- Authorization
- Fleet
- BGP
- Starting and Stopping
- Show Commands
- Monitoring
- Telemetry
- Flow Export
- DDoS Mitigation
- Anomaly Detection
- Health Checks
- Audit Trail
- Production Diagnostics
- Logging
- Operational Reports
- Healthcheck
- Self-Update
- Zero-Touch Provisioning
- MRT Analysis
- Upgrade and Restart
- Storage
- Policy
- Core
- Resilience
- Validation
- Link State
- Capabilities
- Address Families
- Protocol
- Subsystems
- Infrastructure
- Route Server at an IXP
- Transit Edge with RPKI
- Public Looking Glass
- ExaBGP Migration Walkthrough
- FlowSpec Injection
- Chaos-Tested Peering
- AS Path Topology