An API-first BGP daemon in Rust for IXP route servers, route reflectors, and automation-heavy control planes. gRPC is the primary interface for all peer lifecycle, routing, and policy operations — the config file bootstraps initial state, then gRPC owns the truth. No restarts to add peers, change policy, or inject routes. And every route decision can explain itself from the live RIB: per-peer received / best / advertised views, policy and export-gate explain, retained rejected routes with reasons, BMP/MRT/metrics — with receipt-backed interop behind each claimed behavior.
Measured, not marketed — every number below links to its published, reproducible receipt:
- Policy reload at IXP scale (700 route-server clients × 400,400 routes, live churn, same harness / same host): new policy fully delivered to every member in 1.5–2.2 s p50 vs BIRD 3.3.1's 77–86 s and OpenBGPD 9.1's 249–253 s — IXP receipt matrix
- Member-flap propagation (50 members flap, 650 observers): re-announce p50 0.46–0.49 s vs BIRD's 2.8–4.2 s and OpenBGPD's 21–22 s; withdraw p50 0.28–0.48 s, also fastest — same matrix
- Cold start: full 400,400-route table delivered to all 700 members in 4.9–5.1 s vs 59.0–62.1 s (BIRD) and 396.1–417.3 s (OpenBGPD) — same matrix
- Route-reflector scale: 1,000 RR clients × 100k routes converge on the wire in 1.82 s at 419 MiB whole-process RSS — 1000-peer scale receipt
- The losses, stated plainly: OpenBGPD holds a smaller reload stall (p50 0.25–0.29 s vs rustbgpd's 0.43–0.84 s) and BIRD wins settled memory outright (408/416 MiB vs rustbgpd's 768/763 MiB at the matrix shape) — published in the same receipt, methodology and fairness protocol included
Status: public alpha. Feature-complete for the initial programmable control-plane target and expanding toward cloud / AI-scale data-center fabric use.
Alpha expectations: The config format and gRPC API are not yet frozen. Breaking changes are possible between minor versions. The daemon runs on Linux (the primary target); other platforms are not tested. See Project Status for details.
The fastest way to see rustbgpd in action. Spins up the daemon with an FRR peer that advertises sample IPv4 and IPv6 prefixes — no real routers needed.
cd examples/docker-compose
docker compose up -dOnce both containers are running (a few seconds):
# See the FRR peer come up
docker compose exec rustbgpd rbgp -s http://127.0.0.1:50051 summary
# Browse the RIB
docker compose exec rustbgpd rbgp -s http://127.0.0.1:50051 rib
# Live TUI dashboard — sessions, prefix counts, message rates
docker compose exec rustbgpd rbgp -s http://127.0.0.1:50051 topPress q to exit the TUI. When you're done: docker compose down.
Policies are written in .rpol — a typed, compiled language with named
prefix/community sets (indexed matchers, not linear walks), parameterized
policies, composition, and unit tests in the policy file itself. From the
shipped route-server example:
policy ixp-hygiene {
# AS_SETs are deprecated (RFC 9774); reject them like arouteserver does.
term reject-as-set { if route.as-path matches "\\{" { reject } }
term reject-aspa-invalid { if route.aspa == invalid { reject } }
# Tag the RPKI outcome as an RFC 8097 extended community for members.
term tag-ov-valid { if route.rpki == valid { add ext-community OV_VALID } }
}
test as-set-is-rejected {
route { prefix 203.0.113.0/24; as-path "64501 {64502 64503}" }
expect ixp-hygiene == reject
}
Then ask the daemon what would happen — before you commit anything:
rbgp policy check hygiene.rpol # offline: compile + run the in-language tests
rbgp policy test hygiene.rpol --policy ixp-hygiene --direction import
# read-only dry run against the LIVE RIB:
# accept/reject/modify counts, per-term hits
rbgp rib --prefix 203.0.113.0/24 advertised 198.51.100.7 --explain
# walk the real export gate ladder to one peer
rbgp policy stats # live per-term hit counters once installedEdits hot-apply on SIGHUP, .rpol mixes freely with the existing TOML policy
chains, and FRR route-map parity is proven route-for-route in interop (M80).
Language reference: docs/rpol-language.md · explain
surfaces: docs/explain.md · IXPs on arouteserver can render
config from their existing general.yml/clients.yml:
IXP filter-pipeline tutorial.
- API-first control plane — full gRPC surface across 11 services plus a
thin CLI (
rbgp): dynamic peer management, policy CRUD, route injection, streaming events, all without restarts - Native route explainability — "why is this route (not) here?" answered from the live RIB in one command, where incumbents need an external looking-glass stack for less (docs/explain.md)
- Update-group fanout — peers with provably identical staged output share one staging pass: ~28x faster 100k-route convergence at 256 uniform RR clients (15.1 s to 0.54 s); v2 extends sharing to VPNv4/v6 with per-member RT filtering at emit (receipt)
- Full BMP monitoring trio — per-collector Adj-RIB-In / Adj-RIB-Out (byte-exact wire PDUs) / Loc-RIB on one exporter, validated against pmacct, gobmp, and tshark at once
- Modern protocol surface — MP-BGP, Add-Path, GR/LLGR, RPKI/RTR + ASPA, FlowSpec, Prefix ORF, large/extended communities — plus VPNv4/v6, RT-Constrain, labeled-unicast, and BGP-LS reflection, and RFC 9107 Optimal Route Reflection (per-client best paths via SPF over BGP-LS topology — a capability no other open-source BGP daemon ships)
- Explicit architecture — pure FSM with no I/O, single-owner RIB with no
locks, bounded channels; no
Arc<RwLock>on routing state (ARCHITECTURE.md) - Reusable crates —
rustbgpd-wire(zero internal deps) andrustbgpd-fsmare published for BGP tooling that doesn't need the router
The full-depth version of each item — the complete observability surface, the BMP/BMPv4 details, the ADR-0077 route-reflector family boundary, the VPN fanout numbers — is the feature tour.
- Internet exchange route servers — transparent mode, Add-Path, per-client best-path (RFC 7947 path-hiding mitigation), RPKI, Prefix ORF, per-member policy
- Route reflectors — including VPNv4/v6, RT-Constrain, labeled-unicast, and BGP-LS reflection, GR/LLGR, and RFC 9107 Optimal Route Reflection
- DDoS mitigation platforms — FlowSpec + RTBH route injection from automation
- Cloud / AI-scale data-center fabrics — API-first BGP control, BFD, ECMP, EVPN/VXLAN alpha, and whitebox-friendly interop surfaces
- Hosting provider prefix management — API-driven customer prefix announcements
- SDN / network automation controllers — programmable BGP control plane
- Route collectors and looking glasses — structured data via gRPC, MRT, BMP,
plus a Birdwatcher-shaped status/peer/accepted/filtered/noexport subset via
the external
examples/birdwatcher-adapter - Lab and test environments — clean API, structured logs, containerlab interop
See docs/USE_CASES.md for detailed deployment scenarios with architecture diagrams, example configs, and API workflows, and the feature tour for exactly which route-reflector families have shipped and where the ADR-0077 scope boundary sits.
- Full general-purpose router deployments expecting default-on, fully policy-guarded FIB integration — Linux FIB integration is default-off and scoped to RFC 7999 discard routes and configured unicast tables (including ECMP and weighted multipath)
- Large-scale production EVPN fabrics that need the full feature surface — VXLAN EVPN is functional and FRR-interop-tested but still alpha. VXLAN local-bias split-horizon remains the one open all-active correctness gate (ASIC/offload-dependent on the Linux softswitch — see ADR-0065); service-provider EVPN families such as MPLS / PBB / MVPN are deliberately out of the current VXLAN/Linux lane. See Current limitations for the alpha boundary and docs/evpn-enablement.md for the shipped feature ladder and standards-tail map
- VPNv4 / VPNv6 PE roles — VRF import, MPLS label forwarding, and CE-facing attachment circuits are out of scope; the shipped SAFI-128 support is the route-reflector / controller-feed slice only
- Environments that need the breadth of FRR's multi-decade feature surface
- Operators who want a CLI-first operational model
See docs/COMPARISON.md for a detailed feature comparison with FRR, BIRD, GoBGP, and OpenBGPd.
Every tagged release ships static-named per-arch tarballs, so
releases/latest/download/ always fetches the current version:
SUFFIX=linux-amd64 # or linux-arm64
curl -fLO "https://github.com/lance0/rustbgpd/releases/latest/download/rustbgpd-${SUFFIX}.tar.gz"
curl -fLO "https://github.com/lance0/rustbgpd/releases/latest/download/checksums-${SUFFIX}.txt"
sha256sum -c "checksums-${SUFFIX}.txt"
tar -xzf "rustbgpd-${SUFFIX}.tar.gz"
sudo install -m 0755 rustbgpd rbgp /usr/local/bin/The tarball also carries man pages and bash/zsh/fish completions under
share/ — the install walkthrough covers
installing those and pinning a specific version.
# Prerequisites: Rust 1.95+, protobuf-compiler
sudo apt-get install -y protobuf-compiler # Debian/Ubuntu
cargo build --release -p rustbgpd -p rustbgpctl
# Binaries are at target/release/rustbgpd and target/release/rbgpRelease images are published to GHCR (versioned tags, e.g.
ghcr.io/lance0/rustbgpd:0.60.0), or build locally:
docker build -t rustbgpd . # lean runtime: daemon + rbgp, nonroot
docker build --target dev -t rustbgpd:dev . # dev/interop image (lab helpers, root)For running rustbgpd on a real host with real peers, see
docs/QUICKSTART.md. It covers starter config generation,
--check / --diff, local UDS access, HTTP probes, runtime peer operations,
remote mTLS access, standalone Docker, and systemd.
The cookbook has complete receipt-proven recipes for
the common deployment shapes: iBGP route reflector at scale, L3VPN reflection,
IXP route server, BMP/event/MRT monitoring feed, EVPN fabric RR, and .rpol
policy. IXPs running arouteserver can render rustbgpd configuration from their
existing general.yml/clients.yml and wire up an Alice-LG looking glass —
the IXP filter-pipeline tutorial walks
it end to end.
For operators coming from FRR, BIRD, or ARouteServer, the CLI keeps familiar
entry points for the daily checks: rbgp summary, rbgp rib recv <peer>,
rbgp rib sent <peer>, rbgp policy counters, and rbgp doctor for a
redacted support bundle. See the CLI command map.
The IXP route-server receipt matrix runs rustbgpd, BIRD 3.3.1, and OpenBGPD 9.1 through the same harness on the same host — 700 route-server clients × 400,400 routes with live churn, each incumbent at its documented strongest configuration, receiver-side timestamps, two independent campaign runs, losses published alongside wins:
| KPI (700 clients × 400,400 routes, p50) | rustbgpd | BIRD 3.3.1 | OpenBGPD 9.1 |
|---|---|---|---|
| Sessions Established | 0.6 s | 17.3–19.7 s | 124.4–141.4 s |
| Cold start, full table to all members | 4.9–5.1 s | 59.0–62.1 s | 396.1–417.3 s |
| Reload: UPDATE stall | 0.43–0.84 s | 1.61–2.29 s | 0.25–0.29 s |
| Reload: new policy fully delivered | 1.5–2.2 s | 77–86 s | 249–253 s |
| Flapstorm: withdraw propagation | 0.28–0.48 s | 0.45–0.61 s | 10.84–12.43 s |
| Flapstorm: re-announce | 0.46–0.49 s | 2.8–4.2 s | 21–22 s |
| Settled RSS (S2, runs A/B) | 768 / 763 MiB | 408 / 416 MiB | 769 / 767 MiB |
rustbgpd is the only daemon in the matrix holding both a sub-second median stall and single-digit-seconds completion; OpenBGPD has the smallest stall at every scale rung, and BIRD wins memory outright. The receipt includes the full method, configuration disclosure, honesty notes, raw artifacts — and a post-publication note where the receipt's own tables exposed a rustbgpd re-announce plateau that was root-caused, fixed, and rerun (9.5–9.8 s → 0.46–0.49 s).
At route-reflector shapes, the 1000-peer scale receipt measures 1,000 uniform RR clients × 100k routes converging on the wire in 1.82 s at 419 MiB whole-process RSS, and 1,000 clients × 100k VPNv4 in 12.60 s / 625 MiB uniform and 3.92 s / 636 MiB with heterogeneous ~10% RT memberships (vs ~73 s / ~31 GiB and ~12.5 s / ~5.7 GiB extrapolated per-peer), with a one-RT membership flip delivering its 1600-route delta in ~15 ms with zero policy evaluations.
Microbenchmarks, memory scaling, and the bgperf2 cross-daemon comparison: docs/BENCHMARKS.md. Every receipt is indexed in docs/RECEIPTS.md; GoBGP-specific parity is in docs/gobgp-parity.md.
Eleven native rustbgpd.v1 services cover the daemon's operational surface —
Global, Config, Neighbor, Policy (22 RPCs including explain, dry-run, and
per-term stats), PeerGroup, Rib, BFD, Event, Injection, Control, and Evpn —
plus a separate gnmi.gNMI service for OpenConfig BGP telemetry and the first
transaction-backed config subset.
# Stream route changes in real time over the default UDS listener
grpcurl -plaintext -unix /var/lib/rustbgpd/grpc.sock \
-import-path . -proto proto/rustbgpd.proto \
rustbgpd.v1.RibService/WatchRoutesConfig changes get the full Junos-style transactional quartet: rbgp config plan (commit check), rbgp config diff (show compare, annotated with live
reload impact), rbgp config apply --confirm-id --confirm-timeout (commit
confirmed, with a crash-safe boot revert), and rbgp config rollback N
against a bounded on-disk history of applied configs — rollback routes
through the same transaction engine as apply, so it gets the same impact
preview, receipts, and confirm window. Details:
docs/OPERATIONS.md.
The full service/RPC table and per-RPC examples: docs/API.md. gNMI operator guide: docs/GNMI.md.
rustbgpd is intentionally built around:
- gRPC-driven control instead of a large interactive CLI surface
- A pure FSM crate with no I/O —
(State, Event) -> (State, Vec<Action>) - Single-owner routing state instead of shared mutable state across tasks
- Bounded channels for all inter-task communication — backpressure, not locks
- Explicit protocol feature boundaries with ADRs and test-backed development
Designed around an API-first operating model similar to GoBGP, with a smaller and more explicit internal architecture. Rationale: docs/DESIGN.md; crate graph and runtime model: ARCHITECTURE.md.
| Example | Description |
|---|---|
examples/docker-compose/ |
Quick-start with Docker Compose — rustbgpd + FRR peer with sample routes |
examples/minimal/ |
Smallest working config — single eBGP peer |
examples/route-server/ |
IXP route server with RPKI, Add-Path + per-client best-path, rpol hygiene policy |
examples/ddos-mitigation/ |
FlowSpec + RTBH for automated DDoS mitigation |
examples/hosting-provider/ |
iBGP route injector for customer prefix management |
examples/linux-edge-fib/ |
Linux edge host with explicit ADR-0061 [[fib_tables]] unicast FIB programming |
examples/route-collector/ |
Passive collector with MRT dumps and BMP export |
examples/rr-evpn-fabric/ |
EVPN Route Reflector for a VXLAN-EVPN DC fabric (RFC 7432, RR role) |
examples/evpn-vtep-leaf/ |
Leaf VTEP with local [[evpn_instances]] declarations (declarative EVPN instance schema) |
examples/envoy-mtls/ |
Remote gRPC access via Envoy mTLS proxy |
examples/systemd/ |
systemd unit file with security hardening |
- Default listener: Unix domain socket at
/var/lib/rustbgpd/grpc.sock— local-only, no TCP exposure - Optional read-only listeners: expose monitoring/query RPCs without exposing mutating control RPCs
- Remote access: native gRPC mTLS on the TCP listener (
tls_cert_file/tls_key_file/tls_client_ca_file), or an Envoy mTLS proxy front-end for multi-host fan-out — never plaintext TCP off-host - Network controls: put gRPC on a management VLAN/interface and firewall it to known hosts
Full guidance and deployment tiers: docs/SECURITY.md.
Evidence-driven development: fuzz targets on the wire decoder, property tests on the FSM, automated containerlab interop, extensive workspace tests, and an architecture decision record for every protocol and design choice.
| Evidence | Details |
|---|---|
| Workspace tests | Unit, integration, and property tests (cargo test --workspace) |
| Wire fuzzing | libFuzzer harnesses on message and attribute decoders, run nightly in CI |
| Interop suites | Automated interop suite (see docs/INTEROP.md for the full matrix), primarily against FRR 10.3.1 plus GoBGP 3.37.0–4.6.0 across labs and StayRTR-backed RTR coverage; BIRD 2.0.12 covers M0 and BIRD 3.3.1 covers the TCP-AO smoke. A foundation tier is gated on every PR, privileged Linux dataplane smokes run in hosted kernel-dataplane CI, and longer soaks / platform-diversity scripts remain local. |
| Operational proof | Consolidated receipts for CI interop, hosted kernel dataplane, benchmarks, memory profiles, and archived 24 h soaks live in docs/OPERATIONAL_PROOF.md. |
| Protocol coverage | Supported standards at a glance plus per-RFC conformance notes in docs/RFC_NOTES.md; interop matrix in docs/INTEROP.md and receipts in docs/RECEIPTS.md. |
| Architecture decisions | ADRs documenting every protocol and design choice (docs/adr/) |
# Run interop tests
containerlab deploy -t tests/interop/m4-frr.clab.yml
bash tests/interop/scripts/test-m4-frr.shSee docs/INTEROP.md for full procedures and results.
The short version: rustbgpd is still not a general-purpose router replacement. Linux FIB integration is opt-in, EVPN is Linux/VXLAN alpha, VPNv4/VPNv6 is RR / controller-feed only, and a few transport/runtime edges remain deliberately scoped. See docs/LIMITATIONS.md for the full boundary.
Alpha — suitable for lab, data-center fabric pilots, IX route-server pilots, and programmable control-plane deployments where you are comfortable with an evolving API.
| Dimension | Current state |
|---|---|
| Target use case | Data-center fabric pilots, IXP route servers, programmable BGP control planes, lab/test environments |
| Maturity | Public alpha (v0.60.0) |
| Narrow stable contract | The machine-pinned route-server / route-reflector v1 contract covers only its inventoried control-plane roles and surfaces; the project and all unlisted features remain alpha. |
| Implemented | Dual-stack BGP/MP-BGP, Add-Path, GR/LLGR, RPKI/RTR, ASPA path verification, FlowSpec, BMP, MRT, BFD, EVPN/VXLAN (alpha), and full gRPC/CLI management. Linux FIB integration is default-off and scoped to RFC 7999 discard routes and configured unicast tables (including ECMP and weighted multipath); broader routing-suite features remain future work. |
| Supported OS | Linux (primary target). Requires CAP_NET_BIND_SERVICE for port 179. |
| Runtime | Rust 1.95+ (workspace MSRV — set by the bundled SQLite build), single binary, no external dependencies except optional RPKI/BMP/MRT backends |
| Config stability | Inventoried RS/RR v1 fields follow the narrow compatibility policy; unlisted TOML may change between minor versions with migrations documented in CHANGELOG. |
| API stability | Inventoried native gRPC/CLI/JSON surfaces follow the narrow v1 policy; unlisted API remains alpha and may evolve between minor versions. |
| Not yet supported | EVPN runtime L3VNI/device/table IP-VRF identity changes (restart-required by design), true RFC VLAN-aware bundle VTEP origination + dataplane (non-zero Ethernet Tag RR receive/reflect shipped, M82), EVPN route types 6-11 / PBB / MVPN / MPLS/SRv6 service encapsulation, BGP-LS local topology production, Confederation, TCP-AO live selection/deprecation/deletion or runtime protected-range CRUD (ordered keyrings and add-only successor installation on SIGHUP are supported) |
| Tests | Workspace test suite, fuzz targets, an automated interop suite (see docs/INTEROP.md) primarily against FRR plus GoBGP / StayRTR / documented BIRD coverage, and an in-tree EVPN load generator (foundation tier gated on every PR; privileged kernel dataplane smokes run on GitHub-hosted CI) |
| Document | Content |
|---|---|
| docs/feature-tour.md | The full-depth feature tour behind the README highlights |
| docs/cookbook/ | Scenario recipes with receipt-proven configs: RR at scale, L3VPN RR, IXP route server, monitoring feed, EVPN fabric RR, policy quickstart |
| docs/USE_CASES.md | Deployment scenarios: DDoS, hosting, IX, SDN, collector |
| ARCHITECTURE.md | Crate graph, runtime model, ownership, data flow |
| docs/DESIGN.md | Tradeoffs, protocol scope, rationale |
| docs/API.md | gRPC API reference with examples for every RPC |
| docs/CONFIGURATION.md | Config reference and examples, plus editor integration via the shipped JSON Schema (docs/rustbgpd.schema.json) |
| docs/QUICKSTART.md | Bare-metal first run: starter config, validate, run, verify, operate |
| docs/LIMITATIONS.md | Current product boundaries and known non-goals |
| docs/deployment.md | End-to-end install + lifecycle walkthrough: systemd, Docker, containerlab quick-start, upgrade, sample profiles |
| docs/reload-matrix.md | Per-field reload classification: which keys hot-apply, which need a restart, which are rejected at parse time |
| docs/OPERATIONS.md | Running in production: reload, upgrade, failure modes, debugging |
| docs/explain.md | The explain surfaces: why a route was selected, advertised, imported, or rejected |
| docs/SECURITY.md | Security posture, firewall guidance, deployment tiers |
| docs/BENCHMARKS.md | Wire codec and RIB performance numbers, scaling analysis |
| docs/OPERATIONAL_PROOF.md | Consolidated operational proof receipts: CI interop, dataplane, benchmarks, memory, soak |
| docs/RECEIPTS.md | Full receipts index: every M-series interop lab, perf/scale receipt, archived soak, and CI schedule |
| docs/GRAFANA.md | Grafana overview dashboard: import instructions and Prometheus scrape config |
| docs/COMPARISON.md | Feature comparison with FRR, BIRD, GoBGP, OpenBGPd |
| docs/INTEROP.md | Interop test coverage and results |
| docs/evpn-enablement.md | EVPN Phase 1-9 gate ladder: what each gate unlocks, work per gate, priority |
| docs/evpn-vtep-setup.md | EVPN VTEP kernel setup: ip link recipes for L2VNI / IP-VRF / multi-homing mapped to the ADR-0054 §4 + ADR-0058 §3 readiness checks (operator-provisioned netdevs) |
| docs/evpn-vtep-troubleshooting.md | EVPN VTEP alpha troubleshooting runbook |
| docs/gobgp-parity.md | rustbgpd vs GoBGP feature parity by use case |
| docs/adr/ | Architecture decision records — one per protocol and design choice |
| docs/RELEASE_CHECKLIST.md | Pre-release smoke matrix and release steps |
| docs/v1-stable-contract.md | Narrow machine-pinned v1 compatibility contract for proven route-server / route-reflector roles |
| ROADMAP.md | Remaining gaps and planned work |
| CHANGELOG.md | Release history |
| CONTRIBUTING.md | Development setup, code style, PR process |
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

