Install best routes in the Linux kernel over netlink
New crate bgp-fib. It follows the routing table's best routes and keeps
the kernel's routing table the same, and learns the machine's interfaces
and addresses from the kernel, which is what says whether a next hop can
be reached.
- netlink: the rtnetlink messages used (routes, addresses, links, errors),
as bytes and back. No I/O; property tested and fuzzed.
- interfaces: what is directly reachable, and from which interface.
- plan: what to ask the kernel for, given the best routes and what the
kernel has. No I/O; tested against a model kernel.
- kernel (Linux only): the sockets and the task. Requests go in batches;
routes of ours found at startup are kept if still right and removed if
not; a change of interfaces has every route worked out again; a clean
stop removes our routes.
Only routes marked proto bgp with the configured table and metric are
ever touched. A best route is installed if its next hop is a neighbor;
next hops further away are not resolved through other routes yet, and
such prefixes are counted and shown instead.
Configured with `kernel { table metric }`; off by default. The daemon
needs CAP_NET_ADMIN and stops if the kernel refuses it. On shutdown it
closes sessions and then removes its routes.
/api/kernel and the status page show installed, unresolved and refused
counts, the last error and the interfaces; five bgp_kernel_* metrics.
Testing: scripts/kernel-tests.sh runs, in network namespaces of their
own and with only the capabilities the daemon needs, the installer
against `ip route`, the daemon with a peer, and two daemons that route
for each other with pings across over IPv4 and IPv6.
scripts/linux-vm.sh runs that, or anything else, in a Lima VM from
macOS. CI runs the kernel tests and fuzzes the netlink decoder.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
1f84235e87
commit
1fc44798b7
38 files changed
+3745
-16
No files matched your search
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# Runs the tests that need a real Linux kernel to change the routes of:
|
||||
# those of the bgp-fib crate that `cargo test` skips, and the end-to-end
|
||||
# test of two daemons that route for each other.
|
||||
#
|
||||
# They run in a network namespace made for the purpose, so the machine's
|
||||
# own interfaces and routes are out of their reach, and with the one
|
||||
# capability the daemon needs, CAP_NET_ADMIN, rather than as root.
|
||||
#
|
||||
# Run it on Linux, as a user who can sudo. On another system,
|
||||
# scripts/linux-vm.sh runs it in a virtual machine.
|
||||
set -eu
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
[ "$(uname -s)" = Linux ] || { echo "this needs Linux; see scripts/linux-vm.sh" >&2; exit 1; }
|
||||
|
||||
# Built as the user, so that nothing in the target directory is root's.
|
||||
cargo build --locked -p bgp
|
||||
cargo test --locked -p bgp-fib --test kernel --no-run
|
||||
cargo test --locked -p bgp-integration-tests --test kernel --no-run
|
||||
|
||||
namespace="ferrix-test-$$"
|
||||
sudo modprobe dummy 2>/dev/null || true
|
||||
sudo ip netns add "$namespace"
|
||||
trap 'sudo ip netns del "$namespace"' EXIT
|
||||
sudo ip netns exec "$namespace" ip link set lo up
|
||||
|
||||
# In the namespace, as the user, with CAP_NET_ADMIN and nothing else.
|
||||
in_namespace() {
|
||||
sudo ip netns exec "$namespace" \
|
||||
setpriv --reuid "$(id -u)" --regid "$(id -g)" --init-groups \
|
||||
--inh-caps +net_admin --ambient-caps +net_admin \
|
||||
env PATH="$PATH" HOME="$HOME" CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-}" "$@"
|
||||
}
|
||||
|
||||
in_namespace cargo test --locked -p bgp-fib --test kernel -- --include-ignored --nocapture "$@"
|
||||
in_namespace cargo test --locked -p bgp-integration-tests --test kernel -- --include-ignored --nocapture "$@"
|
||||
scripts/two-routers.sh
|
||||
Reference in new issue
Block a user