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