# 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 . 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 | ## 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. - Both ferrix and the FRR routers dial each other, so connection collisions (RFC 4271 §6.8) are normal at start-up: one of the two TCP connections is closed with a Cease / Connection Collision Resolution NOTIFICATION and the other carries the session. ferrix has the lowest BGP Identifier here, so the connection the FRR router opened is the one that survives; the "opened by" column on the status page shows which side that was. - 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.