TTR Networks

Intermediate · BFD on VyOS: fast failover for quiet failures · section 4 of 7

BFD for BGP

✓ Lab-tested 21 October 2026 on VyOS 2026.10.16-0024-rolling, FRR 10.2.1

BGP is where BFD matters most, because its defaults are the slowest: a keepalive every 60 seconds, and a hold time of 180 seconds.

The lab replaces OSPF with eBGP: one session over each link, each side announcing its LAN. Two settings keep the measurement honest:

  • maximum-paths ebgp 1: VyOS would otherwise install both links as equal paths (ECMP), and a single ping flow could happen to hash onto the healthy one.
  • A weight of 100 on link A's session, on both routers, so both directions prefer link A. Without it, R2 picked link B for the return path, because FRR prefers the older of two otherwise equal eBGP routes.

Without BFD

Link A was cut at 08:45:33. h1 lost 1,506 of 2,100 pings: about 159 seconds of outage. R1 records why the session finally reset: Hold Timer Expired. On a real network that's nearly three minutes of black-holed traffic, during which nobody's monitoring sees an interface down.

The ping also counted errors: once R1's ARP entry for R2 expired, R1 started answering h1 with host unreachable.

With BFD

bfd profile FAST on each BGP neighbour (and neighbor … bfd profile FAST on R2). show bgp neighbors then shows the BFD session attached to the neighbour.

The same cut cost 10 pings: about a second. This time the session's last reset says BFD down initiated: BFD told BGP, and BGP tore the session down and switched to link B straight away.

Unlike OSPF's, BGP's BFD session stays listed while it's down, because the BGP neighbour still exists and keeps trying.

R1: eBGP over both links
delete protocols ospf
set protocols bgp system-as '64501'
set protocols bgp parameters router-id '192.0.2.1'
set protocols bgp address-family ipv4-unicast network '198.51.100.0/25'
set protocols bgp neighbor 10.0.12.2 description 'R2 over link A'
set protocols bgp neighbor 10.0.12.2 remote-as '64502'
set protocols bgp neighbor 10.0.12.2 address-family ipv4-unicast
set protocols bgp neighbor 10.0.12.6 description 'R2 over link B'
set protocols bgp neighbor 10.0.12.6 remote-as '64502'
set protocols bgp neighbor 10.0.12.6 address-family ipv4-unicast
set protocols bgp address-family ipv4-unicast maximum-paths ebgp '1'
set protocols bgp neighbor 10.0.12.2 address-family ipv4-unicast weight '100'
set protocols bgp parameters log-neighbor-changes
  • Line 1: OSPF out, BGP in.
  • Lines 5–10: One session per link, to the same neighbouring AS.
  • Line 11: One path at a time, so the measurement doesn't depend on ECMP hashing.
  • Line 12: Prefer link A.
  • Line 13: Log session changes.
BGP's default timers (real output)
vyos@R1:~$ show bgp neighbors 10.0.12.2 | match "Hold time"
  Hold time is 180 seconds, keepalive interval is 60 seconds
  • Line 2: A keepalive every minute; the session dies after three minutes of silence.
Cutting link A, BGP without BFD (real output)
root@r1-container:~# date +%T; ip link set eth0 nomaster   # cut link A in the middle; carrier stays up
08:45:33

root@h1:~# ping -i 0.1 -c 2100 -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 ---
2100 packets transmitted, 594 received, +138 errors, 71.7143% packet loss, time 221330ms
rtt min/avg/max/mdev = 0.348/2.136/18.258/1.757 ms, pipe 30
  • 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: 1,506 of 2,100 pings lost: about 159 seconds. The errors are R1's host unreachable replies once it gave up resolving R2 on link A.
Why the session finally went (real output)
vyos@R1:~$ show bgp neighbors 10.0.12.2 | match "Last reset"
  Last reset 00:07:41,  Notification sent (Hold Timer Expired)
  • Line 2: The hold timer expired: three minutes after the last keepalive.
R1: BFD on both BGP neighbours
set protocols bgp neighbor 10.0.12.2 bfd profile 'FAST'
set protocols bgp neighbor 10.0.12.6 bfd profile 'FAST'
R2 (FRR): BGP with BFD, and the multihop session
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
exit
!
interface eth1
 description link B to R1 (backup)
 ip address 10.0.12.6/30
exit
!
interface eth2
 description LAN2
 ip address 198.51.100.129/25
exit
!
interface lo
 ip address 192.0.2.2/32
exit
!
router bgp 64502
 bgp router-id 192.0.2.2
 no bgp ebgp-requires-policy
 neighbor 10.0.12.1 remote-as 64501
 neighbor 10.0.12.1 description R1 over link A
 neighbor 10.0.12.1 bfd
 neighbor 10.0.12.1 bfd profile FAST
 neighbor 10.0.12.5 remote-as 64501
 neighbor 10.0.12.5 description R1 over link B
 neighbor 10.0.12.5 bfd
 neighbor 10.0.12.5 bfd profile FAST
 !
 address-family ipv4 unicast
  network 192.0.2.2/32
  network 198.51.100.128/25
  neighbor 10.0.12.1 weight 100
  maximum-paths 1
 exit-address-family
exit
!
bfd
 profile FAST
 exit
 !
 profile MULTIHOP
  transmit-interval 1000
  receive-interval 1000
 exit
 !
 peer 192.0.2.1 multihop local-address 192.0.2.2
  profile MULTIHOP
 exit
 !
exit
!
  • Lines 26–36: Two eBGP sessions, each with BFD and the FAST profile.
  • Lines 38–43: The LAN and loopback, link A preferred, one path.
  • Lines 46–58: Both profiles, and the multihop peer between the loopbacks.
The BFD session attached to a neighbour (real output)
vyos@R1:~$ show bgp neighbors 10.0.12.2 | match "BFD:|Detect|Status:"
  BFD: Type: single hop
  Detect Multiplier: 3, Min Rx interval: 300, Min Tx interval: 300
  Status: Up, Last update: 0:00:00:12
  • Lines 2–4: Single-hop BFD, 300 ms × 3, up.
The same cut, with BFD (real output)
root@r1-container:~# date +%T; ip link set eth0 nomaster   # cut link A in the middle; carrier stays up
08:56:27

root@h1:~# ping -i 0.1 -c 200 -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 ---
200 packets transmitted, 190 received, 5% packet loss, time 20980ms
rtt min/avg/max/mdev = 0.379/1.586/7.926/0.974 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: 10 pings lost: about a second.
…and why the session went this time (real output)
vyos@R1:~$ show bgp neighbors 10.0.12.2 | match "Last reset"
  Last reset 00:00:18,  BFD down initiated (n/a)
  • Line 2: BFD told BGP the path was dead.

Check your understanding

Why are BGP's default timers so much slower than OSPF's?

  • BGP sessions often cross networks and carry huge tables; flapping a session is expensive, so its defaults favour stability.
  • BGP can't send keepalives more often than once a minute.
  • BGP runs over UDP.
  • Because BGP routes are always backed up by OSPF.