Do not choose a route whose next hop cannot be reached (RFC 4271 §9.1.2.1)

Where routes go into the kernel, a route the kernel could not be given
is no longer taken into the table: its next hop is no neighbor on any
interface, or its prefix is a network the machine is itself on. Such a
route used to be able to win selection and then leave its prefix without
a route in the kernel, though another peer had one that worked.

It is held aside the way an RPKI-invalid route is, and by the same
means: judged on arrival against the interfaces as the kernel last
described them, looked for in the table when they change, and taken
from what is held when its next hop can be reached. The fib publishes
the interfaces for this; the next hop is resolved once for an UPDATE
and not for each of its routes.

The lab has a phase, nexthops: FRR's better route with a next hop that
is nowhere is held and BIRD's is installed, and they change places as
an address comes and goes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Rayhaan JaufeerallyandClaude Fable 5.1 committed 2026-10-02 20:29:31 +02:00
1 parent 3d946c32ce
commit f1d80c66df
15 files changed
+680 -63

No files matched your search

+14 -5
View File
@@ -262,10 +262,18 @@ kernel {
address in the network of one of the machine's interfaces that is up. For
an IPv6 route with a link-local next hop, the interface is the one the
peer is a neighbor on. A route whose next hop is further away (a route
from a peer in our own AS that did not set itself as next hop, say) is not
installed, and neither is whatever it replaced: looking up the way to such
a next hop through other routes is not done yet. The status page counts
these, by reason.
from a peer in our own AS that did not set itself as next hop, say)
cannot be installed: looking up the way to such a next hop through other
routes is not done yet.
- **Routes that cannot be installed are not chosen.** With `kernel {}`, a
route whose next hop cannot be reached is not taken into the table, so
that it cannot be the best route of its prefix while another peer has
one that works (RFC 4271 §9.1.2.1). It is held aside, counted as refused
for "next hop unreachable" and shown as held on the status page, and
taken as soon as the machine's interfaces change so that it can be
reached; a route in the table whose next hop goes away is held in the
same way. Without `kernel {}` the daemon does not know what can be
reached, and takes every route.
- **Nexthop objects.** Where the kernel has them (Linux 5.3 and later) a
gateway is put there once, as a nexthop object, and routes name it; `ip
route` shows such routes with `nhid`, and `ip nexthop` the objects. The
@@ -359,7 +367,8 @@ Routinator 0.15.2. What it covers:
| `restart` | The daemon stopped in good order (kernel emptied, peers told) and killed (routes kept, stale one cleared by the next start) |
| `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 |
| `hijacks` | FRR announces our own prefix, a route whose next hop is BIRD, and the exchange LAN's own prefix: the first two are refused, the third stays out of the kernel |
| `hijacks` | FRR announces our own prefix, a route whose next hop is BIRD, and the exchange LAN's own prefix: none is taken |
| `nexthops` | A better route from FRR whose next hop cannot be reached is held and BIRD's is chosen and installed; they swap when the next hop becomes a neighbor, and swap back when it stops being one |
| `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 |