BMP TCP Out Unit¶
The bmp-tcp-out unit restreams BMP (BGP Monitoring Protocol, RFC 7854) data to
downstream consumers. It accepts TCP connections from BMP collectors and sends
them a full initial table dump followed by real-time updates.
Configuration¶
[units.bmp-out]
type = "bmp-tcp-out"
listen = "0.0.0.0:11020"
sources = ["rib"]
rib_unit = "rib"
sys_name = "netom-bmp-out"
sys_descr = "Netom BMP restreamer"
max_client_buffer = 100000
forward_router_info = true
acl = ["0.0.0.0/0", "::/0"]
# Optional TLS
tls = false
tls_cert = "/path/to/cert.pem"
tls_key = "/path/to/key.pem"
Parameters¶
Parameter |
Required |
Default |
Description |
|---|---|---|---|
|
yes |
— |
Address and port to listen on for BMP client connections. |
|
yes |
— |
Upstream gate(s) to receive live updates from (typically a RIB unit). |
|
no |
|
Name of the RIB unit used for the initial table dump. |
|
no |
|
Value sent in the BMP Initiation Message sysName TLV. |
|
no |
|
Value sent in the BMP Initiation Message sysDescr TLV. |
|
no |
|
Maximum number of updates buffered per client during the initial dump phase. If exceeded, the client is disconnected. See Buffer Overflow below. |
|
yes |
— |
List of allowed client IP addresses or CIDR prefixes. Use |
|
no |
|
Include upstream router identity (sysName/sysDescr) as a JSON Admin Label TLV (type 4, RFC 9736) in Peer Up messages. |
|
no |
|
Restream live Route Monitoring messages verbatim instead of rebuilding them from parsed routes, for peers whose raw copies arrive from a |
|
no |
|
Enable TLS encryption for client connections. |
|
no |
— |
Path to PEM certificate file. If omitted with |
|
no |
— |
Path to PEM private key file. Required if |
How It Works¶
Connection Lifecycle¶
When a BMP consumer connects:
ACL check — the client IP is checked against the
acllist. Rejected connections are closed immediately.Initiation Message — a BMP Initiation Message (type 4) is sent with
sys_nameandsys_descr.Initial table dump — for each active BGP peer known to Netom:
A BMP Peer Up Notification is sent (with synthetic BGP OPEN messages).
All routes for that peer are read from the RIB and sent as BMP Route Monitoring messages.
End-of-RIB markers are sent per address family (IPv4 Unicast, IPv6 Unicast).
Buffered updates drained — any live updates that arrived during the dump are replayed.
Live phase — the client receives real-time updates as they arrive from upstream.
Update Types¶
Upstream event |
BMP message sent |
|---|---|
Route announcement/withdrawal |
Route Monitoring (type 0) wrapping a BGP UPDATE |
BGP session down |
Peer Down Notification (type 2) |
BGP session reappears |
Peer Up Notification (type 3) |
Buffer Overflow¶
During the initial dump phase, live updates are buffered in memory so they can be replayed after the dump completes. If the RIB is large and the update rate is high, the buffer can fill up before the dump finishes.
When the buffer exceeds max_client_buffer, the client is disconnected. The
netom_bmp_tcp_out_buffer_overflows_total metric tracks how often this happens.
Tuning considerations:
If
netom_bmp_tcp_out_buffer_overflows_totalis increasing and the system has sufficient RAM available, increasingmax_client_buffer(e.g., to 200000 or 500000) can resolve the issue by giving the initial dump more time to complete before the buffer fills up.Each buffered update consumes approximately 750-900 bytes of memory. Use this table to estimate peak memory usage per client:
max_client_bufferApprox. RAM per client
100,000 (default)
~75-90 MB
200,000
~150-180 MB
500,000
~375-450 MB
If buffer overflows persist even with a larger buffer, the root cause is usually that the dump is too slow relative to the update rate. Consider whether the consuming application can keep up with the data rate.
Admin Label TLV (Upstream Router Identity)¶
When forward_router_info = true (the default), each Peer Up Notification
includes an Admin Label TLV (type 4, as defined in RFC 9736). The value is
a JSON object carrying the upstream BMP router’s sysName and sysDescr that
were received via the BMP Initiation Message on the bmp-tcp-in side.
This allows downstream BMP consumers to identify which upstream router each peer belongs to, even when netom multiplexes multiple routers into a single BMP session.
Fields whose value is a placeholder ("no-sysname" / "no-sysdesc") or empty
are omitted from the JSON. If both fields are absent, the TLV is not included.
Set forward_router_info = false to disable the TLV entirely.
Wire Format Specification for Downstream Implementors¶
The TLV appears after the two BGP OPEN messages inside the BMP Peer Up Notification (message type 3), as permitted by RFC 9736 Section 4.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type = 4 | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Value (UTF-8 JSON) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Type (2 bytes, big-endian):
0x0004— Admin Label (RFC 9736 Section 4.4).Length (2 bytes, big-endian): byte length of the Value field.
Value: UTF-8 encoded JSON object.
JSON Schema¶
{
"sysName": "<string>",
"sysDescr": "<string>"
}
Both keys are optional. At least one will be present when the TLV is included.
Values are JSON-escaped (e.g. \", \\, \n). Downstream parsers should
tolerate unknown keys for forward compatibility.
Parsing Algorithm¶
To extract the Admin Label from a Peer Up Notification:
Parse the BMP Common Header (6 bytes) — verify message type = 3.
Skip the Per-Peer Header (42 bytes).
Skip Local Address (16 bytes), Local Port (2 bytes), Remote Port (2 bytes).
Parse the Sent OPEN message: read its BGP length field (bytes 16–17 of the BGP message, big-endian) and skip that many bytes total.
Parse the Received OPEN message the same way.
Any remaining bytes are TLVs. For each TLV:
Read Type (2 bytes) and Length (2 bytes), both big-endian.
If Type = 4, the next Length bytes are the Admin Label JSON.
Otherwise skip Length bytes (unknown TLV — ignore).
Examples¶
Full Peer Up with Admin Label (both fields):
Type: 0x0004 Length: 0x002E
Value: {"sysName":"edge-rtr01","sysDescr":"Cisco IOS XR 7.9.1"}
Only sysName present:
Type: 0x0004 Length: 0x001A
Value: {"sysName":"edge-rtr01"}
No Admin Label TLV is present when:
forward_router_info = falsein config, orThe upstream BMP router did not send sysName/sysDescr in its Initiation Message, or sent only placeholder values.
Fastpath¶
Without fastpath, every restreamed Route Monitoring message is rebuilt: the upstream message is parsed into per-route payloads at ingest, stored in the RIB, and re-encoded into a fresh BGP UPDATE here. With fastpath the live path instead forwards the original BGP UPDATE bytes verbatim, re-synthesizing only the BMP common and per-peer headers.
Fastpath is on by default on both ends:
[units.bmp-in]
type = "bmp-tcp-in"
forward_raw_updates = true # default; emit verbatim copies before the parsed routes
[units.bmp-out]
type = "bmp-tcp-out"
fastpath = true # default; consume them, skip the rebuild path per covered peer
Coverage is adaptive per peer, so any flag combination is loss-free: a
peer is served from raw copies only while its raw copies are actually
arriving. bmp-tcp-in emits the raw copy before the parsed payloads of
the same message and does so for every parsed message of an eligible
session, so the switchover point can neither duplicate a message nor drop
one. Coverage marks are cleared on Peer Down / session teardown, because
ingress ids can be re-bound to reconnecting sessions with different
settings.
What fastpath changes:
Fidelity — path attributes, exotic/unknown attributes and the exact NLRI encoding reach the consumer byte-for-byte; the per-peer header timestamp is the original export time; the A-flag (legacy 2-byte AS encoding) reflects the encoding the message actually parsed with. The peer identity fields and the fan-in
peer_distinguisherstill come from the Peer Up this unit synthesized, so the (peer, pd, rib_type) keying stays consistent.Live EoR passthrough — upstream End-of-RIB markers received after the initial dump phase are forwarded verbatim (the rebuild path never restreamed live EoRs at all). Messages carrying only NLRI types the RIB cannot store are likewise forwarded instead of vanishing.
Cost — the per-route re-encode and pa-blob re-aggregation are skipped on the live path.
What it does not change:
The initial table dump stays on the rebuild path — raw bytes are not stored in the RIB.
Non-BMP sources (BGP, MRT) have no raw copies; their routes keep being rebuilt.
ADD-PATH sessions participate fully. Each
(session, path_id)is stored under its own path-child ingress (IngressType::BgpPath); on emit the child resolves back to its parent session’s per-peer header, the synthesized Peer Up advertises the ADD-PATH capability (code 69, SendReceive, in both OPENs) for the session’s negotiated v4/v6 unicast families, and the rebuild path re-attaches the 4-byte path id to the NLRI — in the initial dump and live. Withfastpathenabled their live UPDATEs are forwarded verbatim like any other BMP session (the raw copy carries the session id; the duplicate-suppression check resolves the parsed payloads’ child ids back to the session). (Multicast ADD-PATH routes are emitted with path ids inside the unicast NLRI space — the encoder’s pre-existing family collapse; FlowSpec-ADD-PATH routes are dropped at ingest.)
Caveat: fastpath is a pre-filter mirror. Routes dropped or rewritten by
roto filters in upstream units are restreamed in their original form. Set
fastpath = false on this unit if downstream consumers must observe
filtered data. In pipelines with no bmp-tcp-out unit at all, set
forward_raw_updates = false on bmp-tcp-in to save one gate update per
Route Monitoring message.
Prometheus Metrics¶
All metrics are exported under the configured unit name (e.g., component="bmp-out").
Metric |
Type |
Description |
|---|---|---|
|
counter |
Number of times the TCP listen port was bound. |
|
counter |
Total BMP client connections accepted. |
|
counter |
Total BMP client connections lost. |
|
counter |
Total BMP messages sent to all clients. |
|
counter |
Total bytes sent to all clients. |
|
gauge |
Number of clients currently receiving an initial table dump. |
|
counter |
Number of clients disconnected due to buffer overflow during dump. |
|
counter |
Number of connections rejected by ACL. |
|
counter |
Number of TLS handshake failures. |
Example Configuration¶
Minimal setup receiving from a BMP input and restreaming:
[units.bmp-in]
type = "bmp-tcp-in"
listen = "0.0.0.0:11019"
[units.rib]
type = "rib"
sources = ["bmp-in"]
[units.bmp-out]
type = "bmp-tcp-out"
listen = "0.0.0.0:11020"
sources = ["rib"]
rib_unit = "rib"
acl = ["0.0.0.0/0", "::/0"]
[targets.null]
type = "null-out"
sources = ["rib"]
With TLS and restricted access:
[units.bmp-out]
type = "bmp-tcp-out"
listen = "0.0.0.0:11020"
sources = ["rib"]
rib_unit = "rib"
sys_name = "my-collector"
sys_descr = "Production BMP restreamer"
max_client_buffer = 200000
acl = ["10.0.0.0/8", "2001:db8::/32"]
tls = true
tls_cert = "/etc/netom/cert.pem"
tls_key = "/etc/netom/key.pem"