Status: Accepted Date: 2026-03-05
MRT (Multi-Threaded Routing Toolkit) is the standard format for BGP RIB snapshots and UPDATE archives. Route collectors (RIPE RIS, RouteViews) and offline analysis tools consume MRT files. GoBGP supports MRT dump; rustbgpd should too for operational parity.
RFC 6396 defines the MRT format. TABLE_DUMP_V2 (type 13) is the modern RIB snapshot format, superseding the original TABLE_DUMP (type 12). RFC 8050 extends TABLE_DUMP_V2 with Add-Path subtypes (8/9) for path-ID-aware dumps.
The key challenge is that rustbgpd strips next-hop and MP_REACH_NLRI attributes from routes per the MP-BGP architecture (ADR-0023). The MRT codec must synthesize these attributes when encoding.
A new rustbgpd-mrt crate with four modules:
-
codec.rs-- Pure encoding functions for TABLE_DUMP_V2 records.PEER_INDEX_TABLE(subtype 1),RIB_IPV4_UNICAST(2),RIB_IPV6_UNICAST(4), and Add-Path variants (8/9 per RFC 8050).EncodeErrorenum for explicit length-overflow handling -- no silent truncation. -
writer.rs-- Atomic file writer (temp + rename). Optional gzip via flate2. Collision-resistant filenames:{prefix}.{YYYYMMDD.HHMMSS}.{nanos:09}.mrt[.gz]. -
manager.rs--MrtManagerwithtokio::select!over a periodic interval timer and a trigger channel for on-demand dumps. Queries the RIB viaQueryMrtSnapshot, encodes viaspawn_blocking, writes atomically. -
types.rs--MrtWriterConfigand re-exports ofMrtPeerEntryandMrtSnapshotDatafrom the rib crate.
synthesize_attributes() reconstructs stripped next-hop attributes:
- IPv4 prefix, IPv4 next-hop:
PathAttribute::NextHop(ipv4)inserted in canonical position (after ORIGIN and AS_PATH). - IPv6 prefix:
PathAttribute::MpReachNlriwith IPv6 next-hop, empty NLRI (prefix is in the RIB entry header per TABLE_DUMP_V2). - IPv4 prefix, IPv6 next-hop (RFC 8950):
PathAttribute::MpReachNlriwithAfi::Ipv4,Safi::Unicast, and the IPv6 next-hop. NoNextHopattribute is emitted.
QueryMrtSnapshot collects routes from all per-peer Adj-RIB-In tables.
Loc-RIB is not overlaid, which avoids duplicate entries for the best-path
winner (who would appear in both Adj-RIB-In and Loc-RIB).
RibManager gains peer_asn: HashMap<IpAddr, u32> and
peer_bgp_id: HashMap<IpAddr, Ipv4Addr>, populated on PeerUp and
cleared on PeerDown. These are not cleared during
PeerGracefulRestart or LLGR transitions, so dumps taken during a GR
window still include correct PEER_INDEX_TABLE entries.
Routes from peers not in the explicit metadata (e.g., injected routes
from the sentinel 0.0.0.0 peer) are included with a synthetic peer
entry (bgp_id = 0.0.0.0, asn = 0).
encode_snapshot() sorts peers by (address family, IP, ASN, BGP ID),
prefixes by (family, address, length), and routes within each prefix by
(peer index, path_id). This ensures byte-identical output for identical
RIB state.
- gRPC:
TriggerMrtDumpRPC onControlService. Returns the file path of the produced dump.FAILED_PRECONDITIONwhen MRT is not configured. - CLI:
rustbgpctl mrt-dumpsubcommand. - Config:
[mrt]TOML section withoutput_dir,dump_interval(default 7200),compress(default false),file_prefix(default "rib"). - SIGHUP: MRT config changes logged as warning, require restart (same as other global config).
- TABLE_DUMP (type 12) -- legacy format, not implemented.
- BGP4MP (type 16/17) -- UPDATE stream recording. Deferred; BMP Route Monitoring serves a similar role.
- FlowSpec RIB entries -- TABLE_DUMP_V2 is defined for unicast NLRI. FlowSpec dump is not standard and is deferred.
- Loc-RIB overlay -- intentionally excluded to prevent duplication.
L2VPN/EVPN routes (AFI 25 / SAFI 70) are emitted as RIB_GENERIC
records (subtype 6, RFC 6396 §4.3.5). Per-record layout: 4-byte
sequence number, 2-byte AFI, 1-byte SAFI, variable-length NLRI
encoded as the EVPN route TLV (route type + length + body, via
encode_evpn_nlri), 2-byte entry count = 1, then a single RIB
entry. EVPN does not use Add-Path in this codebase, so no
RIB_GENERIC_ADDPATH variant is needed. Attribute synthesis adds
an MP_REACH_NLRI(AFI=25, SAFI=70, next_hop, evpn_announced=[])
carrying the next-hop only — the NLRI itself rides in the record
header. Sort order across EVPN routes is (peer_index, encoded NLRI bytes) because EvpnRouteKey does not derive Ord; the
canonical NLRI byte representation is total-orderable.
- Completes the monitoring/archival story alongside BMP. MRT files are consumable by standard tools (bgpdump, pybgpstream, mrtparse).
- GoBGP parity for the monitoring category reaches 100%.
- Atomic writes and gzip prevent partial/corrupt dumps.
- Deterministic output enables diff-based regression testing.
- Zero overhead when unconfigured (no manager task spawned).
- Snapshot encoding is allocation-heavy for very large RIBs (groups routes by prefix, clones attributes per entry). Tracked as a deferred hardening item, not a correctness issue.
peer_asn/peer_bgp_idHashMaps add two small maps to RibManager state. Negligible memory impact.
- MRT config changes require daemon restart (consistent with BMP, RPKI).
- On-demand trigger returns the file path synchronously, blocking the gRPC handler until the dump completes. For very large RIBs this could be slow; a future enhancement could make it async with a status poll.