How ansage works
Sessions, the RIB, own prefixes, import and export, and how ansage picks the best route.
ansage is one process with one BGP session per configured neighbor, one routing table (the RIB),
a control socket for the ansage commands and, optionally, an HTTP listener for metrics and a
thread that writes routes into the kernel.
ansage.toml
|
+---------------+----------------+
| | |
neighbor 1 neighbor 2 ... own prefixes (announce, ansage announce/withdraw)
| | |
+---- import ---+----> RIB <-----+
|
export | best routes
v v
per neighbor [kernel] (optional)
ip route ... proto bgpSessions
Each [[neighbor]] runs the BGP state machine of RFC 4271 (Idle, Connect, Active, OpenSent,
OpenConfirm, Established). ansage connects out every connect_retry seconds; after a failed
connect, or when the neighbor shuts the session down, the delay doubles up to
max_connect_retry and resets once a session is up. With listen it also accepts connections,
but only from configured neighbor addresses; a passive neighbor is never connected to.
Every session negotiates IPv4 and IPv6 unicast, 4-octet AS numbers, route refresh, extended messages and, if enabled, Graceful Restart and the BGP Role (RFC 9234). Both families run over one session, IPv4 or IPv6, see Next hops.
Own prefixes
The prefixes in announce are ansage's own. They go to every neighbor (unless its export
says otherwise), are the best route for
their prefix whatever a neighbor sends, and never go into the kernel. ansage announce and
ansage withdraw change the set at runtime until the next restart; a reload applies only what
changed in the file, so runtime changes survive it.
Import and export
| Direction | Setting | Values |
|---|---|---|
| from a neighbor | import | none (default, RFC 8212): nothing is stored; all: every valid route is stored; a filter name |
| to a neighbor | export | own (default): our own prefixes; none: nothing; a filter name |
With the defaults ansage cannot become a transit AS by accident: learned routes only go out
through a filter, only to neighbors with a role, and routes from providers, peers and route
servers only ever go to customers. See Transit and filters.
On the way out, ansage adds its AS to the path and sets itself as the next hop (eBGP), drops
LOCAL_PREF and MED towards eBGP neighbors (a filter can set MED again), and marks a passed-on
attribute it does not know as partial. ansage show rib --out NEIGHBOR shows exactly what a
neighbor got.
A route is not stored when its AS path contains ansage's own AS (a loop), and UPDATEs with broken attributes are handled per RFC 7606: treated as a withdraw, or the bad attribute is discarded, instead of tearing the session down.
Best path
Of all routes for one prefix, ansage picks one in this order:
- Own prefixes beat anything learned.
- A route whose next hop is unreachable (with
[kernel]) is ranked last. - Highest LOCAL_PREF (default 100). An eBGP neighbor's LOCAL_PREF is dropped on receipt, so on an eBGP route it comes from an import filter. A route with GRACEFUL_SHUTDOWN counts as LOCAL_PREF 0, also on eBGP (RFC 8326).
- Shortest AS path.
- Lowest ORIGIN (IGP, EGP, incomplete).
- Lowest MED among routes from the same neighbor AS (a missing MED is 0).
- eBGP over iBGP.
- Lowest BGP identifier, then lowest neighbor address.
The best routes are what ansage show rib marks with * and, with [kernel], what goes into the
routing table.
Control socket and HTTP
ansage show, announce, drain and the other client commands send one request over the
Unix control socket (control_socket, default /run/ansage/ansage.sock) and print the reply.
metrics_listen adds Prometheus metrics and a read-only copy of the same answers as JSON, see
the HTTP API.