Files
ferrix/fuzz
Rayhaan JaufeerallyandClaude Fable 5.1 d49bab58a5 Add ADD-PATH (RFC 7911): several routes for a prefix from one peer
A peer can now send several routes for one prefix, told apart by a path
identifier, and each is a route of its own in the table.

Wire:
- The ADD-PATH capability lists several address families. It was read as
  exactly one, so the OPEN of a router offering it for IPv4 and IPv6 was
  malformed and the session never came up.
- Prefixes in UPDATEs are `Nlri`: a prefix and a path identifier. The
  identifier is on the wire, in the body and in MP_REACH/MP_UNREACH, for
  the families the session uses ADD-PATH for in that direction. Sending
  and receiving are settled separately, so a session has one codec context
  for each.

Negotiation:
- `add_path` on a peer in the configuration: off (the default), receive,
  send or both, offered for every family offered to the peer.
- In use for a family and a direction when one side offered to send and
  the other to receive. Shown on /statusz and in /api/peers.

Table:
- A route is known by its peer and path identifier together. Identifiers
  are stored only in rows that have a non-zero one, so routes of peers
  that send one route each cost nothing more.
- Equal routes from one peer are chosen between by the lower identifier.
- /api/routes/received gives each route's path_id.

Journal:
- A second journal in each shard records every change to any route, for
  followers that want all the routes of a prefix and not only the best:
  RibTable::reader_of_all_routes and Event::Routes. This is what sending
  several routes to a peer will read. It costs nothing while nobody
  follows it.

Sending: prefixes go out with a path identifier where that was agreed, but
there is still one route for each prefix to send: only originated routes
are announced.

Tested with the table and journal model tests extended to path identifiers
and to followers of all routes, the codec property tests and fuzz targets
extended to ADD-PATH sessions, and end to end in both directions and for
the case where only one side offers it.

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

Fuzz targets

Coverage-guided fuzzing of everything that reads input we do not control. The property tests (cargo test, e.g. crates/packet/tests/properties.rs) check the same things on generated input and run on every build; these targets go further by letting libFuzzer follow code coverage for as long as you leave them running.

Target Input
message Raw bytes as they come off a TCP connection
message_body A message body behind a correct header (reaches the body parsers)
prefix_text A prefix as text
config The configuration file

For the two message targets a finding is either a panic, or a message the decoder accepted that cannot be written and read back as itself.

Running

libFuzzer needs a nightly toolchain and cargo-fuzz:

rustup toolchain install nightly
cargo install cargo-fuzz

Then, from this directory:

cargo +nightly fuzz run message_body corpus/message_body seeds/message_body -- -max_total_time=300

The first directory is the working corpus, which the fuzzer adds to and which is not checked in. seeds/ holds a few valid inputs to start from. Leave out -max_total_time to run until interrupted.

When it finds something

The input is saved under artifacts/<target>/. Reproduce it with

cargo +nightly fuzz run message_body artifacts/message_body/crash-...

Fix the bug, and add a unit test with the input next to the code it broke, so that cargo test keeps it fixed without anyone having to run the fuzzer.