v0.20.0
Breaking changes
-
Fallible encoding (#313): all encode paths now return
Result<_, EncodingError>instead of silently truncating values that do not fit their wire-format fields. There are no panicking wrappers; callers that want the old "just give me bytes" ergonomics can.unwrap(). Migration table:Before After Attribute::encode(asn_len) -> Bytes-> Result<Bytes, EncodingError>(alsoencode_to(asn_len, &mut BytesMut))Attributes::encode(asn_len) -> Bytes-> Result<Bytes, EncodingError>(alsoencode_to)BgpOpenMessage::encode() -> Bytes-> Result<Bytes, EncodingError>BgpUpdateMessage::encode(asn_len) -> Bytes-> Result<Bytes, EncodingError>BgpMessage::encode(asn_len) -> Bytes-> Result<Bytes, EncodingError>TableDumpMessage::encode() -> Bytes-> Result<Bytes, EncodingError>RibEntry::encode()/RibAfiEntries::encode() -> Bytes-> Result<Bytes, EncodingError>PeerIndexTable::encode()/GeoPeerTable::encode() -> Bytes-> Result<Bytes, EncodingError>PeerIndexTable::add_peer(peer) -> u16-> Result<u16, EncodingError>(rejects the 65,536th peer instead of wrapping the id)MrtMessage::encode(sub_type)/Bgp4MpMessage::encode(asn_len)/MrtRecord::encode() -> Bytes-> Result<Bytes, EncodingError>MrtRibEncoder::process_elem(&elem)-> Result<(), EncodingError>MrtRibEncoder::export_bytes()/MrtUpdatesEncoder::export_bytes() -> Bytes-> Result<Bytes, EncodingError>EncodingErrorhas two variants:ValueTooLarge { field, actual, max }for wire-capacity overflows andUnencodable { field, reason }for values with no valid wire representation (ATTR_SET, RIB_GENERIC, OPEN parameter type 255, labeled NLRI with an empty label stack). -
Legacy MRT enum variants:
MrtMessagegainsTableDumpMessageBatchandLegacyBgp, andMrtUpdategainsLegacyBgpUpdate. Downstream exhaustive matches must handle the new variants. -
Traffic Engineering attribute variant:
AttributeValuegainsTrafficEngineering(#290). The code-24 BGP Traffic Engineering attribute (RFC 5543), previously raw-retained, now parses to this typed variant. Downstream exhaustive matches must handle the new variant. -
Link Bandwidth extended community variant:
ExtendedCommunitygainsLinkBandwidth(#299). Two-octet AS-specific extended communities with subtype 0x04 (RFC 10005 link bandwidth) now parse to this variant instead ofTransitiveTwoOctetAs/NonTransitiveTwoOctetAs, changing theirDisplayand serde representations (wire encoding is byte-identical). Downstream exhaustive matches must handle the new variant. -
Tlv::length()andSubTlv::length()removed: both silently saturated atu16::MAX; encoders now compute checked lengths internally. -
OptParamno longer has aparam_lenfield: the field was redundant now that the encoder always derives the wire length fromparam_value, and the parser recomputes it on read. ConstructOptParamwith justparam_typeandparam_value. -
Quagga BGP states:
BgpStategains the implementation-specificClearingandDeletedvariants for wire values 7 and 8. Downstream exhaustive matches must handle the new variants. -
ROUTE-REFRESH message variant:
BgpMessagegainsRouteRefresh(BgpRouteRefreshMessage)andBgpMessageTypegainsROUTE_REFRESHfor BGP message type 5 (RFC 2918), previously rejected as "Unknown BGP Message Type". Downstream exhaustive matches must handle the new variants.
Added
Parser interfaces
- Unified MRT/text-dump parser API (#321):
BgpkitParsergains three new constructor groups that integrate text dumps into the standardfor elem in parseriteration loop.new_text(path)/from_text_reader(r)parse a known text dump;new_auto(path)/from_auto_reader(r)peek the first bytes and auto-dispatch to the text or MRT path. Both text-dump paths stream elements lazily — one route line at a time, constant memory — via a newTextDumpElemIterator. All existing filter methods (add_filter,with_filters, etc.) work on both paths. The defaultnew(path)constructor remains MRT-only. - Diagnostic MRT iterator (#324, #303): added
into_diagnostic_iter()for record-level malformed-data investigation. It emits clean records, recoverable RFC 7606 validation findings with original MRT bytes, and fatal parse errors with available header and byte context. - Experimental resumable HTTP reader (#323):
BgpkitParser::new_resumable_httpuses oneio's range-request reader to resume interrupted HTTP(S) downloads without changing the behavior ofnew. Unsupported Range requests or inconsistent resumed responses return an error (#288). - Cisco
sh ip bgptext dump parsing (#320): newparser::text_dumpmodule parses fixed-width text RIB dumps published by PCH (daily routing table snapshots) and route-views (oix-full-snapshot-*.bz2) intoBgpElems. Column offsets are derived from the table header so blank numeric columns (Metric, LocPrf, Weight) stay distinct from AS-path data; multipath continuation lines and wrapped prefixes (including IPv6) are supported. Route-views dumps without theBGP table version/local ASpreamble parse with sentinel peer identity (0.0.0.0/ AS0) (#321). Also providesdetect_text_dumpfor format sniffing andinfer_timestamp_from_pathfor PCH (YYYY.MM.DD) and route-views (YYYY-MM-DD-HHMM) file-name timestamps. Ported from monocle (#143, #146).
Protocol support
- Early RIPE RIS MRT support (#316): Parse deprecated MRT Type 5 BGP OPEN, UPDATE, NOTIFY, KEEPALIVE, and STATE_CHANGE records, along with historical TABLE_DUMP v1 records that batch multiple entries and declare their physical length four bytes short. Record iteration preserves each physical TABLE_DUMP batch while element, update, and route iteration expands its entries.
- RFC 5543 Traffic Engineering attribute (#322): Typed parsing and encoding for the BGP Traffic Engineering attribute (type 24) (#290). Exposes the Switching Capability, Encoding, Reserved, and eight Maximum LSP Bandwidth fields (IEEE-754), and retains switching-capability-specific information as raw bytes with wire-faithful round-trip.
- RFC 2918 ROUTE-REFRESH messages (#326): Parse and encode BGP ROUTE-REFRESH messages (type 5) found in RIS BGP4MP update archives. AFI and SAFI are kept as raw integers so refreshes for address families outside the typed enums still round-trip byte-for-byte; the reserved byte is exposed as the RFC 7313 message subtype and trailing ORF data (RFC 5291) is retained raw. ROUTE-REFRESH records yield no elements. RFC 7313 Section 5 findings — an unknown message subtype, or a BoRR/EoRR message whose body is not exactly 4 bytes — surface as new
BgpValidationWarningvariants (UnknownRouteRefreshSubtype,InvalidRouteRefreshLength) throughBgpRouteRefreshMessage::validation_warnings()and the diagnostic iterator, while the message itself is retained. - RFC 10005 Link Bandwidth Extended Community (#319): Typed parsing and encoding for the BGP Link Bandwidth Extended Community in both transitive (
0x00) and non-transitive (0x40) forms (#299). Exposes the Global Administrator, bandwidth in bytes per second, and transitivity, and preserves the wire type on encode. - Updated
bgpkit-brokerdependency from 0.11 to 0.12 (#318). - Fixed standalone
clifeature:cargo build --no-default-features --features clinow compiles; the CLI binary was previously broken in that combination becauseBgpkitParser::new/new_cachedrequireoneio(broken since at least v0.18.0, and not covered by any CI feature combination). TLS backend selection is unchanged: standaloneclienablesoneio's plain-HTTP reader, andcli,rustls/cli,native-tlsselect a backend additively as before.
Test data
- Historical RIPE regression fixtures (#316): Added original RRC00 update and bview gzip files from 1999 and January 2000 as repository-only, offline integration fixtures.
- PacketLife ORF capture fixture (#326): Added the PacketLife.net "bgp orf prefix advertisement" capture (via https://github.com/epiecs/packetlife-backup) as a repository-only fixture exercising ROUTE-REFRESH with RFC 5291 ORF payload bytes extracted from the pcapng TCP stream.
- Opt-in MRT framing recovery (#325): Added
into_recovering_record_iter,into_recovering_elem_iter, and CLI--recoversupport for salvaging records after damaged MRT framing. Recovery validates a three-record chain, uses exact embedded BGP headers as BGP4MP anchors, and reports every skipped decompressed byte range as a typed gap event. A record of any MRT type whose framing is intact but whose body fails to parse is skipped exactly (AlignedRecordChainevidence) when intact records follow its declared boundary, and damage extending to the end of the stream — e.g. a truncated final record — is reported as a terminal gap (EndOfStreamevidence) instead of an error. Text-dump parsers, which have no MRT record representation, yield an explicitUnsupportederror.
Examples
- Diagnostic MRT iterator example (#324): Added
examples/diagnostic_iterator.rsto classify clean records, RFC 7606 validation findings, and fatal parse errors while exporting raw MRT bytes for each finding. - Resumable HTTP reader example (#323): Added
examples/resumable_http.rsto parse a remote MRT file withnew_resumable_httpand report unrecoverable read failures.
Fixed
- Fallible MRT error bytes (#315): Header, oversized-record, partial-body, and route-iterator failures now retain all consumed record bytes. Default/raw iteration only writes
mrt_core_dumpwhen explicitly enabled, and raw error skipping no longer recurses. - Silent truncation on encode eliminated (#313): AS_PATH segments with >255 ASes, attribute values exceeding their (extended or non-extended) length field, TLV values in Tunnel Encapsulation / BGP-LS / SFP / BFD Discriminator / Prefix-SID / BIER attributes, RIB entry counts, peer counts, view names, and BGP message total lengths now return
EncodingErrorinstead of writing corrupt length fields. - FlowSpec NLRI length bound: the wire length field is 12-bit (RFC 8955); NLRI data of 4096..=65535 bytes previously passed an unchecked
u16cast and encoded a corrupt length byte. It is now rejected withValueTooLarge. - MP_REACH/MP_UNREACH encoding errors are no longer swallowed: labeled-NLRI failures previously logged a warning and emitted a zero-length (RFC-invalid) attribute value; they now propagate as
EncodingError. - FlowSpec NLRI entries are now encoded:
Nlri::flowspec_nlriswas previously silently dropped when encoding MP_REACH/MP_UNREACH attributes. - Peer index aliasing:
PeerIndexTable::add_peerpreviously wrapped the peer id at 65,536 peers, silently attributing routes to the wrong peer; it now returns an error and leaves the table unmodified. - BGP OPEN parameter type 255 rejected: RFC 9072 reserves type 255 as the extended-length marker; encoding it as a real parameter produced output that round-tripped to a structurally different message.
- BGP OPEN optional-parameter encoding: Encode the Optional Parameters Length as the total byte length required by RFC 4271 instead of the number of parameters. OPEN messages now also use the extended length format from RFC 9072 when requested or required.
- Historical Quagga state changes: Parse BGP4MP state-change records containing Quagga's
Clearing(7) andDeleted(8) FSM states instead of logging an error and dropping the MRT record. - CLI broken-pipe exit status (#325): the CLI now exits 0 when its stdout consumer closes the pipe early (e.g.
bgpkit-parser updates.gz | head), matching Unix convention; previous releases exited 1. Other write errors still exit 1.
Contributors
- @ties — fallible encoding and MRT error-handling overhaul (#312, #315), early RIPE RIS MRT support (#316), historical Quagga BGP states (#317), recovering parser (#325), ROUTE-REFRESH parsing (#326)
- @downwithbgp — RFC 10005 Link Bandwidth Extended Community support (#319), RFC 5543 Traffic Engineering attribute support (#322)
- @digizeph — unified MRT/text-dump parser API (#321), resumable HTTP parser (#323), diagnostic MRT iterator (#324)