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:= ovsdbappstable/2026.2@0fb5a1b9a675;neutron-lib:= neutron-libstable/2026.2@1ee72052251a.
| File | Content |
|---|---|
| 01-drivers-and-exposure | what the agent exposes, drivers × exposing methods, configuration reference, lifecycle of an exposed IP (replaces the REST catalogue) |
| 02-errors | exceptions with situations, asynchronous errors, key logs, 16 defects (4 reproduced) |
| 03-interactions | OVS DB, OVN SB/NB (tables, columns, Neutron external_ids), node-local NB writes, FRR texts, netlink, sysctl, OVS commands, privsep contexts |
| 04-scenarios | 6 sequence diagrams with diagnostics |
| 05-async-processing | every trigger: OVSDB events per driver, sync, frr_sync, reconnection, concurrency |
| 07-rewrite-pack | contracts for a re-implementation, event decision vectors (245/245 replay), side-effect scenarios (11/11) |
| _verification | reference 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
| Process | Entry point | Role | Listens to / consumes |
|---|---|---|---|
ovn-bgp-agent | ovn_bgp_agent.cmd.agent:start → ovn_bgp_agent/agent.py:75 | load one driver, run its OVN event handlers and the two loops | OVN SB or NB (OVSDB monitor_cond), timers |
| privsep daemons (3) | ovn_bgp_agent/privileged/__init__.py:18-42 | execute netlink/sysctl, ovs-*, vtysh with capabilities | requests from the agent |
External dependencies
| System | Protocol | Library | Configuration | Usage |
|---|---|---|---|---|
| OVN SB / NB | OVSDB JSON-RPC (tcp/ssl/unix) | ovsdbapp, ovs | [ovn] ovn_sb_connection / ovn_nb_connection or OVS external_ids | read rows, receive events |
| local OVS DB | OVSDB | ovsdbapp | ovsdb_connection | chassis identity, remotes, bridge mappings |
| node-local OVN NB | OVSDB | ovsdbapp | [local_ovn_cluster] | router/policies/routes/BFD/static MAC bindings (exposing_method = ovn) |
| Linux kernel | rtnetlink, sysctl, ip | pyroute2, oslo.privsep | bgp_nic, bgp_vrf, bgp_vrf_table_id | announcement and traffic steering |
| OVS | ovs-vsctl, ovs-ofctl, ovs-appctl | oslo.concurrency | bridge mappings | flows, ports |
| FRR | vtysh | oslo.concurrency, Jinja2 | bgp_AS, bgp_router_id | VRF leak, EVPN VRFs, IPv6 RA |
Key figures
- REST endpoints: 0. RPC: 0. Database tables: 0.
- Drivers: 4 (
ovn_bgp_driverdefault,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/SystemExitsites; 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
- **The NB driver with
exposing_method = underlayis broken on this branch (D16)**: since commitccf4c29(5.0.0),ensure_base_wiring_configreplaces the driver's empty routing-table dict, so provider IPs are not wired or announced and everysyncfails withKeyError: '<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 forUnexpected exception while wiring provider port. - 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). - 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. - **Event processing races with
sync**: matches read caches thatsyncclears;_SYNC_STATE_LOCKread locks never exclude anything (D11). Correctness rests on the periodic resync. - 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. - Cost on large clouds: full scans of SB
Port_Binding(monitored unconditionally) at every sync and FIP lookup;vtysh -fevery 15 s. - Options accepted but unsupported:
exposing_method = l2vni|dynamicfail at every NB sync (D10);ovn_evpn_driveris declared unsupported by the project; withexposing_method = ovn, tenant networks are not implemented and BFD is likely broken (D14). - EVPN:
rd None:<vni>rendered withoutevpn_local_ip(D15);set_device_statusTypeErrorfor VLAN provider networks in the SB EVPN driver (D2). - Security: privsep with
CAP_SYS_ADMINandCAP_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 = ovnand NBvrf(EVPN) were read, not executed; D14 is inferred.- Behaviour of
FixedIntervalLoopingCallunder 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.