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