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")]
281use bgpkit_parser::{parse_ris_live_message_raw, RisLiveClientMessage, RisSubscribe};
282use tungstenite::{connect, Message};
283
284const RIS_LIVE_URL: &str = "ws://ris-live.ripe.net/v1/ws/?client=rust-bgpkit-parser";
285
286/// This is an example of subscribing to RIS-Live's streaming data from one host (`rrc21`).
287///
288/// For more RIS-Live details, check out their documentation at https://ris-live.ripe.net/manual/
289fn main() {
290    // connect to RIPE RIS Live websocket server
291    let (mut socket, _response) =
292        connect(RIS_LIVE_URL)
293            .expect("Can't connect to RIS Live websocket server");
294
295    // subscribe to messages from one collector and request hex-encoded raw BGP messages
296    let msg = RisSubscribe::new().host("rrc21").include_raw(true).to_json_string();
297    socket.send(Message::Text(msg.into())).unwrap();
298
299    loop {
300        let msg = socket.read().expect("Error reading message").to_string();
301#       #[cfg(feature = "rislive")]
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**Parsing OpenBMP Messages From RouteViews Kafka Stream**
312
313[RouteViews](http://www.routeviews.org/routeviews/) provides a real-time Kafka stream of the OpenBMP
314data received from their collectors. Below is a partial example of how we handle the raw bytes
315received from the Kafka stream. For full examples, check out the [examples folder on GitHub](https://github.com/bgpkit/bgpkit-parser/tree/main/examples).
316
317```rust,no_run
318# use log::{info, error};
319# use bytes::Bytes;
320# struct KafkaMessage { value: Vec<u8> }
321# let m = KafkaMessage { value: vec![] };
322use bgpkit_parser::parser::bmp::messages::*;
323use bgpkit_parser::parser::utils::*;
324use bgpkit_parser::{Elementor, parse_openbmp_header, parse_bmp_msg};
325
326let bytes = &m.value;
327let mut data = Bytes::from(bytes.clone());
328let header = parse_openbmp_header(&mut data).unwrap();
329let bmp_msg = parse_bmp_msg(&mut data);
330match bmp_msg {
331    Ok(msg) => {
332        let timestamp = header.timestamp;
333        let per_peer_header = msg.per_peer_header.unwrap();
334        match msg.message_body {
335            BmpMessageBody::RouteMonitoring(m) => {
336                for elem in Elementor::bgp_to_elems(
337                    m.bgp_message,
338                    timestamp,
339                    &per_peer_header.peer_ip,
340                    &per_peer_header.peer_asn
341                )
342                {
343                    info!("{}", elem);
344                }
345            }
346            _ => {}
347        }
348    }
349    Err(_e) => {
350        let hex = hex::encode(bytes);
351        error!("{}", hex);
352    }
353}
354```
355
356[ris-live-url]: https://ris-live.ripe.net
357[bmp-rfc]: https://datatracker.ietf.org/doc/html/rfc7854
358[openbmp-url]: https://www.openbmp.org/
359
360### Encoding: Archiving Filtered MRT Records
361
362The example will download one MRT file from RouteViews, filter out all the BGP messages that
363are not originated from AS3356, and write the filtered MRT records to disk. Then it re-parses the
364filtered MRT file and prints out the number of BGP messages.
365
366```no_run
367use bgpkit_parser::Elementor;
368use itertools::Itertools;
369use std::io::Write;
370
371let mut updates_encoder = bgpkit_parser::encoder::MrtUpdatesEncoder::new();
372
373bgpkit_parser::BgpkitParser::new(
374    "http://archive.routeviews.org/bgpdata/2023.10/UPDATES/updates.20231029.2015.bz2",
375).unwrap()
376    .add_filter("origin_asn", "3356").unwrap()
377    .into_iter()
378    .for_each(|elem| {
379        updates_encoder.process_elem(&elem);
380    });
381
382let mut mrt_writer = oneio::get_writer("as3356_mrt.gz").unwrap();
383mrt_writer.write_all(updates_encoder.export_bytes().unwrap().as_ref()).unwrap();
384drop(mrt_writer);
385```
386
387# FAQ & Troubleshooting
388
389## Common Issues
390
391### Parser creation fails with "unsupported compression"
392**Problem**: The file uses an unsupported compression format.
393
394**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.
395
396### Out of memory when parsing large files
397**Problem**: Collecting all elements into a vector exhausts available memory.
398
399**Solution**: Use streaming iteration instead of collecting:
400```rust,ignore
401// ❌ Don't do this for large files
402let all_elems: Vec<_> = parser.into_iter().collect();
403
404// ✅ Process iteratively
405for elem in parser {
406    // Process one element at a time
407    process(elem);
408}
409```
410
411### Slow performance on network files
412**Problem**: Remote file parsing is slower than expected.
413
414**Solution**:
415- Use the `--cache-dir` option in CLI to cache downloaded files
416- In library code, download the file first with appropriate buffering
417- Consider processing files in parallel if dealing with multiple files
418
419### Missing or incomplete BGP attributes
420**Problem**: Some [BgpElem] fields are `None` when you expect values.
421
422**Solution**: Not all BGP messages contain all attributes. Check the MRT format and BGP message type:
423- Withdrawals typically don't have AS paths or communities
424- Some collectors may not export certain attributes
425- Use pattern matching to handle `Option` types properly
426
427## Performance Tips
428
429### Use filters early
430Apply filters during parser creation to avoid processing unwanted data:
431```rust,ignore
432// ✅ Efficient - filters during parsing
433let parser = BgpkitParser::new(url)?
434    .add_filter("prefix", "1.1.1.0/24")?;
435
436// ❌ Less efficient - processes everything first
437let filtered: Vec<_> = BgpkitParser::new(url)?
438    .into_iter()
439    .filter(|e| e.prefix.to_string() == "1.1.1.0/24")
440    .collect();
441```
442
443### Process multiple files in parallel
444For bulk processing, use parallel iterators:
445```rust,ignore
446use rayon::prelude::*;
447
448let files = vec!["file1.mrt.bz2", "file2.mrt.bz2", "file3.mrt.bz2"];
449files.par_iter().for_each(|file| {
450    let parser = BgpkitParser::new(file).unwrap();
451    // Process each file in parallel
452});
453```
454
455### Choose the right data structure
456- Use [MrtRecord] iteration for minimal memory overhead
457- Use [MrtUpdate] for efficient batch processing without per-prefix attribute duplication
458- Use [BgpElem] for easier per-prefix analysis
459- See [Data Representation](#data-representation) for detailed comparison
460
461# Command Line Tool
462
463`bgpkit-parser` is bundled with a utility commandline tool `bgpkit-parser-cli`.
464
465## Installation
466
467### Install compiled binaries
468
469You can install the compiled `bgpkit-parser` CLI binaries with the following methods:
470- **Homebrew** (macOS): `brew install bgpkit/tap/bgpkit-parser`
471- [**Cargo binstall**](https://github.com/cargo-bins/cargo-binstall): `cargo binstall bgpkit-parser`
472
473### From source
474
475You can install the tool by running
476```bash
477cargo install bgpkit-parser --features cli
478```
479or checkout this repository and run
480```bash
481cargo install --path . --features cli
482```
483
484## Usage
485
486Run `bgpkit-parser --help` to see the full list of options.
487
488```text
489MRT/BGP/BMP data processing library
490
491Usage: bgpkit-parser [OPTIONS] <FILE>
492
493Arguments:
494  <FILE>  File path to a MRT file, local or remote
495
496Options:
497  -c, --cache-dir <CACHE_DIR>    Set the cache directory for caching remote files. Default behavior does not enable caching
498      --json                     Output as JSON objects
499      --psv                      Output as full PSV entries with header
500      --pretty                   Pretty-print JSON output
501  -e, --elems-count              Count BGP elems
502  -r, --records-count            Count MRT records
503      --recover                  Recover after damaged MRT framing and report skipped byte ranges on stderr
504  -o, --origin-asn <ORIGIN_ASN>  Filter by origin AS Number
505  -f, --filter <FILTERS>         Generic filter expression (key=value or key!=value)
506  -p, --prefix <PREFIX>          Filter by network prefix
507  -4, --ipv4-only                Filter by IPv4 only
508  -6, --ipv6-only                Filter by IPv6 only
509  -s, --include-super            Include super-prefix when filtering
510  -S, --include-sub              Include sub-prefix when filtering
511  -j, --peer-ip <PEER_IP>        Filter by peer IP address
512  -J, --peer-asn <PEER_ASN>      Filter by peer ASN
513  -m, --elem-type <ELEM_TYPE>    Filter by elem type: announce (a) or withdraw (w)
514  -t, --start-ts <START_TS>      Filter by start unix timestamp inclusive
515  -T, --end-ts <END_TS>          Filter by end unix timestamp inclusive
516  -a, --as-path <AS_PATH>        Filter by AS path regex string
517  -h, --help                     Print help
518  -V, --version                  Print version
519
520```
521
522## Common CLI Examples
523
524### Basic usage - Print all BGP messages
525```bash
526bgpkit-parser http://archive.routeviews.org/bgpdata/2021.10/UPDATES/updates.20211001.0000.bz2
527```
528
529### Filter by origin AS
530```bash
531bgpkit-parser -o 13335 updates.20211001.0000.bz2
532```
533
534### Filter by prefix
535```bash
536bgpkit-parser -p 1.1.1.0/24 updates.20211001.0000.bz2
537```
538
539### Output as JSON
540```bash
541bgpkit-parser --json updates.20211001.0000.bz2 > output.json
542```
543
544### Count elements efficiently
545```bash
546bgpkit-parser -e updates.20211001.0000.bz2
547```
548
549### Recover records after damaged framing
550```bash
551bgpkit-parser --recover -e damaged-updates.gz
552```
553
554### Cache remote files for faster repeated access
555```bash
556bgpkit-parser -c ~/.bgpkit-cache http://example.com/updates.mrt.bz2
557```
558
559### Combine filters
560```bash
561# IPv4 announcements from AS13335
562bgpkit-parser -o 13335 -m a -4 updates.bz2
563```
564
565### Negative filters (exclude matching elements)
566```bash
567# Exclude elements from AS 13335
568bgpkit-parser --filter "origin_asn!=13335" updates.bz2
569
570# Exclude a specific peer
571bgpkit-parser --filter "peer_ip!=192.168.1.1" updates.bz2
572
573# Combine positive and negative filters
574bgpkit-parser -o 13335 --filter "peer_asn!=64496" updates.bz2
575```
576
577# Data Representation
578
579BGPKIT Parser provides three ways to access parsed BGP data: [MrtRecord], [MrtUpdate], and [BgpElem]. Choose based on your needs:
580
581```text
582┌──────────────────────────────────────────────┐
583│                  MRT File                    │
584│  (Binary format: bgp4mp, tabledumpv2, etc.)  │
585└──────────────────────┬───────────────────────┘
586587                       ├──> Parser
588589         ┌──────────────┼────────────────┐
590         │              │                │
591         ▼              ▼                ▼
592   [MrtRecord]    [MrtUpdate]      [BgpElem]
593   (Low-level)   (Intermediate)   (High-level)
594         │             │                │
595         └─────────────┴────────────────┘
596597598              Your Analysis Code
599```
600
601## [MrtRecord]: Low-level MRT Representation
602
603[MrtRecord] preserves the complete, unmodified information from the MRT file. Use this when you need:
604- **Raw MRT data access**: Direct access to all MRT fields
605- **Format-specific details**: Peer index tables, geo-location data, etc.
606- **Memory efficiency**: Minimal overhead, compact representation
607- **Re-encoding**: Converting back to MRT format
608
609See the [MrtRecord] documentation for the complete structure definition.
610
611**Key components**:
612- `common_header`: Contains timestamp, record type, and metadata
613- `message`: The actual MRT message (TableDump, TableDumpV2, or Bgp4Mp)
614
615**Iteration**: Use [`BgpkitParser::into_record_iter()`] to iterate over [MrtRecord]s.
616
617## [MrtUpdate]: Intermediate Message-Level Representation
618
619[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:
620- **Efficient batch processing**: Avoid duplicating attributes across prefixes
621- **Message-level analysis**: Work with UPDATE messages or RIB entries as units
622- **Memory efficiency**: Shared attributes aren't cloned for each prefix
623
624# RPKI RTR Protocol Support
625
626BGPKIT Parser includes support for the RPKI-to-Router (RTR) protocol, enabling downstream
627clients to communicate with RTR cache servers and fetch Route Origin Authorizations (ROAs).
628
629## Overview
630
631The RTR protocol is used to deliver validated RPKI data from a cache server to a router.
632BGPKIT Parser provides:
633- **PDU definitions**: All RTR protocol data structures for both v0 (RFC 6810) and v1 (RFC 8210)
634- **Parsing**: Decode binary RTR PDUs into structured Rust types
635- **Encoding**: Serialize RTR PDUs to binary format for sending to servers
636
637**Note**: This library provides PDU parsing/encoding only. Transport (TCP, SSH, TLS) and
638RPKI validation logic are out of scope and should be handled by downstream clients.
639
640## Quick Example
641
642```rust
643use bgpkit_parser::models::rpki::rtr::*;
644use bgpkit_parser::parser::rpki::rtr::{parse_rtr_pdu, RtrEncode};
645
646// Create a Reset Query to request the full ROA database
647let query = RtrResetQuery::new_v1();
648let bytes = query.encode();
649
650// Parse a PDU from bytes
651let (pdu, consumed) = parse_rtr_pdu(&bytes).unwrap();
652assert!(matches!(pdu, RtrPdu::ResetQuery(_)));
653```
654
655## Available PDU Types
656
657| PDU Type | Direction | Description |
658|----------|-----------|-------------|
659| Serial Notify | Server → Client | Notifies client of new data |
660| Serial Query | Client → Server | Requests incremental update |
661| Reset Query | Client → Server | Requests full database |
662| Cache Response | Server → Client | Begins data transfer |
663| IPv4 Prefix | Server → Client | ROA for IPv4 prefix |
664| IPv6 Prefix | Server → Client | ROA for IPv6 prefix |
665| End of Data | Server → Client | Ends data transfer |
666| Cache Reset | Server → Client | Cannot provide incremental update |
667| Router Key | Server → Client | BGPsec key (v1 only) |
668| Error Report | Bidirectional | Error notification |
669
670## Building an RTR Client
671
672See the [`rtr_client` example](https://github.com/bgpkit/bgpkit-parser/blob/main/examples/rtr_client.rs)
673for a complete working example that:
6741. Connects to an RTR server
6752. Sends a Reset Query
6763. Collects ROAs
6774. Validates a route announcement (1.1.1.0/24 → AS13335)
678
679```bash
680cargo run --example rtr_client -- rtr.rpki.cloudflare.com 8282
681```
682
683**Supported message types** (via enum variants):
684- `Bgp4MpUpdate`: BGP UPDATE messages from UPDATES files
685- `LegacyBgpUpdate`: Deprecated MRT Type 5 BGP UPDATE messages
686- `TableDumpV2Entry`: RIB entries from TableDumpV2 RIB dumps
687- `TableDumpMessage`: Legacy TableDump v1 messages
688
689**Example**:
690```no_run
691use bgpkit_parser::{BgpkitParser, MrtUpdate};
692
693let parser = BgpkitParser::new("updates.mrt.bz2").unwrap();
694for update in parser.into_update_iter() {
695    match update {
696        MrtUpdate::Bgp4MpUpdate(u) => {
697            // One UPDATE message may contain multiple prefixes sharing attributes
698            println!("Peer {} announced {} prefixes",
699                u.peer_ip,
700                u.message.announced_prefixes.len()
701            );
702        }
703        MrtUpdate::LegacyBgpUpdate(u) => {
704            println!("Legacy UPDATE from peer {}", u.peer_ip);
705        }
706        MrtUpdate::TableDumpV2Entry(e) => {
707            // One prefix with multiple RIB entries (one per peer)
708            println!("Prefix {} seen by {} peers",
709                e.prefix,
710                e.rib_entries.len()
711            );
712        }
713        MrtUpdate::TableDumpMessage(m) => {
714            println!("Legacy table dump for {}", m.prefix);
715        }
716    }
717}
718```
719
720**Iteration**: Use [`BgpkitParser::into_update_iter()`] to iterate over [MrtUpdate]s.
721
722## [BgpElem]: High-level Per-Prefix Representation
723
724[BgpElem] provides a simplified, per-prefix view of BGP data. Each [BgpElem] represents a single prefix announcement or withdrawal. Use this when you want:
725- **Simple analysis**: Focus on prefixes without worrying about MRT format details
726- **Format-agnostic processing**: Same structure regardless of MRT format
727- **BGP attributes**: Easy access to AS path, communities, etc.
728
729**Example transformation**:
730```text
731MRT Record with 3 prefixes        →        3 BgpElem objects
732┌────────────────────────┐              ┌──────────────────┐
733│ BGP UPDATE Message     │              │ BgpElem          │
734│ AS Path: 64512 64513   │  ────────>   │ prefix: P1       │
735│ Prefixes:              │              │ as_path: 64512.. │
736│   - P1: 10.0.0.0/24    │              └──────────────────┘
737│   - P2: 10.0.1.0/24    │              ┌──────────────────┐
738│   - P3: 10.0.2.0/24    │  ────────>   │ BgpElem          │
739└────────────────────────┘              │ prefix: P2       │
740                                        │ as_path: 64512.. │
741                                        └──────────────────┘
742                                        ┌──────────────────┐
743                                        │ BgpElem          │
744                            ────────>   │ prefix: P3       │
745                                        │ as_path: 64512.. │
746                                        └──────────────────┘
747```
748
749See the [BgpElem] documentation for the complete structure definition.
750
751**Key fields**:
752- `timestamp`: Unix timestamp of the BGP message
753- `elem_type`: Announcement or withdrawal
754- `peer_ip` / `peer_asn`: The BGP peer information
755- `prefix`: The IP prefix being announced or withdrawn
756- `as_path`: The AS path attribute (if present)
757- `origin_asns`: Origin AS numbers extracted from AS path
758- `communities`: BGP communities (standard, extended, and large)
759- `next_hop`, `local_pref`, `med`: Other BGP attributes
760
761**Iteration**: Use [`BgpkitParser::into_elem_iter()`] or default iteration to iterate over [BgpElem]s.
762
763## Which One Should I Use?
764
765| Use Case | Recommended | Why |
766|----------|-------------|-----|
767| Simple prefix analysis | [BgpElem] | Easy per-prefix access, format-agnostic |
768| High-performance processing | [MrtUpdate] | Avoids attribute duplication overhead |
769| Counting prefixes per UPDATE | [MrtUpdate] | Direct access to message structure |
770| Re-encoding MRT data | [MrtRecord] | Preserves complete MRT structure |
771| MRT format-specific details | [MrtRecord] | Access to peer index tables, geo-location, etc. |
772
773**Memory trade-off**:
774- [BgpElem] duplicates shared attributes (AS path, communities) for each prefix
775- [MrtUpdate] keeps attributes shared within each message/entry
776- [MrtRecord] has minimal overhead but requires more code to extract BGP data
777
778# RFCs Support
779
780BGPKIT Parser implements comprehensive BGP, MRT, BMP, and related protocol standards. All listed RFCs are fully supported.
781
782**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).
783
784## Core BGP Protocol
785
786**Most commonly used**:
787- [RFC 4271](https://datatracker.ietf.org/doc/html/rfc4271): A Border Gateway Protocol 4 (BGP-4) - Core protocol
788- [RFC 2858](https://datatracker.ietf.org/doc/html/rfc2858): Multiprotocol Extensions for BGP-4 (IPv6 support)
789- [RFC 6793](https://datatracker.ietf.org/doc/html/rfc6793): Four-Octet AS Number Space
790- [RFC 7911](https://datatracker.ietf.org/doc/html/rfc7911): Advertisement of Multiple Paths (ADD-PATH)
791
792**Additional BGP RFCs**:
793- [RFC 2042](https://datatracker.ietf.org/doc/html/rfc2042): Registering New BGP Attribute Types
794- [RFC 2918](https://datatracker.ietf.org/doc/html/rfc2918): Route Refresh Capability for BGP-4
795- [RFC 3392](https://datatracker.ietf.org/doc/html/rfc3392): Capabilities Advertisement with BGP-4
796- [RFC 4724](https://datatracker.ietf.org/doc/html/rfc4724): Graceful Restart Mechanism for BGP
797- [RFC 4456](https://datatracker.ietf.org/doc/html/rfc4456): BGP Route Reflection
798- [RFC 5065](https://datatracker.ietf.org/doc/html/rfc5065): Autonomous System Confederations for BGP
799- [RFC 5492](https://datatracker.ietf.org/doc/html/rfc5492): Capabilities Advertisement with BGP-4
800- [RFC 7606](https://datatracker.ietf.org/doc/html/rfc7606): Revised Error Handling for BGP UPDATE Messages
801- [RFC 8277](https://datatracker.ietf.org/doc/html/rfc8277): Using BGP to Bind MPLS Labels to Address Prefixes (obsoletes RFC 3107)
802- [RFC 8654](https://datatracker.ietf.org/doc/html/rfc8654): Extended Message Support for BGP
803- [RFC 8950](https://datatracker.ietf.org/doc/html/rfc8950): Advertising IPv4 NLRI with an IPv6 Next Hop
804- [RFC 9072](https://datatracker.ietf.org/doc/html/rfc9072): Extended Optional Parameters Length for BGP OPEN Message
805- [RFC 9234](https://datatracker.ietf.org/doc/html/rfc9234): Route Leak Prevention Using Roles in UPDATE and OPEN Messages
806
807## MRT (Multi-Threaded Routing Toolkit)
808
809- [RFC 6396](https://datatracker.ietf.org/doc/html/rfc6396): MRT Routing Information Export Format
810- [RFC 6397](https://datatracker.ietf.org/doc/html/rfc6397): MRT BGP Routing Information Export Format with Geo-Location Extensions
811- [RFC 8050](https://datatracker.ietf.org/doc/html/rfc8050): MRT Routing Information Export Format with BGP Additional Path Extensions
812
813## BMP (BGP Monitoring Protocol)
814
815- [RFC 7854](https://datatracker.ietf.org/doc/html/rfc7854): BGP Monitoring Protocol (BMP)
816- [RFC 8671](https://datatracker.ietf.org/doc/html/rfc8671): Support for Adj-RIB-Out in BMP
817- [RFC 9069](https://datatracker.ietf.org/doc/html/rfc9069): Support for Local RIB in BMP
818- [RFC 9515](https://datatracker.ietf.org/doc/html/rfc9515): Revision to Registration Procedures for Multiple BMP Registries
819- [RFC 9736](https://datatracker.ietf.org/doc/html/rfc9736): The BGP Monitoring Protocol (BMP) Peer Up Message Namespace
820- [RFC 9972](https://datatracker.ietf.org/doc/html/rfc9972): Advanced BGP Monitoring Protocol (BMP) Statistics Types
821
822## BGP Communities
823
824Full support for standard, extended, and large communities:
825- [RFC 1997](https://datatracker.ietf.org/doc/html/rfc1997): BGP Communities Attribute
826- [RFC 4360](https://datatracker.ietf.org/doc/html/rfc4360): BGP Extended Communities Attribute
827- [RFC 5668](https://datatracker.ietf.org/doc/html/rfc5668): 4-Octet AS Specific BGP Extended Community
828- [RFC 5701](https://datatracker.ietf.org/doc/html/rfc5701): IPv6 Address Specific BGP Extended Community Attribute
829- [RFC 7153](https://datatracker.ietf.org/doc/html/rfc7153): IANA Registries for BGP Extended Communities
830- [RFC 8097](https://datatracker.ietf.org/doc/html/rfc8097): BGP Prefix Origin Validation State Extended Community
831- [RFC 8092](https://datatracker.ietf.org/doc/html/rfc8092): BGP Large Communities
832
833## RPKI-to-Router (RTR) Protocol
834
835- [RFC 6810](https://datatracker.ietf.org/doc/html/rfc6810): The Resource Public Key Infrastructure (RPKI) to Router Protocol
836- [RFC 8210](https://datatracker.ietf.org/doc/html/rfc8210): The Resource Public Key Infrastructure (RPKI) to Router Protocol, Version 1
837
838## BGP Path Attributes
839
840Typed parsing for these RFC-defined BGP path attributes:
841
842- [RFC 5543](https://datatracker.ietf.org/doc/html/rfc5543): BGP Traffic Engineering Attribute
843- [RFC 7311](https://datatracker.ietf.org/doc/html/rfc7311): Accumulated IGP Metric (AIGP) Attribute
844- [RFC 9015](https://datatracker.ietf.org/doc/html/rfc9015): BGP SFP Attribute
845- [RFC 9026](https://datatracker.ietf.org/doc/html/rfc9026): BFD Discriminator Attribute
846- [RFC 8669](https://datatracker.ietf.org/doc/html/rfc8669): BGP Prefix-SID Attribute
847- [RFC 9793](https://datatracker.ietf.org/doc/html/rfc9793): BGP Extensions for BIER
848- [RFC 10005](https://datatracker.ietf.org/doc/html/rfc10005): BGP Link Bandwidth Extended Community
849
850Additional known attribute type codes are raw-retained (`AttributeValue::Raw`) and re-encoded faithfully. Deprecated and unassigned codes are also preserved.
851
852## Advanced Features
853
854**FlowSpec**:
855- [RFC 8955](https://datatracker.ietf.org/doc/html/rfc8955): Dissemination of Flow Specification Rules
856- [RFC 8956](https://datatracker.ietf.org/doc/html/rfc8956): Dissemination of Flow Specification Rules for IPv6
857- [RFC 9117](https://datatracker.ietf.org/doc/html/rfc9117): Revised Validation Procedure for BGP Flow Specifications
858
859**Tunnel Encapsulation**:
860- [RFC 5640](https://datatracker.ietf.org/doc/html/rfc5640): Load-Balancing for Mesh Softwires
861- [RFC 8365](https://datatracker.ietf.org/doc/html/rfc8365): Ethernet VPN (EVPN)
862- [RFC 9012](https://datatracker.ietf.org/doc/html/rfc9012): BGP Tunnel Encapsulation Attribute
863
864**Link-State (BGP-LS)**:
865- [RFC 7752](https://datatracker.ietf.org/doc/html/rfc7752): North-Bound Distribution of Link-State and TE Information
866- [RFC 8571](https://datatracker.ietf.org/doc/html/rfc8571): BGP-LS Advertisement of IGP TE Performance Metric Extensions
867- [RFC 9085](https://datatracker.ietf.org/doc/html/rfc9085): BGP-LS Extensions for Segment Routing
868- [RFC 9294](https://datatracker.ietf.org/doc/html/rfc9294): BGP-LS Advertisement of Application-Specific Link Attributes
869
870# See Also
871
872## Related BGPKIT Projects
873
874- **[BGPKIT Broker](https://github.com/bgpkit/bgpkit-broker)**: Search and discover MRT data files from RouteViews and RIPE RIS
875- **[BGPKIT API](https://data.bgpkit.com)**: RESTful API for MRT data file discovery
876- **[Monocle](https://github.com/bgpkit/monocle)**: Real-time BGP monitoring and alerting
877- **[BGPKIT Commons](https://github.com/bgpkit/bgpkit-commons)**: Common data structures and utilities
878
879## Resources
880
881- **[GitHub Repository](https://github.com/bgpkit/bgpkit-parser)**: Source code, examples, and issue tracking
882- **[Documentation](https://docs.rs/bgpkit-parser)**: Full API documentation
883- **[Changelog](https://github.com/bgpkit/bgpkit-parser/blob/main/CHANGELOG.md)**: Version history and release notes
884
885## Community
886
887- **Questions?** Open a [GitHub Discussion](https://github.com/bgpkit/bgpkit-parser/discussions)
888- **Found a bug?** Submit a [GitHub Issue](https://github.com/bgpkit/bgpkit-parser/issues)
889
890*/
891
892#![doc(
893    html_logo_url = "https://raw.githubusercontent.com/bgpkit/assets/main/logos/icon-transparent.png",
894    html_favicon_url = "https://raw.githubusercontent.com/bgpkit/assets/main/logos/favicon.ico"
895)]
896// A dropped `Result` from an encode_to() call would silently skip wire data —
897// exactly the corruption class the fallible encoding API exists to prevent.
898#![deny(unused_must_use)]
899
900#[cfg(feature = "parser")]
901pub mod encoder;
902pub mod error;
903pub mod models;
904#[cfg(feature = "parser")]
905pub mod parser;
906#[cfg(feature = "wasm")]
907pub mod wasm;
908
909pub use models::BgpElem;
910pub use models::BgpRouteElem;
911pub use models::MrtRecord;
912#[cfg(feature = "parser")]
913pub use parser::*;