Breaking changes
BgpOpenMessage::sender_iprenamed tobgp_identifier: The field type remainsIpv4Addr(aliased asBgpIdentifier), but the name now correctly reflects RFC 4271 terminology — this is the BGP Identifier, not necessarily the sender's IP address. (thanks @ties for the contribution)
Security improvements
- AS_PATH segment count validation: Added bounds check to prevent buffer over-read when parsing AS_PATH segments. Validates that
count * asn_len.bytes()does not exceed remaining buffer size (CWE-126). - BGP message length underflow protection: Added saturating arithmetic to prevent integer underflow when calculating message length (CWE-191).
- NLRI prefix length validation: Enforce maximum prefix lengths (32 bits for IPv4, 128 bits for IPv6) immediately after reading length byte (CWE-20).
- BGP marker RFC 4271 compliance: Fixed marker encoding to use 16 bytes of 0xFF as required by RFC 4271. Added validation on parse with warning for non-compliant markers.
- Communities divisibility validation: Validate that Communities (4 bytes), Extended Communities (8 bytes), and Large Communities (12 bytes) attribute lengths are properly divisible by their respective sizes.
- FlowSpec traffic rate validation: Added NaN and infinity checks for FlowSpec Traffic Rate extended communities to prevent undefined behavior in downstream calculations.
- FlowSpec DSCP byte offset: Corrected Traffic Marking extended community parsing per RFC 5575 (DSCP at proper byte offset).
- Production code safety: Replaced
assert_eq!withdebug_assert_eq!in production parsing code to prevent panics on malformed input. - Timestamp overflow handling: Fixed timestamp truncation for values beyond 2106 (u32::MAX) using proper bounds checking.
- Encoding truncation checks: Added overflow warnings for
as u8/as u16casts in encoding functions. - IPv4 enforcement for AGGREGATOR/ORIGINATOR_ID: Encoders now reject IPv6 addresses for these attributes (BGP specifications require IPv4 only).
New features
-
WebAssembly (WASM) support (experimental): New
wasmfeature flag compiles the BMP/BGP/MRT parsing core to WebAssembly for use in JavaScript environments. Published as@bgpkit/parseron npm with support for Node.js (CommonJS), bundlers (ES modules), and browsers/workers (ES modules with manual init). This feature is experimental and the API may change in future releases.- Core parsing functions (all platforms):
parseOpenBmpMessage(data): parses OpenBMP-wrapped BMP frames (e.g. RouteViews Kafka stream)parseBmpMessage(data, timestamp): parses raw BMP frames (without an OpenBMP header)parseBgpUpdate(data): parses a single BGP UPDATE message intoBgpElem[]parseMrtRecords(data): streaming generator that yields MRT records one at a time from a decompressed bufferparseMrtRecord(data)/resetMrtParser(): low-level MRT record parsing
- Node.js I/O helpers:
streamMrtFrom(pathOrUrl): fetch, decompress (gz/bz2), and stream-parse MRT records from a URL or local fileopenMrt(pathOrUrl): fetch and decompress MRT data into aBuffer
- Supports gzip (RIPE RIS) and bzip2 (RouteViews, requires optional
seek-bzipdependency) compression - Multi-target build script (
src/wasm/build.sh) produces nodejs, bundler, and web targets in a single npm package - JS wrapper handles JSON deserialization; TypeScript types included
- Node.js examples in
examples/wasm/: Kafka OpenBMP stream consumer and MRT file parser - Browser-based MRT explorer demo: mrt-explorer.labs.bgpkit.com
- Core parsing functions (all platforms):
-
BgpElem::peer_bgp_idfield:BgpElemnow exposes an optionalpeer_bgp_id: Option<BgpIdentifier>containing the peer's BGP Identifier (Router ID) when available. Populated from the PEER_INDEX_TABLE in TableDumpV2/RIB records;Nonefor BGP4MP records. -
with_filtersandadd_filtersmethods: Added new methods toBgpkitParserfor passing pre-builtVec<Filter>directly, addressing issue #271. (thanks @JustinLoye for the feature suggestion!)with_filters(filters: &[Filter])- replaces all existing filters with the provided slice; clones internally so no manual clone neededadd_filters(filters: &[Filter])- extends existing filters with the provided slice- Both methods enable building filter specifications independently and reusing them across multiple parsers without string parsing overhead
- Added rust documentation to
add_filtermethod with complete list of available filter types
Example:
use bgpkit_parser::BgpkitParser; use bgpkit_parser::parser::Filter; let filters = vec![ Filter::new("peer_ip", "185.1.8.65").unwrap(), Filter::new("type", "w").unwrap(), ]; // Reuse across multiple parsers let parser1 = BgpkitParser::new(url1).unwrap().with_filters(&filters); let parser2 = BgpkitParser::new(url2).unwrap().with_filters(&filters);
-
Immutable Elementor API: New methods enable parallel processing of MRT records
Elementor::with_peer_table(peer_table)creates a pre-initialized ElementorElementor::record_to_elems_iter(&self, record)returns a lazy iterator without requiring&mut selfBgpkitParser::into_elementor_and_raw_record_iter()returns(Elementor, iterator)with PeerIndexTable pre-extractedBgpkitParser::into_elementor_and_record_iter()returns(Elementor, iterator)with PeerIndexTable pre-extracted- New
RecordElemIterandBgpUpdateElemItertypes for lazy element iteration - New
ElemErrortype for explicit error handling - Parallel processing example demonstrating multi-threaded parsing with significant speedup
Performance improvements
-
Memory usage reduction (61% improvement): Optimized memory allocation patterns resulting in significant peak memory reduction:
- NLRI Add-Path clone-free parsing: Replaced input buffer cloning with speculative byte-slice parsing. The new
try_parse_prefixfunction parses from a byte slice without consuming, returning(prefix, bytes_consumed). Theread_nlri_prefixmethod is now a thin wrapper that callstry_parse_prefixand advances the cursor. This eliminates the expensiveinput.clone()operation while maintaining correct Add-Path heuristic retry behavior. - Attribute vector pre-allocation: Estimate capacity from data size (
remaining / 3bytes per attribute) instead of fixed 20, reducing reallocations for BGP messages with many attributes. - RIS Live vector pre-allocation: Calculate capacity from announcements + withdrawals counts before allocation, preventing growth reallocations.
- Measured improvement: Peak memory reduced from 2,037 MB to 789 MB (61.3% reduction) when parsing full BGP table dump (RouteViews LINX RIB, 151MB compressed).
- Code quality: Single implementation of prefix parsing logic in
try_parse_prefix, eliminating duplication withread_nlri_prefix.
- NLRI Add-Path clone-free parsing: Replaced input buffer cloning with speculative byte-slice parsing. The new
-
Use zerocopy for MRT header parsing
- Replaced manual byte parsing with zerocopy's
FromBytestrait forRawMrtCommonHeaderandRawMrtEtCommonHeader - Reduces bounds checking overhead by using compile-time verified struct layouts
- Added compile-time assertions to ensure header sizes match wire format (12 bytes standard, 16 bytes ET)
- Encoding now uses zerocopy's
IntoBytestrait for efficient byte conversion
- Replaced manual byte parsing with zerocopy's
-
Use zerocopy for BGP OPEN message and capability parsing
RawBgpOpenHeader(10 bytes),RawMultiprotocolExtensions(4 bytes), andRawFourOctetAs(4 bytes) use zerocopy struct layouts- Replaces sequential cursor reads with single bounds-checked struct references
Code improvements
- Enhanced warning messages: Added context to 14 warning messages across BGP, BMP, and MRT parsers to help identify which parsing stage encountered an issue. Also fixed typo in NLRI warning ("NRLI" → "NLRI"). (thanks @ties for the contribution)
- Codecov configuration: Added
require_base: trueto ensure Codecov only posts coverage reports when a valid base commit coverage exists, preventing comparisons against outdated baselines.
Bug fixes
- WASM
only_to_customerserialization: Added test to verify that messages without the OTC (Only To Customer) attribute correctly serializeonly_to_customerasnull(not0) in JSON output. This ensures JavaScript consumers can properly distinguish between "no OTC attribute" (null) and "OTC with AS 0" (0). - OTC attribute on withdrawal messages: Withdrawal elements no longer inherit the
only_to_customervalue from their associated UPDATE message. Since the OTC attribute (RFC 9234) is used for route leak detection on route advertisements, it is not semantically meaningful for withdrawals. Withdrawal elements now correctly haveonly_to_customer: null. - Fix
Attributes::from_iterforAttributeValueto apply default BGP attribute flags instead of empty flags- Prevents malformed encoding for well-known mandatory attributes such as
ORIGINandAS_PATH
- Prevents malformed encoding for well-known mandatory attributes such as
- Preserve add-path
path_idwhen encoding TABLE_DUMP_V2 RIB entries and emit add-path RIB subtypes fromMrtRibEncoderwhen entries carry path IDs - Encode BGP4MP ASNs using the subtype-selected ASN width and always refresh MRT header lengths during record encoding
Testing
- Added benchmarks for
into_raw_record_iterfor both updates and RIB dumps