Peer at link-local addresses: fe80::1%eth0

A peer's endpoint may be a link-local IPv6 address with the interface it
is on. Such a peer is the address and the interface together, wherever
peers are told apart: admission, collisions, hold-downs, the refusal log,
the status page. The interface is looked up by name each time it is
needed, so one that appears later or is made anew is found.

Our routes go out with our link-local address in both places of
MP_REACH_NLRI's next hop, as FRR sends its own. A peer's link-local next
hop is taken alone, twice, or after "::" (BIRD), and resolved in the
kernel on the interface of the session rather than by looking fe80::/64
up, which every interface has.

The lab has a new phase, linklocal: sessions with FRR (by interface, with
radvd beside the daemon) and BIRD over a LAN with link-local addresses
only, both families, pings across, the interface down and up.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Rayhaan JaufeerallyandClaude Fable 5.1 committed 2026-10-02 18:24:13 +02:00
1 parent 92e013ca01
commit fd2248feb5
38 files changed
+975 -151

No files matched your search

+41 -5
View File
@@ -184,9 +184,44 @@ link-local one. In the kernel such a route is an IPv4 route by way of an
IPv6 neighbor (`10.2.0.0/24 via inet6 2001:db8::2 dev eth0`, Linux 5.2 and
later).
The session's addresses have to be global ones (or unique local): a peer
configured by a link-local address (`fe80::...`), which needs the
interface named with it, is not supported yet.
## Peers at link-local addresses
A link with no addresses but the link-local ones every interface has
(`fe80::/10`) is enough for a session. Such an address means something
only on its link, so the peer is the address and the interface together:
```
peers {
name: "upstream"
endpoint { address: "fe80::1%eno3" }
remote_asn: 64602
}
```
- The interface is looked up by its name each time it is needed: one that
is not there yet, or is made anew with another number (a tunnel that is
restarted), is found when it is. Until then the peer's state says there
is no such interface.
- The same address on two interfaces is two peers. A link-local address
without an interface is refused, as is an interface on any other
address.
- To take the peer's connections the daemon must listen on `::` (as it
does by default), not on one global address.
- Both address families go over the session (IPv4 as above, if the peer
agrees). Our routes go with our link-local address as next hop, in both
places MP_REACH_NLRI has for one, as FRR sends its own. The peer's next
hop is taken in any of the forms in use: the link-local address alone,
twice, or after `::`. In the kernel the routes go by way of that address
on the session's interface (`10.2.0.0/24 via inet6 fe80::1 dev eno3`).
- `local_address`, if set to a link-local address of ours, is taken to be
on the peer's interface.
With FRR, configure the peer by interface (`neighbor eno3 interface
remote-as ...`, "BGP unnumbered"). FRR then learns who is on the link from
IPv6 router advertisements, which this daemon does not send: run `radvd`
(or the like) on the interface beside it. FRR's older `neighbor fe80::1
interface eno3` brings the session up but FRR 10.5 then takes every route
from us for unreachable. BIRD needs only `neighbor fe80::1%eno3 as ...`.
## Forwarding: routes in the kernel (Linux)
@@ -293,14 +328,15 @@ Routinator 0.15.2. What it covers:
| `scale` | A table from BIRD (`SCALE_ROUTES`, a million for the Internet's size) into the table and the kernel; the daemon killed and restarted under it; the table withdrawn |
| `limits` | A peer whose role does not fit gets no session; a peer over its prefix limit gets Cease / Maximum Number of Prefixes and is held down |
| `v6only` | The exchange LAN without IPv4 addresses: one IPv6 session with each router for both families, IPv4 routes with IPv6 next hops (RFC 8950) in BGP and in the kernel, IPv4 pings across |
| `linklocal` | The exchange LAN with link-local addresses only, and the same ones on a second interface: sessions with FRR (by interface, with radvd beside the daemon) and BIRD at `fe80::…%ix0`, both families in BGP and in the kernel, pings across, the interface taken down and up |
`scripts/interop/real-rpki.sh` checks the RTR client against a Routinator
that has the real RPKI, ASPAs included: the daemon has to end up with as
many VRPs and ASPAs as the validator says it has.
Not covered: routers other than FRR and BIRD; IPv6 routes over an IPv4
session (the daemon does not send them); sessions between link-local
addresses; long runs.
session (the daemon does not send them); an interface that is removed and
made anew under a session; long runs.
## Finding a route