Files
ferrix/.github/workflows/ci.yml
T
Rayhaan JaufeerallyandClaude Fable 5.1 cbf0df1eef Policy scripts: the operator's own rules for routes, in Rhai
A new crate, bgp-policy, runs functions of a script on routes: on their
way in, after the general checks of a peer's import and before the
checks that can change (RPKI, next hop reachability); and on their way
out to a peer. A function is given the route and the peer, may refuse
the route, and may change its communities, large communities,
LOCAL_PREF and MED, and on the way out prepend our AS:

    fn from_peer(route, peer) {
        if route.has_community("65535:666") { return false; }
        route.add_community(LEARNED_FROM[peer.role]);
        route.local_pref = PREFERENCE[peer.role];
        true
    }

Configuration: policy { path | source, import_function, export_function }
and, for a peer, import { function } and export { function }. The script
is compiled at startup; `bgp --check` reads it and says which function
is whose. A function that fails on a route has refused it. Scripts have
no files, network or clock, and are stopped after 200,000 steps.

Route selection now goes by a LOCAL_PREF on a route from an external
peer: the decoder never lets a peer's own through, so one that is there
was set by policy.

What it costs was measured before it was built on (benches/policy.rs):
a call that tests a few communities and changes two takes 1 to 3
microseconds, some two hundred times what Rust would. So a function is
asked once for the routes of an UPDATE, which share their attributes,
unless it asks for the prefix. One peer sending 1.23 M routes over a
session: 0.37 s without a function, 0.80 s with one that marks and
ranks every route, 3.4 s if it also looks at the prefix.

Export applies to what is announced, which today is what the daemon
originates; learned routes are not passed on yet.

Tested by unit tests of the crate, sessions end to end, a fuzz target on
the example script (testdata/policy.rhai), and a lab phase in which a
script changes which of FRR's and BIRD's route is chosen and what each
of them is told.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-02 21:09:39 +02:00

76 lines
2.5 KiB
YAML

# Runs on every push and pull request. Gitea Actions reads this file too
# (it falls back to .github/workflows), so one definition serves both.
name: ci
on:
push:
pull_request:
env:
CARGO_TERM_COLOR: always
# Warnings fail the build here, and only here: locally they stay warnings
# so that work in progress compiles.
RUSTFLAGS: -D warnings
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Format
run: cargo fmt --all -- --check
- name: Lint
run: cargo clippy --locked --workspace --all-targets -- -D warnings
- name: Test
run: cargo test --locked --workspace
# A link in the documentation to something that is not there.
- name: Documentation
env:
RUSTDOCFLAGS: -D warnings
run: cargo doc --locked --workspace --no-deps --document-private-items
# The example operators start from, through the daemon itself.
- name: Example configuration
run: cargo run --locked -p bgp -- --check testdata/server.textpb
# The tests that change a kernel's routes, in a network namespace of
# their own; and two daemons that route for each other.
- name: Kernel tests
run: scripts/kernel-tests.sh
# The daemon against FRR, BIRD and Routinator; see bin/bgp/README.md.
interop:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install FRR, BIRD and Routinator
run: scripts/interop/install.sh
- name: Build
run: cargo build --release --locked -p bgp
- name: Interoperability lab
run: scripts/interop/lab.sh
# A short run of each fuzz target: enough to notice a parser change that
# breaks on input the seeds are close to. Long runs are done by hand; see
# fuzz/README.md.
fuzz:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- name: Install cargo-fuzz
run: cargo install cargo-fuzz --locked
- name: Fuzz
working-directory: fuzz
# cargo-fuzz sets its own flags; the workspace's -D warnings would
# replace them.
env:
RUSTFLAGS: ""
run: |
for target in message message_body attrs policy prefix_text config rtr netlink; do
mkdir -p "corpus/$target"
cargo fuzz run "$target" "corpus/$target" "seeds/$target" -- -max_total_time=60
done