Skip to content
Open
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Rotonda version from which it was forked, Netom adds:

- [active TCP/TLS BMP input](docs/bmp-tcp-in.md) for pulling exporter feeds;
- BMP restreaming with an initial RIB dump followed by live updates;
- [EVPN monitoring](docs/evpn.md) with tenant-aware route queries for symmetric IRB;
- bounded buffers, streaming full-RIB exports, and slow-consumer protection;
- stronger BMP peer lifecycle, reconnect, withdrawal, and memory handling;
- TLS and access controls for BMP consumers;
Expand Down
7 changes: 7 additions & 0 deletions doc/netom-cli.1
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,13 @@ as above; the other filters are not implemented for FlowSpec.
.B show ipv6 bgp ...
As above, for IPv6.
.TP
.B show evpn
EVPN routes with RD, MAC/prefix, VNIs, next hop, route targets, peer/path,
and active/withdrawn state. Optional filters, in order: rd VALUE or
route-target VALUE; route-type NUMBER; one of vni NUMBER, prefix PREFIX,
or ingress ID; include-withdrawn; detail. Detail displays all returned
fields and attributes. With --json, emits the buffered data-array response.
.TP
.B show bmp routers
Monitored routers feeding BMP to this daemon.
.TP
Expand Down
29 changes: 29 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,35 @@ Commands:
exit Exit the CLI
```

## EVPN routes

`show evpn` queries the [EVPN RIB](evpn.md), including both IPv4 and IPv6
routes. The table shows route type, RD, MAC/prefix, both VNI fields, next hop,
route targets, source peer/path ID, and active/withdrawn state.

```sh
netom-cli show evpn
netom-cli show evpn route-target 65000:100 route-type 5
netom-cli show evpn rd 192.0.2.1:100 vni 50000
netom-cli show evpn prefix 2001:db8::/64
netom-cli show evpn ingress 101 include-withdrawn detail
netom-cli --json show evpn route-target 65000:100
```

Combine filters in this order, omitting stages as needed:

1. `rd <value>` or `route-target <value>`.
2. `route-type <1-255>` (type 2 MAC/IP, type 5 IP prefix).
3. One of `vni <0-16777215>`, `prefix <address/length>`, or `ingress <id>`.
4. `include-withdrawn`, then `detail`.

`ingress` matches the stored ingress ID, including an ADD-PATH child ID.
`include-withdrawn` requires retained withdrawn records on the daemon.
`detail` displays all returned fields, including ESI, gateway, Router's MAC,
raw NLRI, and attributes. `--json` passes through the original buffered
`{"data": [...]}` response. VNI columns contain raw 24-bit label fields;
interpret them as VNIs for VXLAN, not as decoded MPLS label numbers.

## Finding the daemon

In order: `--url`, `$NETOM_URL`, `-c <config>`, `./netom.conf`,
Expand Down
10 changes: 10 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ Component-specific settings belong under that component's table, such as
placing a global setting at the end of the file would put it inside the
last component instead.

## Enable EVPN monitoring

The global runtime setting `enable_evpn` defaults to `false`. Set
`enable_evpn = true` above the first component table and restart Netom to
opt in to EVPN ingestion, BGP capabilities, and API queries. Reloads cannot
change this setting. A peer's `protocols = ["L2VpnEvpn"]` alone does not enable
EVPN. The opt-in avoids accidentally retaining additional EVPN routing state
and incurring its query memory and CPU costs; see [EVPN monitoring](evpn.md)
for behavior and configuration details.

## Example files

The [annotated configuration](../etc/netom.conf) is maintained with the
Expand Down
116 changes: 116 additions & 0 deletions docs/evpn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# EVPN monitoring

EVPN monitoring is **disabled by default**. Enable it explicitly in the
TOML global settings, above all `[units.*]` and `[targets.*]` tables:

```toml
enable_evpn = true
```

Restart Netom after changing this flag; a reload that changes it is rejected.
This keeps negotiated BGP capabilities and retained routing state consistent.
When disabled, Netom omits EVPN from BGP MP and ADD-PATH capabilities, drops
EVPN announcements and withdrawals from BGP/BMP route conversion through the
unsupported-NLRI accounting path, and returns HTTP 503 with an enablement
message for EVPN queries. Other families continue to work. Verbatim BMP
forwarding is independent of monitoring and can still carry EVPN updates.

EVPN retains a separate collection of routes and attributes, and queries incur
additional copying, allocation, and serialization costs. These costs grow with
routes, paths, tenants, and concurrent queries. Requiring an explicit opt-in
keeps deployments that only monitor other families from accidentally taking
on this state and query load. Enabling EVPN is not a memory or query-cost limit;
size the deployment for its routing state and workload.

With the flag enabled, Netom collects L2VPN EVPN (AFI 25, SAFI 70) from BGP and BMP, including
ADD-PATH sessions. Configure `L2VpnEvpn` in a BGP peer's `protocols` list;
BMP peers use the capabilities in their exported Peer Up messages.

EVPN routes live in a separate RIB. Overlapping tenant prefixes do not collide
with each other or with the global unicast table. Identity includes the route
type, wire-format route distinguisher (RD), route-specific key, and ingress
(including the ADD-PATH child). Type 2 identity excludes ESI and labels;
type 5 identity excludes ESI, gateway, and label. Changes to forwarding fields
replace the same route, and withdrawals match even when labels differ.
Peer Down, family-scoped withdrawals, and ingress cleanup include EVPN.

## Symmetric IRB

Inspect type 2 MAC/IP advertisements and type 5 IP prefix advertisements
together to monitor the MAC-VRF and IP-VRF views of a tenant. The decoder
exposes the RD, Ethernet tag, ESI, MAC, IPv4/IPv6 host or prefix, gateway,
and label fields. Both type 2 labels are preserved for deployments that
advertise a MAC-VRF label and an IP-VRF label.

The API also decodes route targets, the EVPN Router's MAC extended community,
and the MP_REACH next hop. Use a route target to select the routes associated
with a tenant across multiple advertising RDs. An RD distinguishes routes;
it is not a tenant membership or import-policy identifier. Route targets are
reported as advertised; Netom does not simulate VRF import policy or recursive
forwarding resolution.

Label fields are returned as **raw 24-bit integers**. For VXLAN these are
VNIs. For MPLS, decode the label-stack entry according to the encapsulation;
do not interpret the raw field as an MPLS label number. The API does not
infer which VNI is an L2 VNI or L3 VNI from its value alone.

## Query API

`GET /api/v1/ribs/l2vpnevpn/routes` returns `{"data": [...]}`. Each row has:

- `route`: `nlri`, retained `attributes`, `ingress_id`, `ltime`, and `active`;
- `overlay`: `route_targets`, `router_mac`, and `next_hop`;
- `source_ingress_id` and `path_id`: original session and optional ADD-PATH ID.

The `nlri.raw` byte array includes the route type and length header, allowing
inspection of fields not decoded by the API. Types 1, 3, and 4 are retained,
with RD and applicable tag/ESI fields decoded. Unknown route types with an RD
are preserved as opaque records and matched by their complete NLRI.

All filters below are optional and combine with AND:

| Parameter | Meaning |
| --- | --- |
| `rd` | Exact RD, e.g. `65000:100` or `192.0.2.1:100` |
| `route_target` | Exact advertised RT, e.g. `65000:100` |
| `route_type` | Numeric EVPN type, e.g. `2` or `5` |
| `vni` | Match either raw label field (for VXLAN monitoring) |
| `prefix` | Exact type 2 host or type 5 prefix |
| `ingress_id` | Exact stored ingress ID, including ADD-PATH child IDs |
| `include_withdrawn` | `true` includes retained withdrawn records; default `false` |

Unknown parameters are rejected. Withdrawn records are available only when
the RIB is configured to retain withdrawn attributes. A withdrawal preserves
the last announced attributes and forwarding fields.

```sh
curl -G http://127.0.0.1:8080/api/v1/ribs/l2vpnevpn/routes \
--data-urlencode 'route_target=65000:100' \
--data-urlencode 'route_type=5'

curl -G http://127.0.0.1:8080/api/v1/ribs/l2vpnevpn/routes \
--data-urlencode 'rd=192.0.2.1:100' \
--data-urlencode 'prefix=10.0.0.0/24'
```

The endpoint produces buffered JSON and takes a snapshot of the EVPN table;
large tables require memory proportional to the stored records and response.
It shares the concurrent query limit with other RIB queries.

## Pipeline support and limits

BMP output includes EVPN in live rebuilt updates and initial RIB dumps,
retaining next hops, communities, and ADD-PATH IDs. Synthetic Peer Up messages
and End-of-RIB markers include EVPN when advertised by the source peer.
BGP4MP MRT updates use the same decoder; TABLE_DUMP_V2 EVPN import is not
implemented. Use [`netom-cli show evpn`](cli.md#evpn-routes) for interactive
inspection.
The ClickHouse route schema does not expose EVPN.

Roto route filters can use `is_evpn()` and `evpn_rd()`. `fmt_prefix()` returns
the type 2 host or type 5 prefix; EVPN routes without an IP prefix return
`0.0.0.0/0`, so guard IP-only policies with `is_evpn()`.

Wire formats follow [RFC 7432](https://www.rfc-editor.org/rfc/rfc7432),
[RFC 9135](https://www.rfc-editor.org/rfc/rfc9135), and
[RFC 9136](https://www.rfc-editor.org/rfc/rfc9136).
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ clickhouse

rib-query-api
addpath-flowspec-api
evpn
best-path-selection
```

Expand Down
3 changes: 3 additions & 0 deletions docs/rib-query-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ in this API changes state.

## Endpoints

EVPN uses a separate [tenant-aware endpoint](evpn.md).

| Endpoint | Returns |
| --- | --- |
| `GET /api/v1/ribs/l2vpnevpn/routes` | EVPN routes, with RD/RT/VNI filters (see [EVPN](evpn.md)) |
| `GET /api/v1/ribs/ipv4unicast/routes/{addr}/{len}` | every route for one prefix |
| `GET /api/v1/ribs/ipv6unicast/routes/{addr}/{len}` | |
| `GET /api/v1/ribs/ipv4unicast/routes` | the whole table (see [Whole-table dumps](#whole-table-dumps)) |
Expand Down
5 changes: 5 additions & 0 deletions etc/netom.conf
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ log_target = "stderr" # "stderr", "file" or "syslog"

http_listen = ["[::]:8080"]

# EVPN monitoring is an explicit opt-in because its retained routes and API
# queries add memory and CPU costs. Defaults to false; changes need a restart.
# Also configure L2VpnEvpn in BGP peer protocols when using BGP input.
# enable_evpn = true


### 2. Component Definitions

Expand Down
Loading