bgpkit-commons 0.11.0

A library for common BGP-related data and functions.
Documentation

BGPKIT Commons

Crates.io Docs.rs License Discord

bgpkit-commons is a library for common BGP-related data and functions. It provides a unified interface to multiple BGP data sources through a lazy-loading architecture — modules are independently enabled via feature flags and data is only fetched when explicitly requested.

Architecture

graph TD
    B[BgpkitCommons]

    B -->|load_asinfo| M1[asinfo]
    B -->|load_as2rel| M2[as2rel]
    B -->|load_bogons| M3[bogons]
    B -->|load_countries| M4[countries]
    B -->|load_mrt_collectors| M5[mrt_collectors]
    B -->|load_rpki| M6[rpki]

    M1 -->|asinfo_get, asinfo_all| A1[RIPE NCC / CAIDA / APNIC / PeeringDB]
    M2 -->|as2rel_lookup| A2[BGPKIT inference]
    M3 -->|bogons_match| A3[IANA registries]
    M4 -->|country_by_code| A4[GeoNames]
    M5 -->|mrt_collectors_all| A5[RouteViews / RIPE RIS]
    M6 -->|rpki_validate| A6[Cloudflare / RIPE NCC / RPKIviews / RPKISPOOL]

Each module is gated by a feature flag. The all feature (default) enables everything. Data is fetched on the first load_xxx() call and kept in memory until reload() is called. The Cloudflare RPKI module also exposes a validator-aware polling API for avoiding full re-downloads when the source has not changed; see Conditional RPKI loading.

Modules

Module Feature Data Sources Key Functions
[asinfo] asinfo RIPE NCC, CAIDA as2org, APNIC, IIJ IHR, PeeringDB asinfo_get, asinfo_all, asinfo_are_siblings
[as2rel] as2rel BGPKIT AS relationship inference as2rel_lookup
[bogons] bogons IANA special registries bogons_match, bogons_match_prefix, bogons_match_asn
[countries] countries GeoNames country_by_code, country_by_code3, country_by_name
[mrt_collectors] mrt_collectors RouteViews, RIPE RIS mrt_collectors_all, mrt_collector_peers_all
[rpki] rpki Cloudflare, RIPE NCC, RPKIviews, RPKISPOOL rpki_validate, rpki_validate_check_expiry, rpki_lookup_by_prefix

RPKI data sources

Source Data and scope Wire/file compression Main entry points
Cloudflare Current aggregate ROA, ASPA, and BGPsec data HTTP Content-Encoding: gzip RpkiTrie::from_cloudflare, RpkiTrie::from_cloudflare_conditional
RIPE NCC Historical data from all five RIRs output.json.xz RpkiTrie::from_ripe_historical, list_ripe_files
RPKIviews Historical collector-specific snapshots .tgz (gzip-compressed tar) RpkiTrie::from_rpkiviews, list_rpkiviews_files
RPKISPOOL Historical CCR snapshots from a collector .tar.zst RpkiTrie::from_rpkispools, parse_rpkispools_archive

Collector-specific sources represent the selected collector's vantage point and snapshot; they should not be interpreted as a complete global view by themselves.

Quick Start

[dependencies]
bgpkit-commons = "0.10"
use bgpkit_commons::BgpkitCommons;

let mut commons = BgpkitCommons::new();

// Load the modules you need
commons.load_bogons().unwrap();
commons.load_asinfo(false, false, false, false).unwrap();

// Access the data
if let Ok(is_bogon) = commons.bogons_match("23456") {
    println!("ASN 23456 is bogon: {}", is_bogon);
}
if let Ok(Some(info)) = commons.asinfo_get(13335) {
    println!("AS13335: {} ({})", info.name, info.country);
}

Examples

RPKI Validation

use bgpkit_commons::BgpkitCommons;

let mut commons = BgpkitCommons::new();
commons.load_rpki(None).unwrap(); // None = real-time from Cloudflare

let result = commons.rpki_validate(13335, "1.1.1.0/24").unwrap();
println!("Validation result: {:?}", result);

Conditional RPKI loading

For a long-running service that polls Cloudflare repeatedly, retain the validators from the previous successful load. A matching validator produces Ok(None) from the next request, so the large JSON payload is not downloaded or parsed again:

use bgpkit_commons::rpki::RpkiTrie;

let mut etag = None;
let mut last_modified = None;

if let Some(load) = RpkiTrie::from_cloudflare_conditional(
    etag.as_deref(),
    last_modified.as_deref(),
)? {
    etag = load.etag.clone();
    last_modified = load.last_modified.clone();
    // Swap `load.trie` into the serving process after the complete rebuild.
} // `None` means HTTP 304: keep the currently served trie.
# Ok::<(), bgpkit_commons::BgpkitCommonsError>(())

BgpkitCommons::reload() is not validator-aware: it performs a regular full reload. Use the direct RpkiTrie conditional API when polling needs ETag/Last-Modified reuse.

Historical RPKI Data

use bgpkit_commons::BgpkitCommons;
use bgpkit_commons::rpki::{HistoricalRpkiSource, RpkiViewsCollector};
use chrono::NaiveDate;

let mut commons = BgpkitCommons::new();
let date = NaiveDate::from_ymd_opt(2024, 1, 4).unwrap();

// From RIPE NCC historical archives
commons.load_rpki_historical(date, HistoricalRpkiSource::Ripe).unwrap();

// Or from an RPKIviews collector
let source = HistoricalRpkiSource::RpkiViews(RpkiViewsCollector::SobornostNet);
commons.load_rpki_historical(date, source).unwrap();

// Or from RPKISPOOL (CCR format, parses faster)
use bgpkit_commons::rpki::RpkiSpoolsCollector;
let source = HistoricalRpkiSource::RpkiSpools(RpkiSpoolsCollector::default());
commons.load_rpki_historical(date, source).unwrap();

Available RPKIviews collectors: SobornostNet (default), MassarsNet, AttnJp, KerfuffleNet.

Available RPKISPOOL collectors: SobornostNet (default), AttnJp, KerfuffleNet.

AS Information with Builder

use bgpkit_commons::BgpkitCommons;

let mut commons = BgpkitCommons::new();
let builder = commons.asinfo_builder()
    .with_as2org()
    .with_peeringdb();
commons.load_asinfo_with(builder).unwrap();

if let Ok(are_siblings) = commons.asinfo_are_siblings(13335, 132892) {
    println!("AS13335 and AS132892 are siblings: {}", are_siblings);
}

Direct Module Access

All modules can be used directly without BgpkitCommons:

use bgpkit_commons::bogons::Bogons;
use bgpkit_commons::rpki::RpkiTrie;

let bogons = Bogons::new().unwrap();
let trie = RpkiTrie::from_cloudflare().unwrap();

Feature Flags

Feature Description
asinfo AS information: names, countries, organizations, population, hegemony
as2rel AS relationship data
bogons Bogon prefix and ASN detection
countries Country information lookup
mrt_collectors MRT collector metadata
rpki RPKI validation (ROA and ASPA)
all (default) Enables all modules

For a minimal build:

[dependencies]
bgpkit-commons = { version = "0.10", default-features = false, features = ["bogons", "rpki"] }

Examples requiring a particular module are feature-gated in Cargo.toml. For example:

cargo run --example rpki_historical --features rpki
cargo run --example rpkispools --features rpki
cargo run --example as2org --features asinfo,countries

Operational notes

  • Loading data requires network access; sources are fetched lazily when their load method is called.
  • The Cloudflare RPKI payload is large in memory even when HTTP gzip substantially reduces transfer size.
  • .gz, .xz, and .bz2 URL suffixes are decompressed by oneio. RPKIviews .tgz archives are streamed and require the gunzip executable to be available in PATH.
  • PeeringDB loading can use PEERINGDB_API_KEY; when unset, the client sends no empty API-key header.
  • reload() replaces already-loaded module data by fetching it again. It does not provide an atomic swap or conditional HTTP polling for the RPKI module.

License

MIT