The page opened with every session in bold green, the normal state, and the brightest numbers on it were the rejection counts, which RPKI doing its job produces by the thousand. The two sessions that were actually down were in the same red, thirty rows down. Now: - A status line at the top says what needs attention, by name and with the reason: sessions down, peers restarting, the kernel behind or refusing routes, RPKI data missing or about to expire. When nothing does, it says so. A second line gives the normal state in grey. - Colour means one thing each. Red: failed, needs a hand. Amber: degraded, worth watching. Green, set small: a system doing its job. Grey: inactive and expected. Normal is black; "Established" is no longer green, and a rejection count no longer red. - Peers that need attention come first, then the others grouped by what they are to us, with a "problems only" switch. Numbers are right aligned with thousands separators; the established time and uptime are one cell; the session's properties are glyphs (v4, v6, GR, ENH, AP, 2B) with the meaning as a tooltip, as are the roles. - Received routes: the best route leads, marked ★; attributes without a column are glyphs (OTC, AA, AGG, AS4, OID, CL); validity is ✓ ✗ –. - Rejected routes: those alike (same prefix, reason and path) are one row with a count and the last time; each peer's reasons are a bar. - Communities with a configured name (community_names, new) are badges with that name, the number as the tooltip: "comrack", "SwissIX", "interconnection 2011" rather than 210036:100:2 and so on. A name for a pattern shows the open part after it. The daemon does nothing with the names but pass them to the page. - One lookup box at the top, which takes a peer's name too; a peer's name anywhere on the page leads to its routes; table headers and the status line stay in view while scrolling. - The host name comes from gethostname(2), not from running `hostname`, which a static binary on a bare machine could not find: comrack said "unknown host". Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Ferrix BGP
An implementation of the Border Gateway Protocol, which is used to exchange routing and control plane information between Autonomous Systems.
The aim of this project is to provide a modern, high performance, secure, programmatic and customizable software package that can be useful to network operators, researchers, and people interested in Internet.
Current status
The daemon establishes BGP sessions with configured neighbors, evaluates received routes against import policy, validates them with the RPKI (route origin validation and ASPA), selects the best path for each prefix, and, on Linux, installs it in the kernel. It advertises the routes that it originates and, to neighbors configured for it, the best paths learned from other neighbors, as BGP roles (RFC 9234) and communities permit.
Ferrix has not been deployed in a production network.
Unsupported Features
- Per-client best path selection for route servers, and ADD-PATH for advertised routes
- TCP-AO, TCP MD5, and GTSM
- Long-Lived Graceful Restart, BFD, and configuration changes without a restart
- Recursive resolution of next hops that are not directly connected
Layout
| Crate | What is in it |
|---|---|
crates/primitives |
Prefixes, address families, parsing helpers |
crates/packet |
The wire format: messages, attributes, capabilities |
crates/rib |
The routing table, best route selection, the journal of changes |
crates/rpki |
The RTR client; origin validation and ASPA path verification |
crates/fib |
The best routes in the Linux kernel, over netlink |
crates/server |
Sessions, the state machine, policy, configuration |
crates/web |
The status page, HTTP API and metrics |
crates/integration-tests |
A test server and test peers, and the tests that run the daemon end to end |
crates/bench |
Benchmarks at the scale of the Internet routing table |
bin/bgp |
The daemon |
Documentation
The documentation is a website built from docs/ with
Zola:
zola --root docs serve # http://127.0.0.1:1111
- Overview, installation and quick start
- User guide: BGP neighbors, import policy, BGP roles, RPKI, kernel route installation, route advertisement, graceful restart, configuration examples
- Deployment and monitoring
- Reference: configuration, command line, HTTP API, metrics, supported standards
- Architecture, testing and contributing
Development
CI runs these on every push, and fails on any warning:
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --document-private-items
zola --root docs build
It also runs the tests that need a real Linux kernel
(scripts/kernel-tests.sh) and the lab with FRR, BIRD and Routinator
(scripts/interop/lab.sh); scripts/linux-vm.sh runs either from macOS.
Lints are configured once, under [workspace.lints] in the root Cargo.toml.
unsafe code is forbidden throughout.
cargo test includes property tests: generated messages must survive being
written and read back, and no input, however damaged, may make a parser
panic. They take about a second; for a longer hunt:
PROPTEST_CASES=1000000 cargo test --release -p bgp-packet --test properties
Coverage-guided fuzz targets for the same parsers are in fuzz/; see
fuzz/README.md. CI runs each of them for a minute.
License
Apache License 2.0; see LICENSE.