OpenKeel: the sovereign French Cloud solution of the inherent group, with a European reach Discover inherent

Reverse-spec · Services

ovn-bgp-agent — Summary

Reverse-specification of ovn-bgp-agent — branch stable/2026.2

  • Repository: https://opendev.org/openstack/ovn-bgp-agent — specified branch: stable/2026.2 @ f770768b41dc (7.0.0-2-gf770768, 2026-09-10) — analysed on: 2026-10-28
  • Scope: the whole agent (4 drivers, 5 exposing methods, 55 event classes, 2 periodic loops, kernel/OVS/FRR/OVN interactions), plus a rewrite pack (step 8). Change history (step 7) was not requested.
  • External references cited: ovsdbapp: = ovsdbapp stable/2026.2 @ 0fb5a1b9a675; neutron-lib: = neutron-lib stable/2026.2 @ 1ee72052251a.
FileContent
01-drivers-and-exposurewhat the agent exposes, drivers × exposing methods, configuration reference, lifecycle of an exposed IP (replaces the REST catalogue)
02-errorsexceptions with situations, asynchronous errors, key logs, 16 defects (4 reproduced)
03-interactionsOVS DB, OVN SB/NB (tables, columns, Neutron external_ids), node-local NB writes, FRR texts, netlink, sysctl, OVS commands, privsep contexts
04-scenarios6 sequence diagrams with diagnostics
05-async-processingevery trigger: OVSDB events per driver, sync, frr_sync, reconnection, concurrency
07-rewrite-packcontracts for a re-implementation, event decision vectors (245/245 replay), side-effect scenarios (11/11)
_verificationreference check output

Overview

ovn-bgp-agent runs on every OpenStack node that uses OVN and makes the IPs that live on that node reachable through BGP: VMs on provider networks, floating IPs, router gateways and, optionally, tenant subnets and load-balancer VIPs. It has no API and no database. It watches the OVN Southbound or Northbound database (read-only), reacts to row changes (port bound here, gateway moved here, FIP associated…), and for each IP it wires the kernel and OVS so that traffic is handed to OVN (ip rules and routes in a per-bridge routing table, neighbours, proxy ARP/NDP, an OVS flow that rewrites the destination MAC), then announces the IP by adding it to a dummy interface in a VRF that the local FRR redistributes into BGP. A periodic full resynchronisation (300 s) repairs missed events and removes leftovers; another loop (15 s) re-applies the FRR configuration. Variants put the routes into EVPN VRFs (VXLAN type-5), into a node-local OVN cluster, or announce subnet routes from every node (stretched L2).

Architecture

flowchart LR
  neutron[neutron-server<br/>OVN driver] -->|OVSDB write| nb[(OVN NB)]
  nb --> northd[ovn-northd] --> sb[(OVN SB)]
  sb <-->|OVSDB| ovnc[ovn-controller]
  subgraph node[Compute / network node]
    agent[ovn-bgp-agent]
    ovsdb[(local OVS DB)]
    kernel[Linux kernel<br/>VRF bgp-vrf, bgp-nic,<br/>rules, routes, neigh]
    ovs[OVS br-ex<br/>flows cookie 999]
    frr[FRR bgpd/zebra]
    lnb[(node-local OVN NB<br/>exposing_method=ovn)]
  end
  agent -->|OVSDB read: system-id, bridge mappings| ovsdb
  agent -->|OVSDB monitor, read-only| sb
  agent -->|OVSDB monitor, read-only| nb
  agent -->|privsep: netlink, sysctl| kernel
  agent -->|privsep: ovs-vsctl / ovs-ofctl| ovs
  agent -->|privsep: vtysh -f| frr
  agent -.->|OVSDB write| lnb
  kernel -->|connected / kernel routes| frr
  frr -->|BGP /32, /128, prefixes| fabric[Leaf switches]

Processes

ProcessEntry pointRoleListens to / consumes
ovn-bgp-agentovn_bgp_agent.cmd.agent:start → ovn_bgp_agent/agent.py:75load one driver, run its OVN event handlers and the two loopsOVN SB or NB (OVSDB monitor_cond), timers
privsep daemons (3)ovn_bgp_agent/privileged/__init__.py:18-42execute netlink/sysctl, ovs-*, vtysh with capabilitiesrequests from the agent

External dependencies

SystemProtocolLibraryConfigurationUsage
OVN SB / NBOVSDB JSON-RPC (tcp/ssl/unix)ovsdbapp, ovs[ovn] ovn_sb_connection / ovn_nb_connection or OVS external_idsread rows, receive events
local OVS DBOVSDBovsdbappovsdb_connectionchassis identity, remotes, bridge mappings
node-local OVN NBOVSDBovsdbapp[local_ovn_cluster]router/policies/routes/BFD/static MAC bindings (exposing_method = ovn)
Linux kernelrtnetlink, sysctl, ippyroute2, oslo.privsepbgp_nic, bgp_vrf, bgp_vrf_table_idannouncement and traffic steering
OVSovs-vsctl, ovs-ofctl, ovs-appctloslo.concurrencybridge mappingsflows, ports
FRRvtyshoslo.concurrency, Jinja2bgp_AS, bgp_router_idVRF leak, EVPN VRFs, IPv6 RA

Key figures

  • REST endpoints: 0. RPC: 0. Database tables: 0.
  • Drivers: 4 (ovn_bgp_driver default, nb_ovn_bgp_driver, ovn_evpn_driver, ovn_stretched_l2_bgp_driver); exposing methods: 5 declared, 3 implemented (underlay, vrf, ovn).
  • Non-HTTP triggers: 2 periodic loops; 44 concrete OVSDB event classes (+ 11 base classes), 5 to 18 registered per driver.
  • Exceptions: 20 agent classes (ovn_bgp_agent/exceptions.py, ovn_bgp_agent/drivers/openstack/nb_exceptions.py) + RuntimeError/KeyError/SystemExit sites; 16 defects listed, 4 reproduced by running.
  • Configuration options: 35 agent options in 4 groups (21 [DEFAULT], 1 [agent], 8 [ovn], 5 [local_ovn_cluster]) (01 § 5).
  • Rewrite pack: 245 event-match vectors (245/245 replay), 11 side-effect scenarios (11/11 as expected).

Points of attention

  1. **The NB driver with exposing_method = underlay is broken on this branch (D16)**: since commit ccf4c29 (5.0.0), ensure_base_wiring_config replaces the driver's empty routing-table dict, so provider IPs are not wired or announced and every sync fails with KeyError: '<bridge>' (ovn_bgp_agent/drivers/openstack/utils/wire.py:34-38). Reproduced; the unit tests mock the function. Anyone deploying the NB driver from this release should check the logs for Unexpected exception while wiring provider port.
  2. No status feedback: failures are only logs; nothing tells Neutron or the operator that an IP is not announced. The only repair is the next sync (300 s by default).
  3. Exposure of a new provider network's first VM is delayed (D1): the OVS patch port does not exist yet, the exception type mismatch skips the announcement until the next sync.
  4. **Event processing races with sync**: matches read caches that sync clears; _SYNC_STATE_LOCK read locks never exclude anything (D11). Correctness rests on the periodic resync.
  5. FIP announcement point depends on a Neutron flag (neutron:fip-distributed) whose default differs between Neutron (centralized) and the agent (distributed when absent); the agent warns at start.
  6. Cost on large clouds: full scans of SB Port_Binding (monitored unconditionally) at every sync and FIP lookup; vtysh -f every 15 s.
  7. Options accepted but unsupported: exposing_method = l2vni|dynamic fail at every NB sync (D10); ovn_evpn_driver is declared unsupported by the project; with exposing_method = ovn, tenant networks are not implemented and BFD is likely broken (D14).
  8. EVPN: rd None:<vni> rendered without evpn_local_ip (D15); set_device_status TypeError for VLAN provider networks in the SB EVPN driver (D2).
  9. Security: privsep with CAP_SYS_ADMIN and CAP_DAC_OVERRIDE; FRR configuration is passed to the privileged daemon as a path to a temporary file (mode 0600, owned by the agent user) that root reads; the OVN SSL files are set process-wide for all connections.

Blind spots / [inferred]

  • Nothing was run against a real OVN, kernel or FRR: the event vectors come from unit tests (mocked agents), the side effects from a fake node at the privilege boundary. Functional tests (ovn_bgp_agent/tests/functional/) need an OVN deployment and were not run.
  • exposing_method = ovn and NB vrf (EVPN) were read, not executed; D14 is inferred.
  • Behaviour of FixedIntervalLoopingCall under oslo.service 4.x (threads vs eventlet) and first-tick timing were not verified.
  • The stretched-L2 driver's use of pyroute2 route objects and its event/sync asymmetry are [inferred].
  • No unit test covers the centralized-FIP, gateway-move FIP and port-forwarding events: their decision tables have no vectors.
  • devstack/, roles/, playbooks/ (deployment tooling) were not analysed.

Source: reverse-spec-ovn-bgp-agent/00-summary_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.