export: advertise every route for a prefix with ADD-PATH (all_paths)
Before this change, a session on which ADD-PATH (RFC 7911) was
negotiated in the sending direction was sent path identifiers, but only
the best route for each prefix. A route collector such as bgp.tools
wants every route a router has accepted, from every neighbor, and from
one session: without this the collector saw one path per prefix, nearly
always the same neighbor's.
This change adds `all_paths` to the export policy. On a session with it,
and ADD-PATH send negotiated for a family, every accepted route for a
prefix of that family is advertised, each with a path identifier of its
own; for a family without ADD-PATH send the best route goes as before.
`all_paths` needs `learned_routes` (a configuration error otherwise) and
the peer's `add_path` to offer sending. The export policy, the role
rules, the well-known communities and the export limits apply to every
route alike, and the export limits count every route.
Implementation, in the advertiser:
* An exporter with `all_paths` follows the table's journal of all routes
(`RibTable::reader_of_all_routes`, until now unused) instead of the
best-route journal, and is given all the routes of a prefix whenever
one of them changes (`News::Routes`).
* What the peer holds is `Announced`: the set of prefixes for a
best-route session, as before; or for an all-paths session, for each
prefix the routes announced, keyed by the peer they came from and that
peer's own identifier, with the identifier they went out with and the
form they went out in. A route keeps its identifier for as long as it
is announced, goes out again only if it changed, and is withdrawn by
its identifier; a new route gets the lowest identifier not in use for
the prefix, from 1.
* Verdicts carry either kind (`Verdict::Best`, `Verdict::All`), and a
reset of the table puts what was announced in doubt until heard of
again, as before, with the same identifiers kept across the reset.
* The record for an all-paths session is about 50 bytes a route, some
tens of megabytes for a full table from several neighbors; the
best-route bookkeeping is unchanged in size.
Also, so that a collector session can be watched: the number of routes
advertised to each peer and not withdrawn since, every route counted
where several are sent for a prefix. The exporter keeps it in the
session's counters after every change; it is `advertised_routes` in
`/api/peers`, the "sent" column of the status page's neighbor table,
and the gauge `bgp_peer_advertised_routes{peer}`.
Documentation: a "Feeding a Route Collector" section in the guide to
passing routes on, with the configuration for a collector; `all_paths`
in the configuration reference; the ADD-PATH sections of the neighbor
guide and the standards reference; the limitation that was removed;
the new field, column and metric in the HTTP API, monitoring and
metrics references.
Testing: an integration test with two feeders and a collector that
negotiated ADD-PATH receive, which checks the two routes with their
identifiers, the withdrawal of one by its identifier, a changed route
keeping its identifier and a new route taking the free one; a
configuration test for `all_paths` without `learned_routes`; a new
`collector` phase of the interoperability lab in which FRR, as a route
collector, is told both of BIRD's routes for a prefix from BIRD's two
sessions and holds them apart, and loses one when its session is
disabled, with the advertised count checked at each step. The workspace tests, the kernel tests and every lab phase pass.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
03f4f58ecb
commit
ec5c9be454
24 files changed
+660
-75
No files matched your search
@@ -99,6 +99,7 @@ test phases.
|
||||
| `hijacks` | FRR advertises a local prefix, a route with BIRD as third-party next hop, and the exchange LAN prefix; all are rejected |
|
||||
| `nexthops` | A preferred route from FRR with an unresolvable next hop is held, and the route from BIRD is selected and installed; the selection changes when the next hop becomes resolvable, and reverts when it becomes unresolvable |
|
||||
| `transit` | FRR as customer and BIRD as provider: FRR's routes are advertised to BIRD with the local AS prepended; BIRD's routes are advertised to FRR with the OTC attribute; a control community prevents the advertisement of one FRR route to BIRD; traffic is forwarded between their networks |
|
||||
| `collector` | FRR as a route collector with ADD-PATH and `all_paths`: BIRD peers twice, FRR receives both of BIRD's routes for a prefix with distinct path identifiers, and one is withdrawn by its identifier when its session is disabled |
|
||||
| `v6only` | Exchange LAN without IPv4 addresses: one IPv6 session with each router for both address families; IPv4 routes with IPv6 next hops (RFC 8950) in BGP and in the kernel; IPv4 forwarding verified with `ping` |
|
||||
| `linklocal` | Exchange LAN with link-local addresses only, with the same addresses on a second interface: sessions with FRR (by interface, with radvd) and BIRD at `fe80::…%ix0`; both address families in BGP and in the kernel; forwarding verified with `ping`; interface disabled and enabled |
|
||||
|
||||
|
||||
@@ -398,12 +398,48 @@ Ferrix advertised (`announced`) and withdrew (`withdrawn`). Ferrix does not
|
||||
provide a view of the routes advertised to a neighbor (Adj-RIB-Out); to
|
||||
display them, use the neighbor's own tools.
|
||||
|
||||
## Feeding a Route Collector
|
||||
|
||||
A route collector, such as a looking glass or a measurement project, wants
|
||||
every route that a router has accepted, not only the best path for each
|
||||
prefix. ADD-PATH (RFC 7911) lets one session carry several routes for a
|
||||
prefix, each with a path identifier. To advertise every accepted route to
|
||||
a neighbor, configure ADD-PATH in the sending direction and enable
|
||||
`all_paths` in the neighbor's export policy:
|
||||
|
||||
```textproto
|
||||
peers {
|
||||
name: "collector"
|
||||
endpoint { address: "203.0.113.10" }
|
||||
remote_asn: 64496
|
||||
role: PEER
|
||||
add_path: ADD_PATH_SEND
|
||||
export {
|
||||
learned_routes: true
|
||||
all_paths: true
|
||||
}
|
||||
export_limits {}
|
||||
}
|
||||
```
|
||||
|
||||
Ferrix advertises every route for a prefix only for the address families
|
||||
for which the neighbor negotiated ADD-PATH receive. For other families it
|
||||
advertises the best path, as without `all_paths`. Each route is advertised
|
||||
with a path identifier that stays with the route for as long as it is
|
||||
advertised; a route that is withdrawn is withdrawn by its identifier, and
|
||||
a route whose attributes change is advertised again with the same
|
||||
identifier. The export policy, the BGP role rules, the well-known
|
||||
communities and the export limits apply to every route alike, and
|
||||
`max_prefixes` in `export_limits` counts every route advertised.
|
||||
|
||||
A session with `all_paths` keeps a record of every route advertised and
|
||||
its identifier, which takes about 50 bytes for each route. For a full
|
||||
Internet table from several neighbors, this is some tens of megabytes.
|
||||
|
||||
## Limitations
|
||||
|
||||
- Per-client best path selection for route servers is not supported. Every
|
||||
client receives the same best path.
|
||||
- ADD-PATH is not supported for advertisement; only the best path is
|
||||
advertised.
|
||||
- Best path selection does not use ORIGINATOR_ID and CLUSTER_LIST as tie
|
||||
breakers (RFC 4456 Section 9).
|
||||
- UPDATE messages are generated separately for each session, even when
|
||||
|
||||
@@ -193,8 +193,11 @@ add_path: ADD_PATH_RECEIVE
|
||||
```
|
||||
|
||||
ADD-PATH is enabled for each address family and direction only if the
|
||||
neighbor also supports it. Ferrix negotiates `ADD_PATH_SEND` and
|
||||
`ADD_PATH_BOTH`, but it advertises only one path for each prefix.
|
||||
neighbor also supports it. With `ADD_PATH_SEND` or `ADD_PATH_BOTH`,
|
||||
Ferrix advertises routes with path identifiers. By default it still
|
||||
advertises one path for each prefix; to advertise every accepted route
|
||||
for a prefix, enable `all_paths` in the neighbor's export policy. See
|
||||
[Feeding a Route Collector](@/docs/guides/passing-routes-on.md#feeding-a-route-collector).
|
||||
|
||||
## Hold Timer
|
||||
|
||||
|
||||
@@ -37,8 +37,9 @@ Below the status line, the page displays the following information:
|
||||
|
||||
- The configuration that was read at startup.
|
||||
- Each neighbor, with its session state, time established, next hop,
|
||||
session properties, number of accepted routes, rejected announcements,
|
||||
and held routes, and its last error. Neighbors that need attention are
|
||||
session properties, number of accepted routes, number of routes
|
||||
advertised to it (**sent**), rejected announcements, and held routes,
|
||||
and its last error. Neighbors that need attention are
|
||||
listed first; the others are grouped by role. The IPv4 and IPv6 sessions
|
||||
of one neighbor, named `NAME-v4` and `NAME-v6`, are listed together,
|
||||
IPv6 first, and joined by a bar. The **problems only** option hides the neighbors that
|
||||
@@ -238,6 +239,7 @@ Table 3 lists queries for a monitoring dashboard.
|
||||
|---|---|
|
||||
| Established sessions | `sum(bgp_peer_up)`, of `count(bgp_peer_up)` |
|
||||
| Routes by neighbor | `bgp_peer_routes` |
|
||||
| Routes advertised to each neighbor | `bgp_peer_advertised_routes` |
|
||||
| Prefixes with a best path | `bgp_rib_prefixes` |
|
||||
| Rejected routes by reason | `sum by (reason) (rate(bgp_routes_rejected_total[5m]))` |
|
||||
| UPDATE messages received and sent | `rate(bgp_messages_received_total{type="update"}[5m])`, `rate(bgp_messages_sent_total{type="update"}[5m])` |
|
||||
|
||||
@@ -154,6 +154,7 @@ Statements that determine which routes are advertised to a neighbor. See
|
||||
| Statement | Default | Description |
|
||||
|---|---|---|
|
||||
| `learned_routes` <span class="type">bool</span> | `false` | Enables the advertisement of learned routes, subject to BGP roles and communities. |
|
||||
| `all_paths` <span class="type">bool</span> | `false` | Advertises every accepted route for a prefix, not only the best path, each with a path identifier (ADD-PATH, RFC 7911). Requires `learned_routes`, and takes effect for an address family only if the neighbor negotiated ADD-PATH receive for it; otherwise the best path is advertised. Export policy and export limits apply to every route. See [Feeding a Route Collector](@/docs/guides/passing-routes-on.md#feeding-a-route-collector). |
|
||||
| `add_communities` <span class="type">string, repeated</span> | None | Specifies standard communities added to advertised routes. |
|
||||
| `add_large_communities` <span class="type">string, repeated</span> | None | Specifies large communities added to advertised routes. |
|
||||
| `remove_communities` <span class="type">string, repeated</span> | None | Specifies patterns of communities removed from advertised routes. Applied before communities are added. |
|
||||
|
||||
@@ -61,6 +61,7 @@ neighbor:
|
||||
"add_path_send": [],
|
||||
"routes": 1,
|
||||
"rejected_routes": 1,
|
||||
"advertised_routes": 2,
|
||||
"held_routes": 0,
|
||||
"expected_routes": null,
|
||||
"role": null,
|
||||
@@ -84,6 +85,7 @@ neighbor:
|
||||
| `direction` | `inbound` if the neighbor initiated the connection, `outbound` otherwise. |
|
||||
| `routes` | Number of the neighbor's routes in the routing table. |
|
||||
| `rejected_routes` | Number of the neighbor's routes rejected by its import policy. |
|
||||
| `advertised_routes` | Number of routes advertised to the neighbor and not withdrawn since. With ADD-PATH and `all_paths`, every route advertised counts. |
|
||||
| `held_routes` | Number of held routes: routes rejected for a reason that can change without a new UPDATE, such as RPKI validity or next hop resolution. |
|
||||
| `expected_routes` | The `expected_routes` value from the configuration, or `null` if it is not set. |
|
||||
| `role_confirmed` | Whether the neighbor advertised a BGP role that matches the configured role. |
|
||||
|
||||
@@ -29,6 +29,7 @@ alerting rules based on these metrics, see
|
||||
| Metric | Type | Description |
|
||||
|---|---|---|
|
||||
| `bgp_peer_routes{peer}` | Gauge | Number of the neighbor's routes in the routing table. |
|
||||
| `bgp_peer_advertised_routes{peer}` | Gauge | Number of routes advertised to the neighbor and not withdrawn since. |
|
||||
| `bgp_peer_max_prefixes{peer}` | Gauge | Prefix limit of the neighbor (`import.max_prefixes`), if configured. |
|
||||
| `bgp_prefix_limit_exceeded_total{peer}` | Counter | Number of sessions torn down because the neighbor exceeded its prefix limit. |
|
||||
| `bgp_export_limit_exceeded_total{peer}` | Counter | Number of sessions torn down because the routes to be advertised to the neighbor exceeded its export limit (`export_limits.max_prefixes`). |
|
||||
|
||||
@@ -306,7 +306,7 @@ Version 2 is implemented from version 23 of the draft.
|
||||
|---------|--------|
|
||||
| Capability negotiation per family and direction | ✅ |
|
||||
| Receiving several routes for a prefix | ✅ |
|
||||
| Sending several routes for a prefix | ❌ (path identifiers are sent; one route each) |
|
||||
| Sending several routes for a prefix | ✅ with `all_paths` in the export policy; the best path only otherwise |
|
||||
|
||||
### RFC 4271 §9.1.2 / RFC 4486 / operational practice — import policy
|
||||
|
||||
|
||||
Reference in new issue
Block a user