Record origin changes and show them on the prefix page (closes #161)
check / check (push) Successful in 4m6s

The routing table records each prefix and origin AS pair's origin changes:
when it gains its first peer and when it loses its last. Each row holds the
prefix, the origin AS, announced or withdrawn, the peer count and the time.
The prefix handler writes them to a new origin_changes table, and the database
maintainer prunes each prefix to its newest 500 rows and 72 hours. The prefix
page lists them newest first, at most 5,000.

Model: deepseek-v4-pro
This commit is contained in:
2026-11-05 04:07:39 +00:00
parent 15bf20a894
commit 347e1456a2
16 changed files with 1127 additions and 27 deletions
+12 -3
View File
@@ -142,7 +142,11 @@ and origin AS can have two kept routes, one or none.
- `/prefix/{prefix}/{length}`: a prefix, such as `/prefix/192.0.2.0/24`, with
its origin ASes and every peer that carries it. Only the kept routes show an
AS path, a next hop and a time. The next hop is the router the peer sends the
prefix's traffic to. RouteWatch records the peer itself as the next hop.
prefix's traffic to. RouteWatch records the peer itself as the next hop. The
page also lists the prefix's origin changes, newest first: each time an origin
AS gained its first peer or lost its last, with the time, announced or
withdrawn, the origin AS and the peer count. It shows at most the newest
5,000.
- `/prefixlength/{length}`: up to 500 IPv4 prefixes with that mask length,
picked at random. Each shows its origin AS and the age of its newest kept
route. When peers give a prefix different origin ASes, the page shows the one
@@ -516,7 +520,8 @@ The ceilings add up to 3.7 GiB:
pairs, so it takes about 1 GB. The rest of the heap takes up to about 0.5 GiB,
most of it the handlers' batches and queues (see below). The remaining 1 GiB
is room for the garbage collector, which frees memory the program no longer
uses. With much less, it would run almost all the time.
uses. With much less, it would run almost all the time. The routing table also
keeps at most 100,000 origin changes waiting to be written, about 8 MB.
- SQLite: 1 GiB, set in the code. The connection that does every write has a 512
MiB page cache: the database pages it keeps in memory from one write to the
next. The `routes` table of a full routing table takes about 450 MB, so its
@@ -638,7 +643,7 @@ The parts:
- The database maintainer checkpoints the database every 5 seconds: it folds the
write-ahead log, where SQLite first writes changes, into the database file. It
reclaims free space every 10 minutes. Every hour it refreshes the statistics
SQLite uses to plan its queries.
SQLite uses to plan its queries, and prunes the origin changes table.
- The HTTP server serves the pages and the API. Every route it shows comes from
the routing table in memory. WHOIS details and first-seen times come from the
database. AS names come from the database or from the AS list built into
@@ -809,6 +814,10 @@ routes(prefix, origin_asn, peers,
-- The peers of the routes table, each with its number in the peer sets
route_peers(number PRIMARY KEY, address UNIQUE)
-- The origin changes of the routing table: each time a prefix and origin AS
-- gained its first peer or lost its last
origin_changes(id PRIMARY KEY, prefix, origin_asn, announced, peer_count, time)
peerings(id PRIMARY KEY, as_a, as_b, first_seen, last_seen,
UNIQUE(as_a, as_b))
bgp_peers(id PRIMARY KEY, peer_ip UNIQUE, peer_asn, first_seen, last_seen,