Files
ferrix/docs/lab/README.md
T
Rayhaan JaufeerallyandClaude Fable 5.1 a137160b48 feature: lab topology, student handout; drop peer routes on session end
Phase 5 of the teaching demo plus two fixes found while exercising the
dialer on the status page.

- Adj-RIB-In: routes learned from a peer are removed when its session ends
  (RFC 4271 §8.2.2), emitting a Withdrawn event per prefix before the
  session Down event. Previously stale routes from dead sessions stayed in
  the received table.
- statusz: poll the peers table every 5 s so dial state (Connecting /
  Backoff and its retry countdown) stays current; those changes carry no
  event.
- docs/lab: docker-compose topology with ferrix (AS65000) and two FRR
  routers. r2 accepts nothing directly from ferrix so student prefixes
  only reach it via r1, then come back with AS path 65002 65001 65000. r1
  applies community-driven policy: NO_EXPORT stops forwarding, 65001:100
  prepends, BLACKHOLE drops. Dockerfile for the daemon.
- docs/lab/HANDOUT.md: student exercises walking through announcement,
  reading the bytes, prepending, NO_EXPORT, action communities,
  blackholing and withdrawal.

The container files have not been executed (no runtime available here);
docs/lab/README.md lists what is most likely to need adjusting.

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

3.7 KiB

BGP teaching lab

A small topology in which a prefix announced from the ferrix_bgp web UI is carried around a loop of two routers and arrives back, so students can watch what their path attributes and communities do.

        announce                     re-advertise
 ┌─────────┐  ──────▶  ┌────────┐  ──────▶  ┌────────┐
 │ ferrix  │           │  r1    │           │  r2    │
 │ AS65000 │           │ AS65001│           │ AS65002│
 │ web UI  │  ◀──────────────────────────────────────┘
 └─────────┘   comes back with AS path 65002 65001 65000
  • ferrix (AS65000, 10.200.0.1) dials r1 and r2 and announces whatever students enter on http://localhost:8080/statusz. It does not forward routes it learns, so the only routes it sends are the students'.
  • r1 (AS65001, FRR) applies policy to routes from ferrix based on the communities they carry, then passes them to r2. It originates 192.0.2.0/24.
  • r2 (AS65002, FRR) refuses routes directly from ferrix, so it only learns student prefixes via r1, and re-advertises everything to ferrix. It originates 198.51.100.0/24.

Running it

From the repository root:

docker compose -f docs/lab/docker-compose.yml up --build

Then open http://localhost:8080/statusz. Both peers should show Established within a few seconds and the received table should already list the two prefixes r1 and r2 originate.

Useful on the routers:

docker exec r1 vtysh -c 'show bgp ipv4 unicast'
docker exec r2 vtysh -c 'show bgp ipv4 unicast 10.100.1.0/24'
docker exec r1 vtysh -c 'show bgp neighbors 10.200.0.1 advertised-routes'

Policy on r1

Students set r1 does Visible effect in ferrix
nothing forwards to r2 prefix returns, AS path 65002 65001 65000
NO_EXPORT keeps it, does not send to r2 (RFC 1997) prefix does not return
65001:100 prepends 65001 three times returns with path 65002 65001 65001 65001 65001 65000
BLACKHOLE (65535:666) drops it on import prefix does not return
AS-path prepends on ferrix nothing special returns with extra 65000s in the path

Without containers

fake_peer in crates/integration-tests/examples is enough for the core loop on one machine: it echoes every prefix back with its own ASN prepended and honours NO_EXPORT. See bin/bgp/README.md.

Caveats

These container files were written without a container runtime to hand, so they have not been executed. Things most likely to need a touch:

  • the FRR image tag, and FRR's route-map / community-list syntax if your version differs from 10.x;
  • no bgp ebgp-requires-policy is required on FRR 7.4+ or eBGP routes are silently dropped; it is present in both configs;
  • ferrix binds port 179 inside its container, which requires no special capability there. If you run it on the host instead, either run as root, grant CAP_NET_BIND_SERVICE, or change listen_endpoints and the FRR neighbor port.
  • ferrix does not check AS paths for its own ASN. That is what lets the looped route be accepted; a production BGP speaker would reject it.