One of four independent issues improving multi-node FIP failover speed
(BFD visibility/management, active drain handshake, standby pre-staging,
failover hot-path tightening). They can be implemented in any order.
Problem
Ungraceful failover (node crash, partition, ovn-controller crash) is
dominated by OVN's BFD-based detection of the dead gateway chassis —
typically 3×1s ≈ 3s before the chassisredirect Port_Binding is even moved.
The agent's own reaction after that is already <1s (immediateStateRefresh
bypasses the event debounce). The BFD timers are currently invisible to the
agent and untuned, so operators have no signal on what the real failover
floor is, and no agent-side lever to lower it.
Proposal
Add a new bfd.go with three parts. Part 1 is on by default; parts 2 and 3
are opt-in and toggle independently.
- BFD check (default on). On each reconcile:
- OVN tunnel BFD: enumerate local Geneve tunnel interfaces via
ovs-vsctl
(find Interface type=geneve), read the bfd column, estimate
detection time = detect multiplier × negotiated min_rx/min_tx.
- FRR BGP BFD: read
vtysh -c "show bfd peers json".
- Export
ovn_network_bfd_detect_seconds{layer="ovn"|"frr"} and
slog.Warn when the estimate exceeds bfd_check_max_detect.
- OVN tunnel BFD management (default off,
ovn_bfd_manage). Set
bfd:min_rx/bfd:min_tx on the local Geneve tunnel interfaces via
ovs-vsctl. ovn-controller sets only bfd:enable=true; verify
against the deployed OVN version that ovn-controller preserves
operator-set timer keys before relying on this.
- FRR BGP-session BFD management (default off,
frr_bfd_manage).
Discover VRF BGP neighbors (show bgp vrf <vrf> neighbors json), then set
neighbor <peer> bfd plus a bfd profile with the configured timers.
Closes the "stale /32 from the dead node" gap on a full node crash.
Document that the fabric side must enable BFD too.
Scope
- New file
bfd.go; OVS helpers extend ovs.go; vtysh helpers reuse
runVtysh (routing.go:66) and the ovsWrapper prefix (routing.go:30).
- New config options in
config.go (with defaults; docgen.go regenerates
docs/reference/configuration.md):
bfd_check_enabled (default true)
bfd_check_max_detect (default 1s)
ovn_bfd_manage (default false), ovn_bfd_min_rx_ms /
ovn_bfd_min_tx_ms (default 150)
frr_bfd_manage (default false), frr_bfd_min_rx_ms /
frr_bfd_min_tx_ms (default 150), frr_bfd_multiplier (default 3)
- New metrics in
metrics.go.
- Wire the check/manage calls into
reconcile (agent.go:230).
Out of scope
- BGP neighbor peering configuration — the agent only manages static
routes and prefix-lists today; this issue adds only the bfd knob to
already-configured neighbors.
- Changing OVN's HA model (
Gateway_Chassis vs HA_Chassis_Group).
Acceptance criteria
Implementation hints
- The repo docs already assert "typically 3×1s = 3 seconds"
(docs/explanation/gateway-drain.md) — use that as the baseline to beat.
- OVS BFD detection time = detect multiplier × negotiated
min_rx/min_tx;
with min_rx=min_tx=150ms and mult 3 the floor drops to ~450ms.
- Keep the check cheap: it runs every reconcile, so cache the tunnel list and
only re-enumerate on an event-triggered reconcile.
One of four independent issues improving multi-node FIP failover speed
(BFD visibility/management, active drain handshake, standby pre-staging,
failover hot-path tightening). They can be implemented in any order.
Problem
Ungraceful failover (node crash, partition,
ovn-controllercrash) isdominated by OVN's BFD-based detection of the dead gateway chassis —
typically 3×1s ≈ 3s before the
chassisredirectPort_Binding is even moved.The agent's own reaction after that is already <1s (
immediateStateRefreshbypasses the event debounce). The BFD timers are currently invisible to the
agent and untuned, so operators have no signal on what the real failover
floor is, and no agent-side lever to lower it.
Proposal
Add a new
bfd.gowith three parts. Part 1 is on by default; parts 2 and 3are opt-in and toggle independently.
ovs-vsctl(
find Interface type=geneve), read thebfdcolumn, estimatedetection time = detect multiplier × negotiated
min_rx/min_tx.vtysh -c "show bfd peers json".ovn_network_bfd_detect_seconds{layer="ovn"|"frr"}andslog.Warnwhen the estimate exceedsbfd_check_max_detect.ovn_bfd_manage). Setbfd:min_rx/bfd:min_txon the local Geneve tunnel interfaces viaovs-vsctl.ovn-controllersets onlybfd:enable=true; verifyagainst the deployed OVN version that ovn-controller preserves
operator-set timer keys before relying on this.
frr_bfd_manage).Discover VRF BGP neighbors (
show bgp vrf <vrf> neighbors json), then setneighbor <peer> bfdplus abfd profilewith the configured timers.Closes the "stale
/32from the dead node" gap on a full node crash.Document that the fabric side must enable BFD too.
Scope
bfd.go; OVS helpers extendovs.go; vtysh helpers reuserunVtysh(routing.go:66) and theovsWrapperprefix (routing.go:30).config.go(with defaults;docgen.goregeneratesdocs/reference/configuration.md):bfd_check_enabled(defaulttrue)bfd_check_max_detect(default1s)ovn_bfd_manage(defaultfalse),ovn_bfd_min_rx_ms/ovn_bfd_min_tx_ms(default150)frr_bfd_manage(defaultfalse),frr_bfd_min_rx_ms/frr_bfd_min_tx_ms(default150),frr_bfd_multiplier(default3)metrics.go.reconcile(agent.go:230).Out of scope
routes and prefix-lists today; this issue adds only the
bfdknob toalready-configured neighbors.
Gateway_ChassisvsHA_Chassis_Group).Acceptance criteria
ovn_network_bfd_detect_secondswhen BFD detection is estimated abovebfd_check_max_detect; no OVS/FRR state is modified.ovn_bfd_manage=truesets the timer keys on local Geneve tunnels andis idempotent across reconciles.
frr_bfd_manage=trueenables BFD on the VRF's BGP neighbors and isidempotent.
bfd.gowith stubbedovs-vsctl/vtysh(pattern:execOVSHook/execVtyshHook).docs/explanation/describes the failover-detection floor and therecommended BFD values;
docs/reference/configuration.mdregenerated.Implementation hints
(
docs/explanation/gateway-drain.md) — use that as the baseline to beat.min_rx/min_tx;with
min_rx=min_tx=150msand mult 3 the floor drops to ~450ms.only re-enumerate on an event-triggered reconcile.