The documentation moves from READMEs into a site in docs/: getting started, a user guide, operations, a reference, and development pages, written in the style of network vendors' documentation (docs/STYLE.md). bin/bgp/README.md and docs/RFCs.md are folded into it. - A theme of its own in the International Typographic Style, in blues, with self-hosted Inter and JetBrains Mono, search over Zola's index, dark mode, and no resources loaded from other hosts. - Example configurations in docs/examples/, shown on the pages and checked with `bgp --check` in CI. - A test that fails when a field of config.proto is missing from the configuration reference. - A CI job that builds the site; Zola fails on broken links and anchors. - A hardened systemd unit, tried under systemd with kernel routes on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6.0 KiB
+++ title = "Monitoring Ferrix" description = "Describes the status page, route lookup, rejected route records, and the metrics and alerting rules for monitoring Ferrix." weight = 2
[extra] nav = "Monitoring" +++
Ferrix provides a status page, a JSON API, an event stream, and Prometheus
metrics over HTTP. To enable the HTTP interface, configure http_endpoint:
http_endpoint { address: "127.0.0.1" port: 8080 }
Table 1 lists the HTTP endpoints. All endpoints are read-only.
| Path | Description |
|---|---|
/statusz |
Status page |
/api/... |
JSON API. See HTTP API Reference. |
/api/events |
Server-sent events for session and route changes |
/metricz |
Prometheus metrics. See Metrics Reference. |
Status Page
The status page, /statusz, displays the following information:
- The configuration that was read at startup.
- Each neighbor, with its session state, address families, role and role confirmation, number of accepted, rejected, and held routes, and last error.
- The originated routes, and a lookup of received routes.
- RPKI validation: the cache, the RTR version, and the age of the data.
- Kernel route installation: the number of installed routes, the number of routes not installed and the reason, the last error reported by the kernel, and the interfaces.
- Rejected routes, by neighbor and by reason.
- A live event log.
Route Lookup
The status page provides a lookup of received routes. The HTTP endpoint
/api/routes/received accepts the same queries. Table 2 lists the query
parameters.
| Parameter | Result |
|---|---|
prefix=193.0.0.0/21 |
All routes for the prefix, best path first |
address=193.0.0.1 |
All prefixes that contain the address, most specific first |
within=193.0.0.0/16 |
The prefix and all more specific prefixes |
peer=NAME |
Only routes from the neighbor, identified by name or address |
best=true |
Only the best path for each prefix |
limit=N |
At most N routes. Default: 1000. Maximum: 100000. |
The following example displays the best path for the destination
193.0.0.1:
curl -s '127.0.0.1:8080/api/routes/received?address=193.0.0.1&best=true' | jq
Note
The
within,peer, andbestparameters, when used withoutprefixoraddress, scan the entire routing table. With a full routing table, such a query takes noticeably longer.
Rejected Routes
Ferrix does not store rejected routes in the routing table. For each
neighbor, it records the number of rejected routes for each reason, and the
200 most recent rejected routes with their AS paths. The status page
displays this information under "Refused routes", and the HTTP endpoint
/api/routes/rejected returns it as JSON. To display the records for one
neighbor, add ?peer=NAME.
[{"peer":"transit-a","total":3,"by_reason":{"RPKI invalid":2,"bogon prefix":1},
"recent":[{"prefix":"203.0.113.0/24","reason":"RPKI invalid","as_path":[64496,64511]}]}]
The records are retained after the session ends. Ferrix logs the first rejected route from each neighbor, and at most one rejected route per minute thereafter.
For a description of each rejection reason, see Import Policy.
Alerting Rules
The following Prometheus alerting rules cover the conditions that require operator action: route hijack and route leak attempts, prefix limits, session failures, loss of RPKI data, and kernel errors.
groups:
- name: bgp
rules:
# A neighbor advertises routes that its import policy rejects. The
# cause is a route leak or hijack at the neighbor, or an outdated
# prefix list.
- alert: BgpRoutesRejected
expr: sum by (peer, reason) (increase(bgp_routes_rejected_total[10m])) > 0
labels: { severity: warning }
# A route that contains the local AS number was received: a routing
# loop, or another network using the local AS number.
- alert: BgpOwnAsInPath
expr: increase(bgp_routes_rejected_total{reason="own AS in path"}[10m]) > 0
labels: { severity: page }
# A neighbor advertised a prefix of the local network, or a route
# with a third-party next hop.
- alert: BgpHijackAttempt
expr: increase(bgp_routes_rejected_total{reason=~"prefix is our own|next hop is not the peer"}[10m]) > 0
labels: { severity: page }
# A neighbor is approaching its prefix limit.
- alert: BgpPeerNearPrefixLimit
expr: bgp_peer_routes / on (peer) bgp_peer_max_prefixes > 0.8
for: 10m
labels: { severity: warning }
# A session was torn down because the neighbor exceeded its prefix
# limit.
- alert: BgpPrefixLimitExceeded
expr: increase(bgp_prefix_limit_exceeded_total[1h]) > 0
labels: { severity: page }
# A configured neighbor has no established session.
- alert: BgpPeerDown
expr: bgp_peer_up == 0
for: 5m
labels: { severity: page }
# No RPKI data is available. Routes are not validated.
- alert: BgpRpkiNoData
expr: sum(bgp_rpki_vrps) == 0
for: 15m
labels: { severity: page }
# The kernel rejected route installation requests.
- alert: BgpKernelErrors
expr: increase(bgp_kernel_errors_total[10m]) > 0
labels: { severity: warning }
Dashboard Queries
Table 3 lists queries for a monitoring dashboard.
| Panel | Query |
|---|---|
| Established sessions | sum(bgp_peer_up), of count(bgp_peer_up) |
| Routes by neighbor | bgp_peer_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]) |
| Kernel routes | bgp_kernel_routes, bgp_kernel_routes_unresolved |
| RPKI data | bgp_rpki_vrps, bgp_rpki_aspas |
The metric bgp_build_info{version} reports the running version.