# 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.

```txt
              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 bgp
```

## Sessions

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](/docs/guides/next-hops.md).

## 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](/docs/guides/transit.md).

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:

1. Own prefixes beat anything learned.
2. A route whose next hop is unreachable (with `[kernel]`) is ranked last.
3. 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).
4. Shortest AS path.
5. Lowest ORIGIN (IGP, EGP, incomplete).
6. Lowest MED among routes from the same neighbor AS (a missing MED is 0).
7. eBGP over iBGP.
8. 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](/docs/guides/kernel-routes.md).

## 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](/docs/reference/http-api.md).
