Skip to main content

bgpkit_parser/
lib.rs

1/*!
2BGPKIT Parser aims to provide the most ergonomic MRT/BGP/BMP message parsing Rust API.
3
4BGPKIT Parser has the following features:
5- **performant**: comparable to C-based implementations like `bgpdump` or `bgpreader`.
6- **actively maintained**: we consistently introduce feature updates and bug fixes, and support most of the relevant BGP RFCs.
7- **ergonomic API**: a three-line for loop can already get you started.
8- **battery-included**: ready to handle remote or local, bzip2 or gz data files out of the box
9
10# Getting Started
11
12Add `bgpkit-parser` to your `Cargo.toml`.
13
14Parse a BGP MRT file in three lines:
15
16```no_run
17use bgpkit_parser::BgpkitParser;
18
19for elem in BgpkitParser::new("http://archive.routeviews.org/route-views4/bgpdata/2022.01/UPDATES/updates.20220101.0000.bz2").unwrap() {
20    println!("{}", elem);
21}
22```
23
24# Examples
25
26The examples below are organized by complexity. For complete runnable examples, check out the [examples folder](https://github.com/bgpkit/bgpkit-parser/tree/main/examples).
27
28## Basic Examples
29
30### Parsing a Single MRT File
31
32Let's say we want to print out all the BGP announcements/withdrawal from a single MRT file, either located remotely or locally.
33Here is an example that does so.
34
35```no_run
36use bgpkit_parser::BgpkitParser;
37let parser = BgpkitParser::new("http://archive.routeviews.org/bgpdata/2021.10/UPDATES/updates.20211001.0000.bz2").unwrap();
38for elem in parser {
39    println!("{}", elem)
40}
41```
42
43Yes, it is this simple!
44
45### Counting BGP Messages
46
47You can use iterator methods for quick analysis. For example, counting the number of announcements/withdrawals in a file:
48
49```no_run
50use bgpkit_parser::BgpkitParser;
51let url = "http://archive.routeviews.org/bgpdata/2021.10/UPDATES/updates.20211001.0000.bz2";
52let count = BgpkitParser::new(url).unwrap().into_iter().count();
53println!("total: {}", count);
54```
55
56Output:
57```text
58total: 255849
59```
60
61## Intermediate Examples
62
63### Filtering BGP Messages
64
65BGPKIT Parser has a built-in [Filter] mechanism to efficiently filter messages. Add filters when creating the parser to only process matching [BgpElem]s.
66
67**Available filter types**: See the [Filter] enum documentation for all options.
68
69```no_run
70use bgpkit_parser::BgpkitParser;
71
72/// Filter by IP prefix
73let parser = BgpkitParser::new("http://archive.routeviews.org/bgpdata/2021.10/UPDATES/updates.20211001.0000.bz2").unwrap()
74    .add_filter("prefix", "211.98.251.0/24").unwrap();
75
76for elem in parser {
77    println!("{}", elem);
78}
79```
80
81**Common filters**:
82- `prefix`: Match a specific IP prefix
83- `origin_asn`: Match origin AS number
84- `peer_asn`: Match peer AS number
85- `peer_ip`: Match peer IP address
86- `type`: Filter by announcement (`a`) or withdrawal (`w`)
87- `as_path`: Match AS path with regex
88- `community`: Match BGP community with regex
89- `otc`: Match only-to-customer ASN (RFC 9234)
90- `next_hop`: Match next hop IP address
91- `origin`: Match origin attribute (`igp`, `egp`, `incomplete`)
92- `local_pref`: Match local preference value
93- `med`: Match multi-exit discriminator value
94- `atomic`: Match atomic aggregate flag (`true`/`false`)
95
96**Negative filters**: Most filters support negation by prefixing the filter value with `!`. For example:
97- `origin_asn = !13335`: Match elements where origin AS is NOT 13335
98- `prefix = !211.98.251.0/24`: Match elements where prefix is NOT 211.98.251.0/24
99- `peer_ip = !192.0.2.1`: Match elements where peer IP is NOT 192.0.2.1
100
101**Note**: Timestamp filters (`ts_start`, `ts_end`) do not support negation.
102
103**Presence filters**: Optional fields support `*` as a wildcard to check whether a field is present or absent. For example:
104- `otc = *`: Match elements that carry an OTC value
105- `otc = !*`: Match elements without an OTC value
106- `next_hop = *`: Match elements that have a next hop
107
108```no_run
109use bgpkit_parser::BgpkitParser;
110
111// Filter out all elements from AS 13335 (get everything EXCEPT AS 13335)
112let parser = BgpkitParser::new("http://archive.routeviews.org/bgpdata/2021.10/UPDATES/updates.20211001.0000.bz2").unwrap()
113    .add_filter("origin_asn", "!13335").unwrap();
114
115for elem in parser {
116    println!("{}", elem);
117}
118```
119
120### Parsing Multiple MRT Files with BGPKIT Broker
121
122[BGPKIT Broker][broker-repo] library provides search API for all RouteViews and RIPE RIS MRT data files. Using the
123broker's Rust API ([`bgpkit-broker`][broker-crates-io]), we can easily compile a list of MRT files that we are interested
124in for any time period and any data type (`update` or `rib`). This allows users to gather information without needing to
125know about the locations of specific data files.
126
127[broker-repo]: https://github.com/bgpkit/bgpkit-broker
128[broker-crates-io]: https://crates.io/crates/bgpkit-broker
129
130The example below shows a relatively more interesting example that does the following:
131- find all BGP archive data created on time 1634693400
132- filter to only BGP updates files
133- find all announcements originated from AS13335
134- print out the total count of the announcements
135
136```no_run
137use bgpkit_parser::{BgpkitParser, BgpElem};
138
139let broker = bgpkit_broker::BgpkitBroker::new()
140    .ts_start("1634693400")
141    .ts_end("1634693400")
142    .page(1);
143
144for item in broker.into_iter().take(2) {
145    log::info!("downloading updates file: {}", item.url);
146    let parser = BgpkitParser::new(item.url.as_str()).unwrap();
147
148    log::info!("parsing updates file");
149    // iterating through the parser. the iterator returns `BgpElem` one at a time.
150    let elems = parser
151        .into_elem_iter()
152        .filter_map(|elem| {
153            if let Some(origins) = &elem.origin_asns {
154                if origins.contains(&13335.into()) {
155                    Some(elem)
156                } else {
157                    None
158                }
159            } else {
160                None
161            }
162        })
163        .collect::<Vec<BgpElem>>();
164    log::info!("{} elems matches", elems.len());
165}
166```
167
168### Error Handling
169
170BGPKIT Parser returns `Result` types for operations that may fail. Here are common scenarios and how to handle them:
171
172**Handling Parser Creation Errors**
173
174```no_run
175use bgpkit_parser::BgpkitParser;
176
177// The URL might be invalid or unreachable
178match BgpkitParser::new("http://example.com/data.mrt.bz2") {
179    Ok(parser) => {
180        for elem in parser {
181            println!("{}", elem);
182        }
183    }
184    Err(e) => {
185        eprintln!("Failed to create parser: {}", e);
186        // Common causes:
187        // - Invalid URL or file path
188        // - Network connection issues
189        // - Unsupported compression format
190    }
191}
192```
193
194**Handling Filter Errors**
195
196```no_run
197use bgpkit_parser::BgpkitParser;
198
199let mut parser = BgpkitParser::new("http://example.com/data.mrt.bz2").unwrap();
200
201// Filter addition can fail with invalid input
202match parser.add_filter("prefix", "invalid-prefix") {
203    Ok(_) => println!("Filter added successfully"),
204    Err(e) => {
205        eprintln!("Invalid filter: {}", e);
206        // Common causes:
207        // - Invalid IP prefix format
208        // - Invalid AS number
209        // - Unknown filter type
210    }
211}
212```
213
214**Robust Production Code**
215
216```no_run
217use bgpkit_parser::BgpkitParser;
218
219fn process_mrt_file(url: &str) -> Result<usize, Box<dyn std::error::Error>> {
220    let parser = BgpkitParser::new(url)?
221        .add_filter("origin_asn", "13335")?;
222
223    let mut count = 0;
224    for elem in parser {
225        // Process element
226        count += 1;
227    }
228
229    Ok(count)
230}
231
232// Usage
233match process_mrt_file("http://example.com/updates.bz2") {
234    Ok(count) => println!("Processed {} elements", count),
235    Err(e) => eprintln!("Error: {}", e),
236}
237```
238
239**Recovering After Damaged MRT Framing**
240
241Recovery is opt-in and never reconstructs a damaged record. It reports the skipped decompressed
242byte range before resuming at a conservatively validated record chain.
243
244```no_run
245use bgpkit_parser::{BgpkitParser, RecoveryConfig, RecoveryEvent};
246
247fn recover(path: &str) -> Result<(), Box<dyn std::error::Error>> {
248    let parser = BgpkitParser::new(path)?;
249    for event in parser.into_recovering_record_iter(RecoveryConfig::default()) {
250        match event? {
251            RecoveryEvent::Item(record) => println!("{}", record),
252            RecoveryEvent::Gap(gap) => eprintln!(
253                "skipped bytes {}..{}: {}",
254                gap.start_offset, gap.end_offset, gap.cause
255            ),
256        }
257    }
258    Ok(())
259}
260```
261
262## Advanced Examples
263
264### Parsing Real-time Data Streams
265
266BGPKIT Parser provides parsing for real-time data streams, including [RIS-Live][ris-live-url]
267and [BMP][bmp-rfc]/[OpenBMP][openbmp-url] messages.
268
269**Parsing Messages From RIS-Live**
270
271Here is an example of handling RIS-Live message streams. After connecting to the websocket server,
272we need to subscribe to a specific data stream. In this example, we subscribe to the data stream
273from one collector (`rrc21`). We can then loop and read messages from the websocket.
274
275RIS Live's JSON fields expose only a subset of BGP attributes. To parse the original BGP wire
276message instead, request `includeRaw` and use `parse_ris_live_message_raw`. The older
277`parse_ris_live_message` function remains available for parsing RIS Live's JSON-projected fields.
278
279```no_run
280# #[cfg(feature = "rislive")]
281# mod ris_live_example {
282use bgpkit_parser::{parse_ris_live_message_raw, RisLiveClientMessage, RisSubscribe};
283use tungstenite::{connect, Message};
284
285const RIS_LIVE_URL: &str = "ws://ris-live.ripe.net/v1/ws/?client=rust-bgpkit-parser";
286
287/// This is an example of subscribing to RIS-Live's streaming data from one host (`rrc21`).
288///
289/// For more RIS-Live details, check out their documentation at https://ris-live.ripe.net/manual/
290fn main() {
291    // connect to RIPE RIS Live websocket server
292    let (mut socket, _response) =
293        connect(RIS_LIVE_URL)
294            .expect("Can't connect to RIS Live websocket server");
295
296    // subscribe to messages from one collector and request hex-encoded raw BGP messages
297    let msg = RisSubscribe::new().host("rrc21").include_raw(true).to_json_string();
298    socket.send(Message::Text(msg.into())).unwrap();
299
300    loop {
301        let msg = socket.read().expect("Error reading message").to_string();
302        if let Ok(elems) = parse_ris_live_message_raw(msg.as_str()) {
303            for elem in elems {
304                println!("{}", elem);
305            }
306        }
307    }
308}
309# }
310```
311
312**Parsing OpenBMP Messages From RouteViews Kafka Stream**
313
314[RouteViews](http://www.routeviews.org/routeviews/) provides a real-time Kafka stream of the OpenBMP
315data received from their collectors. Below is a partial example of how we handle the raw bytes
316received from the Kafka stream. For full examples, check out the [examples folder on GitHub](https://github.com/bgpkit/bgpkit-parser/tree/main/examples).
317
318```rust,no_run
319# use log::{info, error};
320# use bytes::Bytes;
321# struct KafkaMessage { value: Vec<u8> }
322# let m = KafkaMessage { value: vec![] };
323use bgpkit_parser::parser::bmp::messages::*;
324use bgpkit_parser::parser::utils::*;
325use bgpkit_parser::{Elementor, parse_openbmp_header, parse_bmp_msg};
326
327let bytes = &m.value;
328let mut data = Bytes::from(bytes.clone());
329let header = parse_openbmp_header(&mut data).unwrap();
330let bmp_msg = parse_bmp_msg(&mut data);
331match bmp_msg {
332    Ok(msg) => {
333        let timestamp = header.timestamp;
334        let per_peer_header = msg.per_peer_header.unwrap();
335        match msg.message_body {
336            BmpMessageBody::RouteMonitoring(m) => {
337                for elem in Elementor::bgp_to_elems(
338                    m.bgp_message,
339                    timestamp,
340                    &per_peer_header.peer_ip,
341                    &per_peer_header.peer_asn
342                )
343                {
344                    info!("{}", elem);
345                }
346            }
347            _ => {}
348        }
349    }
350    Err(_e) => {
351        let hex = hex::encode(bytes);
352        error!("{}", hex);
353    }
354}
355```
356
357[ris-live-url]: https://ris-live.ripe.net
358[bmp-rfc]: https://datatracker.ietf.org/doc/html/rfc7854
359[openbmp-url]: https://www.openbmp.org/
360
361### Encoding: Archiving Filtered MRT Records
362
363The example will download one MRT file from RouteViews, filter out all the BGP messages that
364are not originated from AS3356, and write the filtered MRT records to disk. Then it re-parses the
365filtered MRT file and prints out the number of BGP messages.
366
367```no_run
368use bgpkit_parser::Elementor;
369use itertools::Itertools;
370use std::io::Write;
371
372let mut updates_encoder = bgpkit_parser::encoder::MrtUpdatesEncoder::new();
373
374bgpkit_parser::BgpkitParser::new(
375    "http://archive.routeviews.org/bgpdata/2023.10/UPDATES/updates.20231029.2015.bz2",
376).unwrap()
377    .add_filter("origin_asn", "3356").unwrap()
378    .into_iter()
379    .for_each(|elem| {
380        updates_encoder.process_elem(&elem);
381    });
382
383let mut mrt_writer = oneio::get_writer("as3356_mrt.gz").unwrap();
384mrt_writer.write_all(updates_encoder.export_bytes().unwrap().as_ref()).unwrap();
385drop(mrt_writer);
386```
387
388# FAQ & Troubleshooting
389
390## Common Issues
391
392### Parser creation fails with "unsupported compression"
393**Problem**: The file uses an unsupported compression format.
394
395**Solution**: BGPKIT Parser natively supports `.bz2` and `.gz` compression. For other formats, decompress the file first or use the [`oneio`](https://crates.io/crates/oneio) crate which supports additional formats.
396
397### Out of memory when parsing large files
398**Problem**: Collecting all elements into a vector exhausts available memory.
399
400**Solution**: Use streaming iteration instead of collecting:
401```rust,ignore
402// ❌ Don't do this for large files
403let all_elems: Vec<_> = parser.into_iter().collect();
404
405// ✅ Process iteratively
406for elem in parser {
407    // Process one element at a time
408    process(elem);
409}
410```
411
412### Slow performance on network files
413**Problem**: Remote file parsing is slower than expected.
414
415**Solution**:
416- Use the `--cache-dir` option in CLI to cache downloaded files
417- In library code, download the file first with appropriate buffering
418- Consider processing files in parallel if dealing with multiple files
419
420### Missing or incomplete BGP attributes
421**Problem**: Some [BgpElem] fields are `None` when you expect values.
422
423**Solution**: Not all BGP messages contain all attributes. Check the MRT format and BGP message type:
424- Withdrawals typically don't have AS paths or communities
425- Some collectors may not export certain attributes
426- Use pattern matching to handle `Option` types properly
427
428## Performance Tips
429
430### Use filters early
431Apply filters during parser creation to avoid processing unwanted data:
432```rust,ignore
433// ✅ Efficient - filters during parsing
434let parser = BgpkitParser::new(url)?
435    .add_filter("prefix", "1.1.1.0/24")?;
436
437// ❌ Less efficient - processes everything first
438let filtered: Vec<_> = BgpkitParser::new(url)?
439    .into_iter()
440    .filter(|e| e.prefix.to_string() == "1.1.1.0/24")
441    .collect();
442```
443
444### Process multiple files in parallel
445For bulk processing, use parallel iterators:
446```rust,ignore
447use rayon::prelude::*;
448
449let files = vec!["file1.mrt.bz2", "file2.mrt.bz2", "file3.mrt.bz2"];
450files.par_iter().for_each(|file| {
451    let parser = BgpkitParser::new(file).unwrap();
452    // Process each file in parallel
453});
454```
455
456### Choose the right data structure
457- Use [MrtRecord] iteration for minimal memory overhead
458- Use [MrtUpdate] for efficient batch processing without per-prefix attribute duplication
459- Use [BgpElem] for easier per-prefix analysis
460- See [Data Representation](#data-representation) for detailed comparison
461
462# Command Line Tool
463
464`bgpkit-parser` is bundled with a utility commandline tool `bgpkit-parser-cli`.
465
466## Installation
467
468### Install compiled binaries
469
470You can install the compiled `bgpkit-parser` CLI binaries with the following methods:
471- **Homebrew** (macOS): `brew install bgpkit/tap/bgpkit-parser`
472- [**Cargo binstall**](https://github.com/cargo-bins/cargo-binstall): `cargo binstall bgpkit-parser`
473
474### From source
475
476You can install the tool by running
477```bash
478cargo install bgpkit-parser --features cli
479```
480or checkout this repository and run
481```bash
482cargo install --path . --features cli
483```
484
485## Usage
486
487Run `bgpkit-parser --help` to see the full list of options.
488
489```text
490MRT/BGP/BMP data processing library
491
492Usage: bgpkit-parser [OPTIONS] <FILE>
493
494Arguments:
495  <FILE>  File path to a MRT file, local or remote
496
497Options:
498  -c, --cache-dir <CACHE_DIR>    Set the cache directory for caching remote files. Default behavior does not enable caching
499      --json                     Output as JSON objects
500      --psv                      Output as full PSV entries with header
501      --pretty                   Pretty-print JSON output
502  -e, --elems-count              Count BGP elems
503  -r, --records-count            Count MRT records
504      --recover                  Recover after damaged MRT framing and report skipped byte ranges on stderr
505  -o, --origin-asn <ORIGIN_ASN>  Filter by origin AS Number
506  -f, --filter <FILTERS>         Generic filter expression (key=value or key!=value)
507  -p, --prefix <PREFIX>          Filter by network prefix
508  -4, --ipv4-only                Filter by IPv4 only
509  -6, --ipv6-only                Filter by IPv6 only
510  -s, --include-super            Include super-prefix when filtering
511  -S, --include-sub              Include sub-prefix when filtering
512  -j, --peer-ip <PEER_IP>        Filter by peer IP address
513  -J, --peer-asn <PEER_ASN>      Filter by peer ASN
514  -m, --elem-type <ELEM_TYPE>    Filter by elem type: announce (a) or withdraw (w)
515  -t, --start-ts <START_TS>      Filter by start unix timestamp inclusive
516  -T, --end-ts <END_TS>          Filter by end unix timestamp inclusive
517  -a, --as-path <AS_PATH>        Filter by AS path regex string
518  -h, --help                     Print help
519  -V, --version                  Print version
520
521```
522
523## Common CLI Examples
524
525### Basic usage - Print all BGP messages
526```bash
527bgpkit-parser http://archive.routeviews.org/bgpdata/2021.10/UPDATES/updates.20211001.0000.bz2
528```
529
530### Filter by origin AS
531```bash
532bgpkit-parser -o 13335 updates.20211001.0000.bz2
533```
534
535### Filter by prefix
536```bash
537bgpkit-parser -p 1.1.1.0/24 updates.20211001.0000.bz2
538```
539
540### Output as JSON
541```bash
542bgpkit-parser --json updates.20211001.0000.bz2 > output.json
543```
544
545### Count elements efficiently
546```bash
547bgpkit-parser -e updates.20211001.0000.bz2
548```
549
550### Recover records after damaged framing
551```bash
552bgpkit-parser --recover -e damaged-updates.gz
553```
554
555### Cache remote files for faster repeated access
556```bash
557bgpkit-parser -c ~/.bgpkit-cache http://example.com/updates.mrt.bz2
558```
559
560### Combine filters
561```bash
562# IPv4 announcements from AS13335
563bgpkit-parser -o 13335 -m a -4 updates.bz2
564```
565
566### Negative filters (exclude matching elements)
567```bash
568# Exclude elements from AS 13335
569bgpkit-parser --filter "origin_asn!=13335" updates.bz2
570
571# Exclude a specific peer
572bgpkit-parser --filter "peer_ip!=192.168.1.1" updates.bz2
573
574# Combine positive and negative filters
575bgpkit-parser -o 13335 --filter "peer_asn!=64496" updates.bz2
576```
577
578# Data Representation
579
580BGPKIT Parser provides three ways to access parsed BGP data: [MrtRecord], [MrtUpdate], and [BgpElem]. Choose based on your needs:
581
582```text
583┌──────────────────────────────────────────────┐
584│                  MRT File                    │
585│  (Binary format: bgp4mp, tabledumpv2, etc.)  │
586└──────────────────────┬───────────────────────┘
587588                       ├──> Parser
589590         ┌──────────────┼────────────────┐
591         │              │                │
592         ▼              ▼                ▼
593   [MrtRecord]    [MrtUpdate]      [BgpElem]
594   (Low-level)   (Intermediate)   (High-level)
595         │             │                │
596         └─────────────┴────────────────┘
597598599              Your Analysis Code
600```
601
602## [MrtRecord]: Low-level MRT Representation
603
604[MrtRecord] preserves the complete, unmodified information from the MRT file. Use this when you need:
605- **Raw MRT data access**: Direct access to all MRT fields
606- **Format-specific details**: Peer index tables, geo-location data, etc.
607- **Memory efficiency**: Minimal overhead, compact representation
608- **Re-encoding**: Converting back to MRT format
609
610See the [MrtRecord] documentation for the complete structure definition.
611
612**Key components**:
613- `common_header`: Contains timestamp, record type, and metadata
614- `message`: The actual MRT message (TableDump, TableDumpV2, or Bgp4Mp)
615
616**Iteration**: Use [`BgpkitParser::into_record_iter()`] to iterate over [MrtRecord]s.
617
618## [MrtUpdate]: Intermediate Message-Level Representation
619
620[MrtUpdate] provides access to BGP announcements without expanding them into individual per-prefix elements. This is a middle ground between [MrtRecord] and [BgpElem]. Use this when you need:
621- **Efficient batch processing**: Avoid duplicating attributes across prefixes
622- **Message-level analysis**: Work with UPDATE messages or RIB entries as units
623- **Memory efficiency**: Shared attributes aren't cloned for each prefix
624
625# RPKI RTR Protocol Support
626
627BGPKIT Parser includes support for the RPKI-to-Router (RTR) protocol, enabling downstream
628clients to communicate with RTR cache servers and fetch Route Origin Authorizations (ROAs).
629
630## Overview
631
632The RTR protocol is used to deliver validated RPKI data from a cache server to a router.
633BGPKIT Parser provides:
634- **PDU definitions**: All RTR protocol data structures for both v0 (RFC 6810) and v1 (RFC 8210)
635- **Parsing**: Decode binary RTR PDUs into structured Rust types
636- **Encoding**: Serialize RTR PDUs to binary format for sending to servers
637
638**Note**: This library provides PDU parsing/encoding only. Transport (TCP, SSH, TLS) and
639RPKI validation logic are out of scope and should be handled by downstream clients.
640
641## Quick Example
642
643```rust
644use bgpkit_parser::models::rpki::rtr::*;
645use bgpkit_parser::parser::rpki::rtr::{parse_rtr_pdu, RtrEncode};
646
647// Create a Reset Query to request the full ROA database
648let query = RtrResetQuery::new_v1();
649let bytes = query.encode();
650
651// Parse a PDU from bytes
652let (pdu, consumed) = parse_rtr_pdu(&bytes).unwrap();
653assert!(matches!(pdu, RtrPdu::ResetQuery(_)));
654```
655
656## Available PDU Types
657
658| PDU Type | Direction | Description |
659|----------|-----------|-------------|
660| Serial Notify | Server → Client | Notifies client of new data |
661| Serial Query | Client → Server | Requests incremental update |
662| Reset Query | Client → Server | Requests full database |
663| Cache Response | Server → Client | Begins data transfer |
664| IPv4 Prefix | Server → Client | ROA for IPv4 prefix |
665| IPv6 Prefix | Server → Client | ROA for IPv6 prefix |
666| End of Data | Server → Client | Ends data transfer |
667| Cache Reset | Server → Client | Cannot provide incremental update |
668| Router Key | Server → Client | BGPsec key (v1 only) |
669| Error Report | Bidirectional | Error notification |
670
671## Building an RTR Client
672
673See the [`rtr_client` example](https://github.com/bgpkit/bgpkit-parser/blob/main/examples/rtr_client.rs)
674for a complete working example that:
6751. Connects to an RTR server
6762. Sends a Reset Query
6773. Collects ROAs
6784. Validates a route announcement (1.1.1.0/24 → AS13335)
679
680```bash
681cargo run --example rtr_client -- rtr.rpki.cloudflare.com 8282
682```
683
684**Supported message types** (via enum variants):
685- `Bgp4MpUpdate`: BGP UPDATE messages from UPDATES files
686- `LegacyBgpUpdate`: Deprecated MRT Type 5 BGP UPDATE messages
687- `TableDumpV2Entry`: RIB entries from TableDumpV2 RIB dumps
688- `TableDumpMessage`: Legacy TableDump v1 messages
689
690**Example**:
691```no_run
692use bgpkit_parser::{BgpkitParser, MrtUpdate};
693
694let parser = BgpkitParser::new("updates.mrt.bz2").unwrap();
695for update in parser.into_update_iter() {
696    match update {
697        MrtUpdate::Bgp4MpUpdate(u) => {
698            // One UPDATE message may contain multiple prefixes sharing attributes
699            println!("Peer {} announced {} prefixes",
700                u.peer_ip,
701                u.message.announced_prefixes.len()
702            );
703        }
704        MrtUpdate::LegacyBgpUpdate(u) => {
705            println!("Legacy UPDATE from peer {}", u.peer_ip);
706        }
707        MrtUpdate::TableDumpV2Entry(e) => {
708            // One prefix with multiple RIB entries (one per peer)
709            println!("Prefix {} seen by {} peers",
710                e.prefix,
711                e.rib_entries.len()
712            );
713        }
714        MrtUpdate::TableDumpMessage(m) => {
715            println!("Legacy table dump for {}", m.prefix);
716        }
717    }
718}
719```
720
721**Iteration**: Use [`BgpkitParser::into_update_iter()`] to iterate over [MrtUpdate]s.
722
723## [BgpElem]: High-level Per-Prefix Representation
724
725[BgpElem] provides a simplified, per-prefix view of BGP data. Each [BgpElem] represents a single prefix announcement or withdrawal. Use this when you want:
726- **Simple analysis**: Focus on prefixes without worrying about MRT format details
727- **Format-agnostic processing**: Same structure regardless of MRT format
728- **BGP attributes**: Easy access to AS path, communities, etc.
729
730**Example transformation**:
731```text
732MRT Record with 3 prefixes        →        3 BgpElem objects
733┌────────────────────────┐              ┌──────────────────┐
734│ BGP UPDATE Message     │              │ BgpElem          │
735│ AS Path: 64512 64513   │  ────────>   │ prefix: P1       │
736│ Prefixes:              │              │ as_path: 64512.. │
737│   - P1: 10.0.0.0/24    │              └──────────────────┘
738│   - P2: 10.0.1.0/24    │              ┌──────────────────┐
739│   - P3: 10.0.2.0/24    │  ────────>   │ BgpElem          │
740└────────────────────────┘              │ prefix: P2       │
741                                        │ as_path: 64512.. │
742                                        └──────────────────┘
743                                        ┌──────────────────┐
744                                        │ BgpElem          │
745                            ────────>   │ prefix: P3       │
746                                        │ as_path: 64512.. │
747                                        └──────────────────┘
748```
749
750See the [BgpElem] documentation for the complete structure definition.
751
752**Key fields**:
753- `timestamp`: Unix timestamp of the BGP message
754- `elem_type`: Announcement or withdrawal
755- `peer_ip` / `peer_asn`: The BGP peer information
756- `prefix`: The IP prefix being announced or withdrawn
757- `as_path`: The AS path attribute (if present)
758- `origin_asns`: Origin AS numbers extracted from AS path
759- `communities`: BGP communities (standard, extended, and large)
760- `next_hop`, `local_pref`, `med`: Other BGP attributes
761
762**Iteration**: Use [`BgpkitParser::into_elem_iter()`] or default iteration to iterate over [BgpElem]s.
763
764## Which One Should I Use?
765
766| Use Case | Recommended | Why |
767|----------|-------------|-----|
768| Simple prefix analysis | [BgpElem] | Easy per-prefix access, format-agnostic |
769| High-performance processing | [MrtUpdate] | Avoids attribute duplication overhead |
770| Counting prefixes per UPDATE | [MrtUpdate] | Direct access to message structure |
771| Re-encoding MRT data | [MrtRecord] | Preserves complete MRT structure |
772| MRT format-specific details | [MrtRecord] | Access to peer index tables, geo-location, etc. |
773
774**Memory trade-off**:
775- [BgpElem] duplicates shared attributes (AS path, communities) for each prefix
776- [MrtUpdate] keeps attributes shared within each message/entry
777- [MrtRecord] has minimal overhead but requires more code to extract BGP data
778
779# RFCs Support
780
781BGPKIT Parser implements comprehensive BGP, MRT, BMP, and related protocol standards. All listed RFCs are fully supported.
782
783**Request a feature**: If you need support for a specific RFC not listed here, please [submit an issue on GitHub](https://github.com/bgpkit/bgpkit-parser/issues).
784
785## Core BGP Protocol
786
787**Most commonly used**:
788- [RFC 4271](https://datatracker.ietf.org/doc/html/rfc4271): A Border Gateway Protocol 4 (BGP-4) - Core protocol
789- [RFC 2858](https://datatracker.ietf.org/doc/html/rfc2858): Multiprotocol Extensions for BGP-4 (IPv6 support)
790- [RFC 6793](https://datatracker.ietf.org/doc/html/rfc6793): Four-Octet AS Number Space
791- [RFC 7911](https://datatracker.ietf.org/doc/html/rfc7911): Advertisement of Multiple Paths (ADD-PATH)
792
793**Additional BGP RFCs**:
794- [RFC 2042](https://datatracker.ietf.org/doc/html/rfc2042): Registering New BGP Attribute Types
795- [RFC 2918](https://datatracker.ietf.org/doc/html/rfc2918): Route Refresh Capability for BGP-4
796- [RFC 3392](https://datatracker.ietf.org/doc/html/rfc3392): Capabilities Advertisement with BGP-4
797- [RFC 4724](https://datatracker.ietf.org/doc/html/rfc4724): Graceful Restart Mechanism for BGP
798- [RFC 4456](https://datatracker.ietf.org/doc/html/rfc4456): BGP Route Reflection
799- [RFC 5065](https://datatracker.ietf.org/doc/html/rfc5065): Autonomous System Confederations for BGP
800- [RFC 5492](https://datatracker.ietf.org/doc/html/rfc5492): Capabilities Advertisement with BGP-4
801- [RFC 7606](https://datatracker.ietf.org/doc/html/rfc7606): Revised Error Handling for BGP UPDATE Messages
802- [RFC 8277](https://datatracker.ietf.org/doc/html/rfc8277): Using BGP to Bind MPLS Labels to Address Prefixes (obsoletes RFC 3107)
803- [RFC 8654](https://datatracker.ietf.org/doc/html/rfc8654): Extended Message Support for BGP
804- [RFC 8950](https://datatracker.ietf.org/doc/html/rfc8950): Advertising IPv4 NLRI with an IPv6 Next Hop
805- [RFC 9072](https://datatracker.ietf.org/doc/html/rfc9072): Extended Optional Parameters Length for BGP OPEN Message
806- [RFC 9234](https://datatracker.ietf.org/doc/html/rfc9234): Route Leak Prevention Using Roles in UPDATE and OPEN Messages
807
808## MRT (Multi-Threaded Routing Toolkit)
809
810- [RFC 6396](https://datatracker.ietf.org/doc/html/rfc6396): MRT Routing Information Export Format
811- [RFC 6397](https://datatracker.ietf.org/doc/html/rfc6397): MRT BGP Routing Information Export Format with Geo-Location Extensions
812- [RFC 8050](https://datatracker.ietf.org/doc/html/rfc8050): MRT Routing Information Export Format with BGP Additional Path Extensions
813
814## BMP (BGP Monitoring Protocol)
815
816- [RFC 7854](https://datatracker.ietf.org/doc/html/rfc7854): BGP Monitoring Protocol (BMP)
817- [RFC 8671](https://datatracker.ietf.org/doc/html/rfc8671): Support for Adj-RIB-Out in BMP
818- [RFC 9069](https://datatracker.ietf.org/doc/html/rfc9069): Support for Local RIB in BMP
819- [RFC 9515](https://datatracker.ietf.org/doc/html/rfc9515): Revision to Registration Procedures for Multiple BMP Registries
820- [RFC 9736](https://datatracker.ietf.org/doc/html/rfc9736): The BGP Monitoring Protocol (BMP) Peer Up Message Namespace
821- [RFC 9972](https://datatracker.ietf.org/doc/html/rfc9972): Advanced BGP Monitoring Protocol (BMP) Statistics Types
822
823## BGP Communities
824
825Full support for standard, extended, and large communities:
826- [RFC 1997](https://datatracker.ietf.org/doc/html/rfc1997): BGP Communities Attribute
827- [RFC 4360](https://datatracker.ietf.org/doc/html/rfc4360): BGP Extended Communities Attribute
828- [RFC 5668](https://datatracker.ietf.org/doc/html/rfc5668): 4-Octet AS Specific BGP Extended Community
829- [RFC 5701](https://datatracker.ietf.org/doc/html/rfc5701): IPv6 Address Specific BGP Extended Community Attribute
830- [RFC 7153](https://datatracker.ietf.org/doc/html/rfc7153): IANA Registries for BGP Extended Communities
831- [RFC 8097](https://datatracker.ietf.org/doc/html/rfc8097): BGP Prefix Origin Validation State Extended Community
832- [RFC 8092](https://datatracker.ietf.org/doc/html/rfc8092): BGP Large Communities
833
834## RPKI-to-Router (RTR) Protocol
835
836- [RFC 6810](https://datatracker.ietf.org/doc/html/rfc6810): The Resource Public Key Infrastructure (RPKI) to Router Protocol
837- [RFC 8210](https://datatracker.ietf.org/doc/html/rfc8210): The Resource Public Key Infrastructure (RPKI) to Router Protocol, Version 1
838
839## BGP Path Attributes
840
841Typed parsing for these RFC-defined BGP path attributes:
842
843- [RFC 5543](https://datatracker.ietf.org/doc/html/rfc5543): BGP Traffic Engineering Attribute
844- [RFC 7311](https://datatracker.ietf.org/doc/html/rfc7311): Accumulated IGP Metric (AIGP) Attribute
845- [RFC 9015](https://datatracker.ietf.org/doc/html/rfc9015): BGP SFP Attribute
846- [RFC 9026](https://datatracker.ietf.org/doc/html/rfc9026): BFD Discriminator Attribute
847- [RFC 8669](https://datatracker.ietf.org/doc/html/rfc8669): BGP Prefix-SID Attribute
848- [RFC 9793](https://datatracker.ietf.org/doc/html/rfc9793): BGP Extensions for BIER
849- [RFC 10005](https://datatracker.ietf.org/doc/html/rfc10005): BGP Link Bandwidth Extended Community
850
851Additional known attribute type codes are raw-retained (`AttributeValue::Raw`) and re-encoded faithfully. Deprecated and unassigned codes are also preserved.
852
853## Advanced Features
854
855**FlowSpec**:
856- [RFC 8955](https://datatracker.ietf.org/doc/html/rfc8955): Dissemination of Flow Specification Rules
857- [RFC 8956](https://datatracker.ietf.org/doc/html/rfc8956): Dissemination of Flow Specification Rules for IPv6
858- [RFC 9117](https://datatracker.ietf.org/doc/html/rfc9117): Revised Validation Procedure for BGP Flow Specifications
859
860**Tunnel Encapsulation**:
861- [RFC 5640](https://datatracker.ietf.org/doc/html/rfc5640): Load-Balancing for Mesh Softwires
862- [RFC 8365](https://datatracker.ietf.org/doc/html/rfc8365): Ethernet VPN (EVPN)
863- [RFC 9012](https://datatracker.ietf.org/doc/html/rfc9012): BGP Tunnel Encapsulation Attribute
864
865**Link-State (BGP-LS)**:
866- [RFC 7752](https://datatracker.ietf.org/doc/html/rfc7752): North-Bound Distribution of Link-State and TE Information
867- [RFC 8571](https://datatracker.ietf.org/doc/html/rfc8571): BGP-LS Advertisement of IGP TE Performance Metric Extensions
868- [RFC 9085](https://datatracker.ietf.org/doc/html/rfc9085): BGP-LS Extensions for Segment Routing
869- [RFC 9294](https://datatracker.ietf.org/doc/html/rfc9294): BGP-LS Advertisement of Application-Specific Link Attributes
870
871# See Also
872
873## Related BGPKIT Projects
874
875- **[BGPKIT Broker](https://github.com/bgpkit/bgpkit-broker)**: Search and discover MRT data files from RouteViews and RIPE RIS
876- **[BGPKIT API](https://data.bgpkit.com)**: RESTful API for MRT data file discovery
877- **[Monocle](https://github.com/bgpkit/monocle)**: Real-time BGP monitoring and alerting
878- **[BGPKIT Commons](https://github.com/bgpkit/bgpkit-commons)**: Common data structures and utilities
879
880## Resources
881
882- **[GitHub Repository](https://github.com/bgpkit/bgpkit-parser)**: Source code, examples, and issue tracking
883- **[Documentation](https://docs.rs/bgpkit-parser)**: Full API documentation
884- **[Changelog](https://github.com/bgpkit/bgpkit-parser/blob/main/CHANGELOG.md)**: Version history and release notes
885
886## Community
887
888- **Questions?** Open a [GitHub Discussion](https://github.com/bgpkit/bgpkit-parser/discussions)
889- **Found a bug?** Submit a [GitHub Issue](https://github.com/bgpkit/bgpkit-parser/issues)
890
891*/
892
893#![doc(
894    html_logo_url = "https://raw.githubusercontent.com/bgpkit/assets/main/logos/icon-transparent.png",
895    html_favicon_url = "https://raw.githubusercontent.com/bgpkit/assets/main/logos/favicon.ico"
896)]
897// A dropped `Result` from an encode_to() call would silently skip wire data —
898// exactly the corruption class the fallible encoding API exists to prevent.
899#![deny(unused_must_use)]
900
901#[cfg(feature = "parser")]
902pub mod encoder;
903pub mod error;
904pub mod models;
905#[cfg(feature = "parser")]
906pub mod parser;
907#[cfg(feature = "wasm")]
908pub mod wasm;
909
910pub use models::BgpElem;
911pub use models::BgpRouteElem;
912pub use models::MrtRecord;
913#[cfg(feature = "parser")]
914pub use parser::*;