rustbgpd
- Established
- 0.8 s
- Base-table delivery
- 2.8 s
steel withdraw · orange re-announce
A BGP route server and route reflector in Rust.
Animated topology of a BGP flapstorm. A steel withdrawal wave, then a Ferris-orange re-announce flood. Withdraw p50 0.47 seconds. Re-announce 0.55 seconds. Press R or use Replay to run it again.
Field reports. Not receipts.
Field report · 2026-08-26
First contact with the default-free zoneTwo live full tables. 136 observed AS_SET dispositions. Not a receipt.
Matrix · 2026-08-20
700 clients, 400,400 routesPolicy reload in 1.4s where BIRD takes 80s. Canonical on lance0.com.
verified IXP Manager 7.4 Bird's Eye API compatibility with documented BIRD-internal divergences.
Pinned IXP Manager v7.4.0 consumer journeys against BIRD 2.0.12 + Bird's Eye 2.1.0. Fail-closed allow-list; remaining divergences are named under Honesty. [source contract]
Route views match the pinned oracle's field shapes. Protocol and export lookups use its longest-match behavior; fallback scans stay within the queried address family and have a separate route-scan bound. An incomplete scan returns HTTP 403 instead of evaluating a partial view.
700 clients × 400,400 routes, same host, same harness. Time for all 700 sessions to reach Established, then for every observer to hold the full base table. rustbgpd v0.75.0 and OpenBGPD 9.3 ran on one host in the same night, 2026-10-04 to 2026-10-05, three runs each with the daemon order alternated. The BIRD 3.3.2 row is dated: it was measured the night before, 2026-10-03 to 2026-10-04, against rustbgpd v0.74.0. BIRD 3.3.3, released 2026-10-01, is not yet measured.
| Daemon | Established | Base-table delivery |
|---|---|---|
| rustbgpd | 0.8 s | 2.8 s |
| BIRD 3.3.2 (dated) | 15.2–17.8 s | 67.3–70.1 s |
| OpenBGPD 9.3 | 88.6–182.5 s | 325.2–417.8 s |
Six legs per daemon (S2 + S3 × three runs). [source receipt]
700 clients × 400,400 routes, same host, same harness. 50 members hard-close simultaneously; 650 survivors observe 28,600 withdrawn prefixes. The 50 reconnect and re-announce. rustbgpd v0.75.0 and OpenBGPD 9.3 ran on one host in the same night, 2026-10-04 to 2026-10-05, three runs each with the daemon order alternated. The BIRD 3.3.2 row is dated: it was measured the night before, 2026-10-03 to 2026-10-04, against rustbgpd v0.74.0. BIRD 3.3.3, released 2026-10-01, is not yet measured.
| Daemon | Withdraw p50 | Re-announce p50 |
|---|---|---|
| rustbgpd | 0.20–0.26 s | 0.29–0.33 s |
| BIRD 3.3.2 (dated) | 0.68–0.99 s | 3.27–4.06 s |
| OpenBGPD 9.3 | 8.45–9.71 s | 17.55–18.06 s |
The re-announce clock starts only after all 50 sessions re-reach Established, so it measures re-delivery fan-out (~18.6M NLRI), not reconnect pacing. [source receipt]
700 clients × 400,400 routes, same host, same harness. SIGHUP policy reload stall and completion — not the IRR filter refresh below. rustbgpd v0.75.0 and OpenBGPD 9.3 ran on one host in the same night, 2026-10-04 to 2026-10-05, three runs each with the daemon order alternated. The BIRD 3.3.2 row is dated: it was measured the night before, 2026-10-03 to 2026-10-04, against rustbgpd v0.74.0. BIRD 3.3.3, released 2026-10-01, is not yet measured.
| Daemon | Stall p50 | Stall worst | Completion p50 | Completion worst |
|---|---|---|---|---|
| rustbgpd | 0.157–0.196 s | 0.378 s | 0.75–0.91 s | 0.97 s |
| BIRD 3.3.2 (dated) | 1.767–2.531 s | 9.285 s | 89.1–103.6 s | 118.2 s |
| OpenBGPD 9.3 | 0.193–0.212 s | 0.268 s | 201.9–208.0 s | 208.1 s |
Stall = the longest gap between UPDATE arrivals at a member while the reload is in flight. Completion = every member verifiably holds the full new-policy table. The three reload paths are not the same amount of work: SIGHUP re-parses only rustbgpd’s policy files, birdc configure re-parses BIRD’s entire config and re-evaluates its filters, and bgpctl reload re-parses and soft-reconfigures OpenBGPD’s RDE. Each is that daemon’s documented route-server reload. [source receipt]
320 members × 183,040 prefixes, 0/10/50% received-view overlap. rustbgpd v0.75.0, BIRD 3.3.2 and OpenBGPD 9.3 in the same night, 2026-10-04 to 2026-10-05, three cross-daemon roots per overlap. BIRD 3.3.3, released 2026-10-01, is not yet measured. Every row 320/320 sessions. RSS is raw process-tree; daemon and container defaults differ, so it is not a ranked comparison.
| Daemon | Completion p50 | Sampler RSS peak |
|---|---|---|
| rustbgpd | 0.584–0.801 s | ~0.6–0.7 GiB |
| BIRD 3.3.2 | 12.926–14.810 s | ~1.3–1.4 GiB |
| OpenBGPD 9.3 | 44.010–63.948 s | ~1.2–1.5 GiB |
rustbgpd was 3.3–3.8 s at this shape in the earlier grouped per-client-best receipt, and 67–69 s ungrouped before ADR-0126. [source receipt] [source receipt]
Both green, both archived in-repo. No control daemon ran alongside them.
1,000 eBGP clients × 400,000 routes, 24 h
1,000 iBGP clients × 100,000 routes, 24 h
The receipts also include the losses.
At 700 × 400,400, OpenBGPD 9.3's worst single observer stalls 0.268 s vs rustbgpd v0.75.0's 0.378 s, and its stall p95 is 198–267 ms vs 217–365 ms. The stall p50 is close: rustbgpd's median is 177 ms vs 198 ms, about 10% lower, but the per-reload values overlap at the tails (157–196 ms vs 193–212 ms). At IRR scale with 50% received-view overlap, OpenBGPD's changed-observer gap p50 is also shorter, 377–517 ms vs 591–627 ms; at 0% and 10% the ranges overlap. [source receipt]
OpenBGPD 9.3 delivers the first re-announced route to each survivor in 0.10–0.17 s p50 (median 0.13 s) vs rustbgpd's 0.16–0.17 s (median 0.17 s). It then needs 17.55–18.06 s to finish the re-announce, vs rustbgpd's 0.29–0.33 s. [source receipt]
At the S2 reload shape the cgroup peaks are about even: rustbgpd's own scope read 1,003 / 914 / 1,068 MiB and OpenBGPD 9.3's container 1,005 / 991 / 991 MiB, so OpenBGPD's median is 11 MiB lower and the ranges overlap. rustbgpd's cgroup peak sits 349–508 MiB above its 559–568 MiB VmHWM; the cgroup also charges socket buffers and page cache. Settled, rustbgpd reads 368–370 MiB vs OpenBGPD's 796–804 MiB at S2, and 376–384 MiB vs 823–836 MiB under flap churn. [source receipt]
Dated, from the 2026-10-03 night: BIRD 3.3.2 had the lower peak RSS sample at both matrix shapes, 407–414 MiB vs rustbgpd v0.74.0's 540–541 MiB at S2 and 332–377 MiB vs 511–544 MiB at S3. Settled RSS under flap churn (S3) was mixed run by run (BIRD 377/332/373 MiB, rustbgpd 376/376/375 MiB); at S2 rustbgpd settled lower, 369/373/370 MiB vs 407/412/414 MiB. BIRD did not run in the v0.75.0 matrix, and BIRD 3.3.3, released 2026-10-01, is not yet measured. [source receipt]
The claim is scoped, not an unqualified Bird's Eye replacement. runtime_compatibility is true; a must_match divergence still re-blocks the flag. File-backed protocol aliases reload on SIGHUP; direct aliases stay startup-only. Product identity stays rustbgpd. Countdown timers and route-change counters stay unsupported; retained-reject namespace and retention metadata are extensions. Still named unsupported: defined-only reject-reason emission, a generic IXP Manager UI-filter policy engine, full-table counts, live hold/keepalive countdowns, and direct runtime alias reconfiguration. Config render and activation are the rs-config-render Foil path, not a Bird's Eye endpoint. 00 · [source contract]
rs-config-render publishes config.toml, policy/, and datasets/ as one immutable activation tree. If recover --apply stops on a later failure, it reports only the recovery steps that completed and keeps the nonzero result.
ghcr.io/lance0/rustbgpd:0.75.0, take a release tarball, or build from a checkout (protobuf-compiler required).