BFD troubleshooting — session down, misconfigured timers, asymmetric intervals
What you'll learn
- Diagnose a BFD session in Down state — firewall, peer, VRF
- Diagnose BFD session flapping — interval too aggressive, peer CPU, asymmetric intervals
- Diagnose BFD up but routing protocol not using it — missing bfd clause
- Read show bfd peer for the negotiated parameters
- Recognise the production failure modes and apply the canonical fixes
Prerequisites
Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-19
BFD failures on VyOS 1.5 LTS fall into four categories: the BFD session is in Down state (firewall, peer not running BFD, VRF mismatch); the BFD session is flapping (interval too aggressive, peer CPU saturated, asymmetric intervals); the BFD session is Up but the routing protocol is not using it (missing bfd clause on the routing protocol side); or the BFD session has negotiated asymmetric intervals that surprise the operator. Each failure has a different evidence trail and a different fix.
This lesson walks the four failure modes, the operational evidence that distinguishes them, and the production-grade fix for each. The goal is the ability to diagnose any BFD issue in minutes and apply the right fix.
The operational surface you have to work with
Before the failure modes, be clear about the tools, because two of the four diagnoses depend on reading state that VyOS exposes in exactly one place.
VyOS 1.5 documents one BFD operational command:
show bfd peers
There is no show bfd neighbors, no show bfd peer <address>,
no show bfd session and no show bfd profile in the VyOS
op-mode tree. show bfd peers prints every session with its
full detail block — discriminators, status, uptime, diagnostics,
and separately the local and remote timers — which is
why it can carry the whole diagnostic load on its own.
Everything below the VyOS layer comes from FRR:
vtysh -c 'show bfd peers'
vtysh -c 'show bgp ipv4 neighbors 192.0.2.2'
journalctl -u frr
Note the log unit. bfdd is a daemon inside FRR, not a systemd
unit of its own — journalctl -u bfdd returns nothing on a
working router, which reads exactly like “no BFD events” and is
not. Read journalctl -u frr.
The four failure modes
flowchart TD
BFDF[BFD failure] --> Q1{What's the session state?}
Q1 -->|"Down"| DOWN[Session Down<br/>firewall, peer, VRF]
Q1 -->|"flapping"| FLAP[Session flapping<br/>interval, CPU, asymmetric]
Q1 -->|"Up"| Q2{Is the routing protocol using BFD?}
Q2 -->|"no"| NOTUSED[BFD up but unused<br/>missing bfd clause]
Q2 -->|"yes"| Q3{Negotiated intervals as expected?}
Q3 -->|"no"| ASYM[Asymmetric intervals<br/>read show bfd peer]
Q3 -->|"yes"| OK[BFD is working correctly]
DOWN --> FIX1[Fix: open firewall, configure peer, fix VRF]
FLAP --> FIX2[Fix: increase interval, raise multiplier]
NOTUSED --> FIX3[Fix: add bfd clause to routing protocol]
ASYM --> FIX4[Fix: align intervals, use symmetric configuration]
The diagram shows the four failure modes and the diagnostic decision tree. The first decision is the session state. The second is whether the routing protocol is using BFD. The third is whether the negotiated intervals match expectations.
Failure mode 1 — Session in Down state
The BFD session is not active. The local router is sending BFD packets (or trying to) but not receiving any from the peer. The most common causes:
Cause 1.1 — Firewall blocking UDP 3784/4784
A firewall on the path between the two routers is blocking BFD packets. The local router sends BFD packets; the packets are dropped by the firewall; the peer never receives them.
The evidence:
show bfd peersshows the sessionStatus: down.tcpdump -nn -i any udp port 3784shows outbound packets but no inbound.journalctl -u frrshows the BFD state transitions;bfddlogs there, not to a unit of its own.
The fix: open UDP 3784 (single-hop) and/or UDP 4784 (multi-hop) on the firewall. For stateful firewalls, the connection tracking must allow the return traffic.
Cause 1.2 — Peer not running BFD
The peer does not have BFD configured. The peer may not have BFD in its BGP configuration; the peer may be running an older BGP implementation that does not support BFD; the peer’s BFD daemon may not be running.
The evidence:
show bfd peersshows the sessionStatus: down.tcpdump -nn -i any udp port 3784shows outbound packets but no inbound.- The peer’s BGP/OSP configuration does not have BFD enabled (operator needs to check the peer side).
The fix: configure BFD on the peer side. If the peer cannot run BFD, the operator can use echo mode (the peer only needs to loop packets back) or accept that BFD cannot be used for this peer.
Cause 1.3 — VRF mismatch
The local router’s BFD peer is in a different VRF than the local router’s BFD configuration. The local router sends BFD packets in the wrong VRF; the packets are dropped because the VRF does not have a route to the peer.
The evidence:
show bfd peersshows the sessionStatus: down.show bfd peersshows the session’svrfon the peer line, and it is not the VRF the peer’s address lives in.show ip route vrf <name> <peer-ip>shows no route to the peer in the configured VRF.
The fix: align the VRF. Either move the BFD peer to the correct VRF, or update the BFD configuration to use the correct VRF.
set protocols bfd peer 192.0.2.2 vrf 'MGMT'
Failure mode 2 — Session flapping
The BFD session is up briefly then down briefly then up again. The cadence matches whatever the underlying issue is.
Cause 2.1 — Interval too aggressive
The configured interval (e.g., 50ms = 20 packets per second per direction) is too aggressive for the link’s capability. The link drops packets; BFD declares the session down; the session restarts; the link drops more packets; BFD declares the session down again.
The evidence:
show bfd peersshows anUptimeof a second or two that resets each time you run it.tcpdumpshows the packet rate matches the configured interval.journalctl -u frrshows the BFD down/up events on the same cadence.
The fix: increase the interval to match the link’s capability. For 100Mbps links, 200ms is typical. For VPN tunnels or slow links, 500ms is typical.
Cause 2.2 — Peer CPU saturated
The peer’s CPU is too busy to send BFD packets at the configured rate. The peer misses packets; BFD declares the session down; the cycle repeats.
The evidence:
show bfd peersshows anUptimeof a second or two that resets each time you run it.- The peer’s
toporshow process list | grep bfddshows the BFD daemon at high CPU. - The peer’s CPU is generally saturated (other processes also at high CPU).
The fix: either reduce the BFD packet rate (increase the interval) or address the peer’s CPU saturation (identify the process consuming CPU).
Cause 2.3 — Asymmetric intervals
The two routers negotiate asymmetric intervals. Router A transmits at 50ms but accepts 100ms; Router B transmits at 100ms but accepts 50ms. The negotiated interval for the A→B direction is 100ms (the slower of A’s transmit and B’s receive); the negotiated interval for the B→A direction is 50ms.
The evidence:
show bfd peersshows theLocal timersandRemote timersblocks disagreeing — a localTransmission interval: 50msagainst a remoteReceive interval: 300ms, for example.- The session may be stable but the operator is surprised by the asymmetric parameters.
The fix: align the intervals on both sides. Either set both sides to the same transmit/receive, or accept the asymmetry if it is intentional (rare).
Failure mode 3 — BFD up but routing protocol not using it
The BFD session is established, but the routing protocol does not tear down its session when BFD detects a failure. The canonical scenario: the operator enables BFD on the BFD side (set protocols bfd peer <ip>) but forgets to enable BFD on the routing protocol side (set protocols bgp neighbor <ip> bfd).
The evidence:
show bfd peersshows the sessionStatus: up.show configuration commands | match 'neighbor 192.0.2.2 bfd'returns nothing, which settles it: the clause is simply absent. That is a better first check than reading a protocol’s neighbour output, because it separates “not configured” from “configured and not working”.vtysh -c 'show bgp ipv4 neighbors 192.0.2.2'carries no BFD block for that peer.show ip ospf neighbor detail(for OSPF) does not report BFD for the adjacency.
The fix: add the bfd clause to the routing protocol
configuration. Note that the local AS is no longer part of the
BGP path — VyOS 1.4 moved it to
set protocols bgp system-as <asn> and put peers under
set protocols bgp neighbor.
For BGP, where BFD attaches to the neighbour and can carry a profile:
set protocols bgp neighbor 192.0.2.2 bfd
set protocols bgp neighbor 192.0.2.2 bfd profile SLOW
For the link-state protocols, BFD attaches to the interface rather than to a neighbour, because their adjacencies are discovered rather than configured:
set protocols ospf interface eth0 bfd
set protocols ospfv3 interface eth0 bfd
set protocols isis interface eth0 bfd
None of those three takes a profile — the interface-attached
form is enable-or-not. If a link-state adjacency needs
non-default timers, configure them on the matching
protocols bfd peer entry instead.
For static routes, where BFD is the thing that turns a static next-hop into a monitored one:
set protocols static route 198.51.100.0/24 next-hop 192.0.2.2 bfd
set protocols static route 198.51.100.0/24 next-hop 192.0.2.2 bfd profile SLOW
set protocols static route6 2001:db8:100::/48 next-hop 2001:db8::2 bfd profile SLOW
Failure mode 4 — Asymmetric intervals surprise
The negotiated intervals do not match the operator’s expectations. The operator configures 50ms on both sides but the negotiated interval is 100ms in one direction.
The cause is in the node names. VyOS splits the timers into
interval transmit (how fast I want to send) and
interval receive (the slowest rate I am prepared to accept
from you). RFC 5880 resolves each direction to the slower of
my transmit and your receive, so one side’s interval receive
silently governs the other side’s actual send rate.
Old material calls the receive knob min-rx. That name is FRR’s
and Cisco’s; it is not a VyOS node and will not commit. The VyOS
tree is:
set protocols bfd peer 192.0.2.2 interval transmit 300
set protocols bfd peer 192.0.2.2 interval receive 300
set protocols bfd peer 192.0.2.2 interval multiplier 3
The evidence:
show bfd peersprints aLocal timersblock and aRemote timersblock for each session, each withDetect-multiplier,Receive intervalandTransmission interval.- Compare local
Transmission intervalagainst remoteReceive interval: the effective rate in that direction is the larger number. - Then do it the other way round for the reverse direction. The two directions are computed independently, which is why an asymmetric configuration produces an asymmetric result rather than a single negotiated value.
The fix: set interval transmit and interval receive to the
same value on both routers. For a symmetric 300ms session with a
900ms detection time, that is transmit 300, receive 300,
multiplier 3 on each side.
How the result is validated
show bfd peers
show ip ospf neighbor detail
show ip route 198.51.100.0/24
show configuration commands | match bfd
vtysh -c 'show bfd peers'
vtysh -c 'show bgp ipv4 neighbors 192.0.2.2'
journalctl -u frr
tcpdump -nn -i any udp port 3784
tcpdump -nn -i any udp port 4784
show bfd peers is the whole VyOS BFD view — session list,
state and both timer blocks. show ip ospf neighbor detail and
show ip route <prefix> confirm the protocol side is consuming
BFD. show configuration commands | match bfd is the
fastest way to prove a bfd clause is present or absent, which
is failure mode 3 in one line. The vtysh pair drops to FRR for
the same state plus the BGP peer’s view of it, and
journalctl -u frr carries the state transitions — including
bfdd’s, which has no unit of its own. The two tcpdump
filters cover single-hop (3784) and multi-hop (4784) BFD.
show bfd peers prints a detail block per session. The shape to
read:
vyos@R1:~$ show bfd peersBFD Peers:
peer 192.0.2.2 vrf default
ID: 1721004311
Remote ID: 2884109553
Active mode
Status: up
Uptime: 3 day(s), 4 hour(s), 11 minute(s), 2 second(s)
Diagnostics: ok
Remote diagnostics: ok
Peer Type: configured
Local timers:
Detect-multiplier: 3
Receive interval: 300ms
Transmission interval: 300ms
Remote timers:
Detect-multiplier: 3
Receive interval: 300ms
Transmission interval: 300msIllustrative output
The values above are illustrative — read the block for its fields, not its numbers. What the operator should verify:
Statusisup, andUptimeis longer than the interval you have been watching. A session that is up but has an uptime of two seconds is a flapping session caught between flaps.Local timersandRemote timersagree. Where they do not, the slower value wins in that direction.- The detection time you actually get is
Detect-multipliertimes the effective receive interval — 900ms in the block above, not 300ms. - The
vrfon the peer line is the VRF the peer’s address lives in. DiagnosticsandRemote diagnosticssay why the session last went down.okon both is the healthy case; anything else is the peer telling you what it saw.
How it fails
The production failure modes the engineer must recognise:
- BFD session in Down. Firewall, peer not running BFD, VRF mismatch. Walk these in order.
- BFD session flapping. Interval too aggressive, peer CPU saturated, asymmetric intervals. Walk these in order.
- BFD up but routing protocol not using it. Missing
bfdclause on the routing protocol side. Add the clause. - Asymmetric intervals. Operator surprise. Align the intervals.
Rollback
BFD troubleshooting changes are usually diagnostic, not configuration-changing. If the operator changes the BFD interval or profile during debugging, the rollback is:
rollback N; commit; saveto revert any configuration changes.delete protocols bfd profile <name>to remove a profile — but only once nothing references it, since a peer or static route pointing at a deleted profile will not commit.delete protocols bfd peer <ip>to remove a peer.
If the operator disabled BFD on a routing protocol during debugging, the rollback is to re-enable it. Note the 1.5 paths:
set protocols bgp neighbor <ip> bfdto re-enable BGP+BFD. There is no ASN in this path any more; the local AS isset protocols bgp system-as <asn>.set protocols ospf interface <intf> bfdto re-enable OSPF+BFD.set protocols static route <prefix> next-hop <ip> bfdto re-enable static+BFD.
Use commit-confirm for the re-enable on a remote router. A BFD
peer with the wrong timers can tear down the BGP session you are
managing the router over, and it will do it in under a second.
Production discipline
Cross-course references
The Linux course’s XIX-Linux-NetFoundations covers the kernel UDP stack. The OPNsense course’s XXX-OPNsense-DynamicRouting covers the equivalent FRR BFD on the firewall side. The lessons vyos-xxxii-01-bfd-concept and vyos-xxxii-02-bfd-config cover the BFD protocol and configuration. The lessons vyos-xxxii-03-bfd-with-bgp, vyos-xxxii-04-bfd-with-ospf, and vyos-xxxii-05-bfd-with-static cover the routing protocol integrations.
Quiz
Knowledge check · 4 questions
Q1. An operator configures BFD on a BGP peer. The BFD session is in `Down` state. The operator's `tcpdump -nn -i any udp port 3784` shows outbound packets but no inbound packets. What is the most likely cause?
Q2. When BFD is enabled on the BFD daemon (`set protocols bfd peer <ip>`) but not on the BGP peer (`set protocols bgp neighbor <ip> bfd`), the BGP session will tear down immediately on BFD failure.
Q3. An operator enables BFD on a BGP peer with a FAST profile (50ms transmit and receive, multiplier 3). The BFD session flaps every 1-2 seconds: `show bfd peers` never shows an Uptime past a couple of seconds, and `tcpdump` shows the local router sending at 20 packets per second. What is the most likely cause and fix?
The BFD interval is 50ms (20 packets per second per direction). The link or peer cannot sustain this rate. The BFD session flaps; the BGP session follows. The fix is to increase the BFD interval to match the link's capability.
Q4. An operator enables BFD on a BGP peer. `show bfd peers` reports the session up, with Local timers showing a 50ms transmission interval and a 50ms receive interval, and Remote timers showing 300ms for both. The operator expected 150ms detection. What is actually happening, and what is the fix?
The local router is configured with `interval transmit 50` and `interval receive 50`; the peer is configured with 300ms for both. RFC 5880 resolves each direction to the slower of the sender's transmit interval and the receiver's receive interval, and it does so independently per direction.
Passing score: 75%. Answers are checked in this browser.