bgpkit-parser 0.18.0 Release

· Mingwei Zhang
parser release

bgpkit-parser 0.18.0 preserves more of the original BGP wire data. Earlier versions parsed many common attributes into typed Rust structures, but element conversion could drop known attributes that did not yet have a semantic parser. That worked for many analysis workflows, but it was not enough for users who need to inspect, serialize, or re-encode less common BGP path attributes.

This release changes that behavior: the parser now retains known-but-unsupported, malformed, deprecated, and unknown BGP path attributes in AttrRaw-backed variants instead of silently dropping them.

Install

cargo add [email protected]

For the WebAssembly package:

npm install @bgpkit/[email protected]

RIS Live raw message parsing

RIS Live’s JSON messages expose a convenient projection of UPDATE data, but that projection does not include every BGP path attribute. For example, attributes such as Only to Customer (OTC, code 35), BGP Prefix-SID, BFD Discriminator, and other less common path attributes may appear in the raw UPDATE while remaining absent from the projected JSON fields. Version 0.18.0 adds helpers that parse RIS Live messages containing the original raw BGP UPDATE bytes.

To request raw BGP messages from RIS Live, set socketOptions.includeRaw in the subscription message. The crate now re-exports RisSubscribe, RisSubscribeType, and RisLiveClientMessage from the crate root, so examples and downstream applications can build subscription messages directly.

use bgpkit_parser::{RisLiveClientMessage, RisSubscribe};

let subscribe = RisSubscribe::new()
    .with_host("rrc00")
    .with_include_raw(true);

let msg = RisLiveClientMessage::RisSubscribe(subscribe).to_json_string().unwrap();
// send `msg` over a WebSocket connection to RIS Live

When a RIS Live message arrives, parse the full ris_message envelope with the raw parser:

use bgpkit_parser::parse_ris_live_message_raw;

let elems = parse_ris_live_message_raw(message_text).expect("parse RIS Live message");
for elem in elems {
    println!("{} {} {:?}", elem.elem_type, elem.prefix, elem.as_path);
}

Users who prefer RIS Live’s JSON-projected fields can call parse_ris_live_message_json() for the explicit JSON-path parser, or keep using the older parse_ris_live_message() function for the same JSON-projected path.

Raw BGP attribute retention

The main parser now keeps raw bytes for attributes it cannot or should not decode semantically. The new AttributeValue::Raw(AttrRaw) variant stores the wire attribute code and value bytes for known-but-unsupported attributes:

use bgpkit_parser::models::bgp::attributes::AttributeValue;

for attr in attributes.inner.iter() {
    match attr {
        AttributeValue::Raw(raw) => {
            println!("raw attribute code={} len={}", raw.code, raw.bytes.len());
        }
        other => {
            println!("typed attribute code={}", other.attr_code());
        }
    }
}

This matters for round-trip workflows. If a route contains a known attribute that bgpkit-parser does not yet decode into a typed model, 0.18.0 preserves and re-encodes the original attribute bytes.

Malformed attributes that target typed parsers now fall back to Raw after recording a validation warning, rather than disappearing from the parsed attribute list.

Deprecated attribute code handling

The IANA registry lists attribute code 13 as deprecated: RCID_PATH / CLUSTER_ID. Version 0.18.0 removes AttrType::CLUSTER_ID and retains code 13 as deprecated raw data instead.

If downstream code exhaustively matches AttrType or AttributeValue, this is one of the release’s breaking changes. Use AttributeValue::attr_code() when the raw code point matters, and AttrRaw::attr_type() when you want to map the raw wire code back to an AttrType value.

New typed BGP path attribute parsers

This release adds typed parsers and round-trip encoding support for several RFC-defined path attributes:

  • RFC 7311 — AIGP, attribute code 26
  • RFC 9015 — SFP, attribute code 37
  • RFC 9026 — BFD Discriminator, attribute code 38
  • RFC 8669 — BGP Prefix-SID, attribute code 40
  • RFC 9793 — BIER, attribute code 41

Each parser preserves unknown TLVs, so applications can inspect known fields without losing the rest of the attribute payload.

For example, AIGP exposes an accumulated_metric() helper:

use bgpkit_parser::models::bgp::attributes::AttributeValue;

for attr in attributes.inner.iter() {
    if let AttributeValue::Aigp(aigp) = attr {
        if let Some(metric) = aigp.accumulated_metric() {
            println!("AIGP accumulated metric: {metric}");
        }
    }
}

API changes to note

The main breaking changes affect raw attribute representation and exhaustive matches:

  • AttrRaw now stores code: u8 instead of attr_type: AttrType.
  • AttrRaw.bytes now uses bytes::Bytes instead of Vec<u8>.
  • AigpTlv.value now uses Bytes.
  • AttributeValue has new variants: Raw, BfdDiscriminator, BgpPrefixSid, Bier, and Sfp.
  • The release removes AttrType::CLUSTER_ID.

For most users who iterate over BgpElem, the visible behavior should stay the same except that the parser preserves more attributes internally. Code that destructures attributes or performs exhaustive matching will need updates.

WebAssembly package

The @bgpkit/parser npm package also ships 0.18.0. The WASM package continues to expose parsers for BGP UPDATE, BMP/OpenBMP, and MRT data in Node.js, bundler, browser, and Worker environments.

import { parseBgpUpdate } from '@bgpkit/parser';

const elems = parseBgpUpdate(updateBytes);
for (const elem of elems) {
  console.log(elem.type, elem.prefix, elem.as_path);
}

The Rust crate includes RIS Live parsing in this release. We track WASM-level RIS Live parser exports and WebSocket helpers separately.