Skip to content

v0.16.0

Latest

Choose a tag to compare

@github-actions github-actions released this 08 Apr 05:04
· 1 commit to main since this release
c964c69

Breaking changes

  • BgpOpenMessage::sender_ip renamed to bgp_identifier: The field type remains Ipv4Addr (aliased as BgpIdentifier), 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! with debug_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 u16 casts 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 wasm feature flag compiles the BMP/BGP/MRT parsing core to WebAssembly for use in JavaScript environments. Published as @bgpkit/parser on 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 into BgpElem[]
      • parseMrtRecords(data): streaming generator that yields MRT records one at a time from a decompressed buffer
      • parseMrtRecord(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 file
      • openMrt(pathOrUrl): fetch and decompress MRT data into a Buffer
    • Supports gzip (RIPE RIS) and bzip2 (RouteViews, requires optional seek-bzip dependency) 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
  • BgpElem::peer_bgp_id field: BgpElem now exposes an optional peer_bgp_id: Option<BgpIdentifier> containing the peer's BGP Identifier (Router ID) when available. Populated from the PEER_INDEX_TABLE in TableDumpV2/RIB records; None for BGP4MP records.

  • with_filters and add_filters methods: Added new methods to BgpkitParser for passing pre-built Vec<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 needed
    • add_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_filter method 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 Elementor
    • Elementor::record_to_elems_iter(&self, record) returns a lazy iterator without requiring &mut self
    • BgpkitParser::into_elementor_and_raw_record_iter() returns (Elementor, iterator) with PeerIndexTable pre-extracted
    • BgpkitParser::into_elementor_and_record_iter() returns (Elementor, iterator) with PeerIndexTable pre-extracted
    • New RecordElemIter and BgpUpdateElemIter types for lazy element iteration
    • New ElemError type 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_prefix function parses from a byte slice without consuming, returning (prefix, bytes_consumed). The read_nlri_prefix method is now a thin wrapper that calls try_parse_prefix and advances the cursor. This eliminates the expensive input.clone() operation while maintaining correct Add-Path heuristic retry behavior.
    • Attribute vector pre-allocation: Estimate capacity from data size (remaining / 3 bytes 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 with read_nlri_prefix.
  • Use zerocopy for MRT header parsing

    • Replaced manual byte parsing with zerocopy's FromBytes trait for RawMrtCommonHeader and RawMrtEtCommonHeader
    • 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 IntoBytes trait for efficient byte conversion
  • Use zerocopy for BGP OPEN message and capability parsing

    • RawBgpOpenHeader (10 bytes), RawMultiprotocolExtensions (4 bytes), and RawFourOctetAs (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: true to ensure Codecov only posts coverage reports when a valid base commit coverage exists, preventing comparisons against outdated baselines.

Bug fixes

  • WASM only_to_customer serialization: Added test to verify that messages without the OTC (Only To Customer) attribute correctly serialize only_to_customer as null (not 0) 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_customer value 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 have only_to_customer: null.
  • Fix Attributes::from_iter for AttributeValue to apply default BGP attribute flags instead of empty flags
    • Prevents malformed encoding for well-known mandatory attributes such as ORIGIN and AS_PATH
  • Preserve add-path path_id when encoding TABLE_DUMP_V2 RIB entries and emit add-path RIB subtypes from MrtRibEncoder when 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_iter for both updates and RIB dumps