Skip to content

QuickRIB

BGP routing table reconstruction and analysis.

QuickRIB rebuilds the routing table that each peer of a route collector held at a chosen instant, replays the BGP updates that followed, and drives any number of analysis modules from that single replay. The data comes from the RIPE RIS and Route Views archives through PyBGPFlux.

The problem

A route collector publishes a complete dump of its tables every two hours (Route Views) or every eight hours (RIPE RIS), and a continuous stream of the update messages received in between. The table at an arbitrary instant is therefore not stored anywhere: it is the last dump before that instant with every subsequent update applied to it. Most quantities computed from BGP data, whether a centrality metric, a reachability signal or a classification of the updates themselves, are functions of that table or of how it changes, so the reconstruction is a prerequisite that every study has to repeat.

QuickRIB performs it once and exposes the result as a live object. Analysis code attaches to the table as an observer and is notified of every change, so a quantity can be maintained message by message instead of being recomputed from a million-prefix table every few minutes. Where an analysis is cheaper to recompute than to maintain, the same replay serves it too.

Built-in observers

Observer Quantity Reference
HegemonyObserver AS and link hegemony, a centrality robust to the collector's partial view Fontugne, Shah and Aben, PAM 2018
IODAObserver Visible /24 blocks per origin AS, the BGP signal of the IODA outage detector IODA, Georgia Tech / CAIDA
BGPlayObserver The RIPEstat bgplay payload for a prefix or an AS RIPE NCC
UpdateTagger BLT classification of every update message Kitabatake, Fontugne and Esaki, 2018
MADObserver Multi-scale anomaly scores over the hegemony temporal graph Loye, Bautista and Fontugne, IMC 2026

Observers that reproduce a published signal are tested against the live API that publishes it.

Installation

pip install quickrib

Quick start

"""Reconstruct a routing table and count the updates applied to it.

The smallest complete run: configure a window, attach one observer, call
`run()`. Everything else in QuickRIB is a different observer on the same
pipeline.
"""

import datetime
from pathlib import Path

from quickrib import QuickRIB, QuickRIBConfig
from quickrib.observers import UpdateTagsCounter

config = QuickRIBConfig(
    start_time=datetime.datetime(2010, 9, 1, 0, 0),
    end_time=datetime.datetime(2010, 9, 1, 1, 59),
    collectors=["route-views.wide"],
    dump_res=datetime.timedelta(minutes=15),
    cache_dir=Path("cache"),
    parser="bgpkit",
)

quickrib = QuickRIB.from_config(config)

counter = UpdateTagsCounter()
quickrib.rib.attach_observer(counter)

quickrib.run()

# The reconstructed table: collector -> (peer ASN, peer IP) -> radix tree.
for collector, peers in quickrib.rib.data.items():
    for (peer_asn, peer_ip), table in peers.items():
        print(f"{collector} AS{peer_asn} {peer_ip}: {len(table.prefixes())} prefixes")

Reading on

  • Getting Started: installation, parsers and configuration.
  • Reconstruction: what the pipeline computes and the assumptions it makes about the archives.
  • Observers: the analysis interface and how to write one.
  • Performance: what a run costs and how to keep it cheap.