A rejected route was recorded with its prefix, reason and AS path, which is not enough to tell why a neighbor sent it: whether a /32 is a blackhole request, which communities a leaked route carries, which network marked it Only to Customer. Each recorded rejection now keeps the attributes of the UPDATE it came in, without the NLRI of MP_REACH_NLRI and MP_UNREACH_NLRI, and its next hop. The attributes are copied once per UPDATE, only when a route of it is rejected, and shared by its rejected routes. A route rejected later, when the RPKI data changes, has the attributes it was stored with. /api/routes/rejected gives them as `summary` and `attributes`, as for received routes, and the status page shows them under "show" in each row of the refused routes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7.6 KiB
+++ title = "HTTP API Reference" description = "Describes the endpoints of the Ferrix HTTP interface: the JSON API, the event stream, the status page, and the metrics endpoint." weight = 3
[extra] nav = "HTTP API" +++
Ferrix serves its HTTP interface on the address configured with
http_endpoint. All endpoints are read-only and use the GET method. If a
query parameter is invalid, the server returns status 400 (Bad Request)
with a description of the error.
Caution
The HTTP interface does not require authentication. Bind it to a loopback address, or place it behind a reverse proxy that requires authentication.
Endpoints
| Endpoint | Description |
|---|---|
/ |
Redirects to /statusz. |
/statusz |
Status page. |
/api/status |
Router ID, AS number, uptime, and table sizes. |
/api/config |
The configuration that was read at startup. |
/api/peers |
Configured neighbors and their sessions. |
/api/routes/local |
Originated routes. |
/api/routes/received |
Received routes. |
/api/routes/rejected |
Rejected routes, by neighbor. |
/api/rpki |
RPKI cache, data, and data age. |
/api/kernel |
Kernel route installation state and interfaces. |
/api/events |
Session and route changes, as server-sent events. |
/metricz |
Prometheus metrics. See Metrics Reference. |
Peers
/api/peers returns an array with one object for each configured
neighbor:
{
"name": "test-peer",
"peer_addr": "127.0.0.1:64815",
"peer_asn": 65001,
"state": "Established",
"direction": "inbound",
"local_addr": "127.0.0.1:1790",
"uptime_secs": 2,
"four_octet_asn": true,
"extended_next_hop": false,
"address_families": ["IPv4 unicast", "IPv6 unicast"],
"add_path_receive": [],
"add_path_send": [],
"routes": 1,
"rejected_routes": 1,
"held_routes": 0,
"role": null,
"role_confirmed": null,
"last_error": null,
"retry_at_unix": null
}
| Field | Description |
|---|---|
state |
Session state: Established, Connecting, Backoff, or Idle. |
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. |
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. |
role_confirmed |
Whether the neighbor advertised a BGP role that matches the configured role. |
retry_at_unix |
For a neighbor without a session, the time of the next connection attempt. |
Received Routes
/api/routes/received returns received routes, one page at a time. Table 1
lists the query parameters.
| Parameter | Description |
|---|---|
prefix |
Returns all routes for the prefix, best path first. Example: prefix=193.0.0.0/21. |
address |
Returns all routes for the prefixes that contain the address, most specific first. Example: address=193.0.0.1. |
within |
Returns the routes for the prefix and all more specific prefixes. Example: within=193.0.0.0/16. |
peer |
Returns only routes from the neighbor, identified by name or address. |
best |
If true, returns only the best path for each prefix. |
limit |
Specifies the approximate number of routes in a page. Default: 1000. Maximum: 100000. |
after |
Returns the page after the specified prefix. Use the next_after value of the previous page. |
before |
Returns the page before the specified prefix. Use the prev_before value of the next page. |
A page contains only complete prefixes. It ends before the prefix whose
routes would exceed limit, but always contains at least one prefix.
Prefixes are sorted by address, with IPv4 prefixes first.
{
"routes": [{
"peer_name": "test-peer",
"peer_addr": "127.0.0.1:64815",
"peer_asn": 65001,
"prefix": "203.0.113.0/24",
"path_id": 0,
"best": true,
"rpki": null,
"aspa": null,
"summary": {
"origin": "IGP",
"as_path": [65001],
"next_hop": "10.0.0.2",
"med": null,
"local_pref": null,
"communities": ["65001:1"],
"large_communities": []
},
"attributes": [ ... ]
}],
"next_after": null,
"prev_before": null
}
| Field | Description |
|---|---|
path_id |
ADD-PATH path identifier, or 0. |
best |
Whether the route is the best path for the prefix. |
rpki, aspa |
Route origin validation and ASPA verification state, if RPKI validation is configured. |
attributes |
All path attributes, as received. |
Rejected Routes
/api/routes/rejected returns, for each neighbor with rejected routes, the
number of rejected routes for each reason and the 200 most recent rejected
routes. To return the records for one neighbor, add ?peer=NAME.
[{
"peer": "test-peer",
"peer_addr": "127.0.0.1",
"total": 1,
"by_reason": { "own AS in path": 1 },
"recent": [{
"prefix": "198.51.100.0/24",
"path_id": 0,
"reason": "own AS in path",
"as_path": [65001, 64500],
"at_unix": 1791020702,
"summary": {
"origin": "IGP",
"as_path": [65001, 64500],
"next_hop": "10.0.0.2",
"med": null,
"local_pref": null,
"communities": [],
"large_communities": []
},
"attributes": [
{ "Origin": 0 },
{ "AsPath": { "segments": [{ "ordered": true, "path": [65001, 64500] }] } },
{ "NextHop": "10.0.0.2" }
]
}]
}]
| Field | Description |
|---|---|
summary, attributes |
The path attributes of the rejected route, in the same format as for received routes. For a route rejected when RPKI data changed, the attributes as stored, including those added by the import policy. |
Kernel
/api/kernel returns the state of kernel route installation:
{
"enabled": true,
"table": 254,
"metric": 20,
"synced": true,
"installed": 0,
"kept": 0,
"unresolved": {},
"refused": 0,
"errors": 0,
"last_error": null,
"interfaces": [
{ "name": "eth0", "index": 2, "up": true,
"addresses": ["192.168.5.15/24", "fe80::5055:55ff:fed4:2526/64"] }
]
}
| Field | Description |
|---|---|
synced |
Whether the kernel routing table has been synchronized with the routing table since the daemon started. |
installed |
Number of routes installed. |
kept |
Number of routes from a previous run that are retained during startup. |
unresolved |
Number of prefixes whose active route is not installed, by reason. |
refused |
Number of prefixes whose active route the kernel rejected. |
errors |
Number of requests that the kernel rejected. |
Events
/api/events is a stream of
server-sent events.
Each event has the name bgp and contains a JSON object. The type field
identifies the event, as listed in Table 2.
type |
Description |
|---|---|
session_up |
A session was established. The peer field has the format of /api/peers. |
session_down |
A session ended. Fields: peer_addr, peer_asn. |
route_refresh_requested |
A neighbor sent a ROUTE-REFRESH message. |
local_announced, local_withdrawn |
An originated route was advertised or withdrawn. |
best_changed |
The best path for a prefix changed. The route field contains the new best path. |
best_withdrawn |
A prefix no longer has a route. |
lagged |
The client did not read events quickly enough and missed events on stream. Reload the corresponding table. |
The following command displays the event stream:
curl -sN 127.0.0.1:8080/api/events