BFD for OSPF
How BFD works
A BFD session runs between two neighbours that already know each other, usually because a routing protocol asked for one. Each side sends tiny UDP packets (port 3784) at an agreed interval. If no packet arrives for interval × multiplier, the session goes down, and BFD tells the protocols that use it. They react at once, as if the link had failed.
- Transmit and receive intervals: how often each side wants to send, and how often it's willing to receive. The two sides negotiate, and the slower one wins.
- Multiplier: how many packets in a row may be missed. With 300 ms and 3, the detection time is 900 ms.
- BFD is designed to be light enough to run in the forwarding path, or in a dedicated daemon (
bfddin FRR), independent of how busy the routing protocol is.
Profiles
VyOS groups timers into named profiles, so every session that should behave the same way says so by name. The lab's profile FAST is 300 ms × 3. OSPF interfaces then ask for BFD with bfd profile FAST. R2 does the same in FRR syntax. FRR doesn't even print the timers in its saved configuration, because 300 ms × 3 is its default.
show bfd peers lists both sessions, with the negotiated timers, the actual interval with jitter (BFD varies it slightly so sessions don't synchronise), and the 900 ms detection timeout. Peer Type: dynamic means OSPF created the session, not the BFD configuration.
The same failure, with BFD
Link A was cut at 08:37:53, and OSPF dropped the neighbour at 08:37:54. h1 lost 9 pings: under a second. The log still says InactivityTimer: when BFD reports the neighbour down, FRR's OSPF expires the dead timer immediately rather than waiting for it.
While the link was down, the session for link A wasn't shown as down: it had gone, because OSPF had removed the neighbour that asked for it. The route to LAN2 had already moved to link B.
set protocols bfd profile FAST interval transmit '300'
set protocols bfd profile FAST interval receive '300'
set protocols bfd profile FAST interval multiplier '3'
set protocols ospf interface eth0 bfd profile 'FAST'
set protocols ospf interface eth1 bfd profile 'FAST'- Lines 1–3: 300 ms intervals, three missed packets: 900 ms to detect a failure.
- Lines 4–5: OSPF asks BFD to watch each neighbour.
frr version 10.2.1_git
frr defaults traditional
hostname R2
no ipv6 forwarding
service integrated-vtysh-config
!
interface eth0
description link A to R1
ip address 10.0.12.2/30
ip ospf bfd
ip ospf bfd profile FAST
ip ospf cost 10
ip ospf network point-to-point
exit
!
interface eth1
description link B to R1 (backup)
ip address 10.0.12.6/30
ip ospf bfd
ip ospf bfd profile FAST
ip ospf cost 100
ip ospf network point-to-point
exit
!
interface eth2
description LAN2
ip address 198.51.100.129/25
ip ospf passive
exit
!
interface lo
ip address 192.0.2.2/32
exit
!
router ospf
ospf router-id 192.0.2.2
network 10.0.12.0/30 area 0
network 10.0.12.4/30 area 0
network 192.0.2.2/32 area 0
network 198.51.100.128/25 area 0
exit
!
bfd
profile FAST
exit
!
exit
!- Lines 10–11: The same on R2, interface by interface.
- Lines 43–47: The FAST profile: empty, because 300 ms × 3 is FRR's default and isn't saved.
vyos@R1:~$ show bfd peers brief
Session count: 2
SessionId LocalAddress PeerAddress Status Profile
========= ============ =========== ====== =======
3012387602 10.0.12.5 10.0.12.6 up FAST
2108029913 10.0.12.1 10.0.12.2 up FAST
vyos@R1:~$ show bfd peer 10.0.12.2
peer 10.0.12.2 local-address 10.0.12.1 vrf default interface eth0
ID: 2108029913
Remote ID: 47564980
Active mode
Status: up
Uptime: 11 second(s)
Diagnostics: ok
Remote diagnostics: ok
Peer Type: dynamic
RTT min/avg/max: 0/0/0 usec
Profile: FAST
Local timers:
Detect-multiplier: 3
Receive interval: 300ms
Transmission interval: 300ms
Transmission interval (actual with jitter): 297ms
Detection timeout: 900ms
Echo receive interval: 50ms
Echo transmission interval: disabled
Remote timers:
Detect-multiplier: 3
Receive interval: 300ms
Transmission interval: 300ms
Echo receive interval: 50ms- Lines 5–6: One session per link, both up, both using FAST.
- Line 16: dynamic: created because OSPF asked for it.
- Lines 20–24: Negotiated timers, the jittered actual interval, and the 900 ms detection time.
- Lines 27–31: What R2 asked for: the same.
root@r1-container:~# date +%T; ip link set eth0 nomaster # cut link A in the middle; carrier stays up
08:37:53
root@h1:~# ping -i 0.1 -w 20 -q 198.51.100.130 # started 5 s before the cut
PING 198.51.100.130 (198.51.100.130) 56(84) bytes of data.
--- 198.51.100.130 ping statistics ---
190 packets transmitted, 181 received, 4.73684% packet loss, time 19919ms
rtt min/avg/max/mdev = 0.422/1.511/4.657/0.786 ms- Lines 1–2: The cut: link A is detached in the middle, so both routers keep carrier on their interfaces.
- Line 4: Ten pings a second from h1 to h2, started 5 seconds earlier.
- Line 7: 9 pings lost: under a second.
vyos@R1:~$ show log | match "AdjChg" | tail -1
Oct 21 08:37:54 ospfd[1284]: AdjChg: Nbr 192.0.2.2, NbrIP 10.0.12.2 (default) on eth0:10.0.12.1: Full -> Deleted (InactivityTimer)- Line 2: One second after the cut at 08:37:53. BFD made OSPF expire its dead timer at once.
vyos@R1:~$ show bfd peers brief
Session count: 1
SessionId LocalAddress PeerAddress Status Profile
========= ============ =========== ====== =======
3012387602 10.0.12.5 10.0.12.6 up FAST
vyos@R1:~$ show bfd peer 10.0.12.2
vyos@R1:~$ show ip route 198.51.100.128/25
Routing entry for 198.51.100.128/25
Known via "ospf", distance 110, metric 110, best
Last update 00:00:04 ago
Flags: Selected
Status: Installed
* 10.0.12.6, via eth1, weight 1- Lines 1–5: Only link B's session is left: link A's was removed along with the OSPF neighbour.
- Lines 7–13: Traffic to LAN2 already goes over link B (metric 110: link B's cost plus the LAN).
Check your understanding
With transmit and receive intervals of 300 ms and a multiplier of 3, how long can a path be silent before BFD declares it down?
- 900 ms
- 300 ms
- 3 seconds
- 40 seconds