Readability, no change in behaviour, but for one log line: - The routes a peer holds from us were counted twice over, differently, in the exporter: once per learned-route batch and once per originated route. Learned::held_by_peer counts the learned ones in one place, and ExportLimits::exceeded_by returns the limit that was passed instead of a bool, so that ending the session no longer has to dig it out again with a default that could not happen. - The two hold-downs for a limit passed, ours or the peer's, were two near-identical blocks; they are one match. - How a session ended is put into words in one place (SessionEnd::reason), for the dialer's backoff and the passive peer's state alike. - parse_export_limits parses one block; what a missing block means (no limits at the top, the top's limits for a peer) is said where it differs, instead of Option in and Option out. - The startup warnings about export limits are a function of their own, and the peers without limits are named in one line rather than one line each: a router with eighty sessions does not need eighty warnings. The warning about a peer without a role is gone: the configuration now refuses one. - Hex formatting of attribute octets is one function; the text for an unknown attribute is built in three plain steps. - The exporter's test fixture returns a named struct, not a tuple. 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
- Route reflection, per-client best path selection for route servers, and ADD-PATH for advertised routes
- TCP-AO, TCP MD5, and GTSM
- 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 |
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 and quick start
- User guide: BGP neighbors, import policy, BGP roles, RPKI, kernel route installation, route advertisement, configuration examples
- Deployment and monitoring
- Reference: configuration, HTTP API, metrics, supported standards
- Architecture and testing
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.