Skip to content

northd: Mark BFD sessions down when no chassis can run them. - #321

Open
remeq wants to merge 1 commit into
ovn-org:mainfrom
remeq:bfd-no-owner-down
Open

northd: Mark BFD sessions down when no chassis can run them.#321
remeq wants to merge 1 commit into
ovn-org:mainfrom
remeq:bfd-no-owner-down

Conversation

@remeq

@remeq remeq commented Aug 25, 2026

Copy link
Copy Markdown

Fixes the stale-BFD-status failure described in #320 for the explicit no currently bound owner case. If the controller that ran a session disappears and no chassis owns the gateway port, the last NB/SB BFD.status could otherwise remain up indefinitely and keep a dead ECMP nexthop eligible.

The change makes northd derive the BFD owner using the same two supported binding forms as bfd_monitor_run():

  • the distributed gateway port's chassisredirect binding;
  • the logical port's own binding only when it is an l3gateway port.

When neither has a bound owner, northd marks non-admin_down NB and SB status down, clears SB.BFD.chassis_name, and lets the existing route/policy logic withdraw the nexthop. When an owner returns, northd restores chassis_name; the controller remains responsible for negotiating and reporting operational state.

SB_port_binding is also an explicit input of bfd_sync, so direct owner-to-NULL binding changes cannot leave stale BFD state. The same ownership rule now maintains chassis_name for distributed gateway ports, enabling the existing BFD RBAC rule to authorize the correct controller.

Validation on current OVN main includes a clean build and focused northd tests for both chassisredirect and direct l3gateway ownership, a direct Port_Binding.chassis clear while the Chassis row remains present, recovery, route withdrawal, and admin_down preservation. The combined #321/#323/#325 stack was also exercised with real controllers and RBAC in the two-node FRR lab.

Scope: this patch deliberately does not classify a hard-crashed chassis whose stale Chassis and Port_Binding rows both remain. That case requires an eligibility decision, implemented by the stacked Concept C proposal in #325 and its companion opt-in Neutron policy.

Reported-at: #320

Assisted-by: Claude Code

The Southbound BFD "status" column is only ever written by the
ovn-controller that runs the session: bfd_monitor_run() picks a session
up on the chassis where the port is a bound "l3gateway" port or where
the port's "cr-" chassisredirect twin is chassis-resident.  When that
chassis goes away and no other chassis can take the gateway port over
(e.g. it was the only chassis with a bridge mapping for the provider
network), nothing is left to update the session status: the NB/SB
status stays "up" forever even though no BFD packets are exchanged any
more.  BFD monitored (ECMP) static routes then keep selecting the dead
next hop and traffic is blackholed.

Fix this in ovn-northd, which can see that no chassis owns the port:
teach bfd_table_sync() to determine the chassis that would run the
session, mirroring the ownership rule of bfd_monitor_run(), and force
both the NB and SB status to "down" when there is no such chassis,
leaving "admin_down" sessions untouched.  Route (and policy) processing
already drops BFD monitored next hops whose session is "down", so this
is enough to withdraw the routes.  Once a chassis (re)claims the
gateway port, its ovn-controller creates a fresh monitor entry and
kicks the session back into negotiation, so a northd-written "down"
does not prevent recovery.

Use the same ownership rule to maintain the SB BFD "chassis_name"
column.  It was previously derived from the port's own Port_Binding
only, but for a distributed gateway port that binding is a "patch"
port whose chassis column is never set, so chassis_name stayed empty
even for healthy sessions.  It now tracks the chassis bound to the
chassisredirect port and is cleared when the session has no owner.

Finally, make the incremental processing engine reevaluate the session
ownership when the Port_Binding of a port with a BFD session changes
its bound chassis: the "northd" engine node deliberately ignores
chassis-only binding updates, so a gateway port being released would
not have re-triggered bfd_table_sync().  Add SB Port_Binding as an
input of the "bfd_sync" engine node, with a change handler that falls
back to recompute when the "chassis" column changed on the Port_Binding
of a port (or of a chassisredirect twin of a port) that has a BFD
session, and ignores all other Port_Binding changes.

Reported-at: ovn-org#320
Assisted-by: Claude Code
Signed-off-by: Premysl Kouril <premysl.kouril@gmail.com>
@remeq
remeq force-pushed the bfd-no-owner-down branch from 0e88206 to 7a95f87 Compare August 28, 2026 14:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant