Skip to content

Agent: BFD visibility and optional management for faster failover detection #128

Description

@berendt

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.

  1. 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.
  2. 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.
  3. 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

  • With defaults, the agent logs a warning and sets
    ovn_network_bfd_detect_seconds when BFD detection is estimated above
    bfd_check_max_detect; no OVS/FRR state is modified.
  • ovn_bfd_manage=true sets the timer keys on local Geneve tunnels and
    is idempotent across reconciles.
  • frr_bfd_manage=true enables BFD on the VRF's BGP neighbors and is
    idempotent.
  • Both manage flags are independently toggleable and default off.
  • Table tests for bfd.go with stubbed ovs-vsctl/vtysh (pattern:
    execOVSHook / execVtyshHook).
  • docs/explanation/ describes the failover-detection floor and the
    recommended BFD values; docs/reference/configuration.md regenerated.

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions