check / check (push) Canceled after 0s
The home page gets cards for the newest and oldest kept route, the newest and oldest updated AS, the AS with the most prefixes, the ASes with a single prefix and fifteen well-known networks. Two more cards count the bogon announcements and the prefixes with several origin ASes. They link to the new pages /bogons and /multiple-origins, which list up to 1,000 entries each. The new package internal/bogon tells reserved prefixes and AS numbers, from the IANA special-purpose and address space registries. Table.Overview walks the table and lets the read lock go every 10,000 prefixes. The server works the cards out once a minute and serves that copy. A new index on asns(last_seen) finds the newest and oldest updated AS. Model: opus-5-5
122 lines
4.3 KiB
SQL
122 lines
4.3 KiB
SQL
-- IMPORTANT: This is the ONLY place where schema changes should be made.
|
|
-- We do NOT support migrations. All schema changes MUST be in this file.
|
|
-- DO NOT make schema changes anywhere else in the codebase.
|
|
|
|
CREATE TABLE IF NOT EXISTS asns (
|
|
asn INTEGER PRIMARY KEY,
|
|
handle TEXT,
|
|
description TEXT,
|
|
-- WHOIS parsed fields
|
|
as_name TEXT,
|
|
org_name TEXT,
|
|
org_id TEXT,
|
|
address TEXT, -- full address (may be multi-line)
|
|
country_code TEXT,
|
|
abuse_email TEXT,
|
|
abuse_phone TEXT,
|
|
tech_email TEXT,
|
|
tech_phone TEXT,
|
|
rir TEXT, -- ARIN, RIPE, APNIC, LACNIC, AFRINIC
|
|
rir_registration_date DATETIME,
|
|
rir_last_modified DATETIME,
|
|
-- Raw WHOIS response
|
|
whois_raw TEXT, -- complete WHOIS response text
|
|
-- Timestamps
|
|
first_seen DATETIME NOT NULL,
|
|
last_seen DATETIME NOT NULL,
|
|
whois_updated_at DATETIME -- when we last fetched WHOIS data
|
|
);
|
|
|
|
-- IPv4 prefixes table. Every read and write finds a row by its prefix, so the
|
|
-- rows are stored by prefix (WITHOUT ROWID) and need no index of their own.
|
|
CREATE TABLE IF NOT EXISTS prefixes_v4 (
|
|
prefix TEXT PRIMARY KEY,
|
|
first_seen DATETIME NOT NULL
|
|
) WITHOUT ROWID;
|
|
|
|
-- IPv6 prefixes table, stored as prefixes_v4 is.
|
|
CREATE TABLE IF NOT EXISTS prefixes_v6 (
|
|
prefix TEXT PRIMARY KEY,
|
|
first_seen DATETIME NOT NULL
|
|
) WITHOUT ROWID;
|
|
|
|
CREATE TABLE IF NOT EXISTS announcements (
|
|
id TEXT PRIMARY KEY,
|
|
prefix_id TEXT NOT NULL,
|
|
peer_asn INTEGER NOT NULL,
|
|
origin_asn INTEGER NOT NULL,
|
|
path TEXT NOT NULL,
|
|
next_hop TEXT,
|
|
timestamp DATETIME NOT NULL,
|
|
is_withdrawal BOOLEAN NOT NULL DEFAULT 0,
|
|
FOREIGN KEY (peer_asn) REFERENCES asns(asn),
|
|
FOREIGN KEY (origin_asn) REFERENCES asns(asn)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS peerings (
|
|
id TEXT PRIMARY KEY,
|
|
as_a INTEGER NOT NULL,
|
|
as_b INTEGER NOT NULL,
|
|
first_seen DATETIME NOT NULL,
|
|
last_seen DATETIME NOT NULL,
|
|
UNIQUE(as_a, as_b)
|
|
);
|
|
|
|
-- BGP peers that send us messages
|
|
CREATE TABLE IF NOT EXISTS bgp_peers (
|
|
id TEXT PRIMARY KEY,
|
|
peer_ip TEXT UNIQUE NOT NULL,
|
|
peer_asn INTEGER NOT NULL,
|
|
first_seen DATETIME NOT NULL,
|
|
last_seen DATETIME NOT NULL,
|
|
last_message_type TEXT
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_announcements_timestamp ON announcements(timestamp);
|
|
CREATE INDEX IF NOT EXISTS idx_announcements_prefix_id ON announcements(prefix_id);
|
|
CREATE INDEX IF NOT EXISTS idx_announcements_peer_asn ON announcements(peer_asn);
|
|
CREATE INDEX IF NOT EXISTS idx_announcements_origin_asn ON announcements(origin_asn);
|
|
CREATE INDEX IF NOT EXISTS idx_peerings_as_a ON peerings(as_a);
|
|
CREATE INDEX IF NOT EXISTS idx_peerings_as_b ON peerings(as_b);
|
|
CREATE INDEX IF NOT EXISTS idx_peerings_lookup ON peerings(as_a, as_b);
|
|
|
|
-- Indexes for asns table
|
|
CREATE INDEX IF NOT EXISTS idx_asns_asn ON asns(asn);
|
|
CREATE INDEX IF NOT EXISTS idx_asns_whois_updated_at ON asns(whois_updated_at);
|
|
-- Finds the AS last seen most recently and the one last seen longest ago, for
|
|
-- the home page.
|
|
CREATE INDEX IF NOT EXISTS idx_asns_last_seen ON asns(last_seen);
|
|
|
|
-- Indexes for bgp_peers table
|
|
CREATE INDEX IF NOT EXISTS idx_bgp_peers_asn ON bgp_peers(peer_asn);
|
|
CREATE INDEX IF NOT EXISTS idx_bgp_peers_last_seen ON bgp_peers(last_seen);
|
|
CREATE INDEX IF NOT EXISTS idx_bgp_peers_ip ON bgp_peers(peer_ip);
|
|
|
|
-- The whole routing table, as internal/routetable keeps it in memory: one row
|
|
-- for each prefix and origin AS that some peer carries. Startup reads every
|
|
-- row, and the rows of the pairs that change are written back.
|
|
CREATE TABLE IF NOT EXISTS routes (
|
|
prefix TEXT NOT NULL, -- in the text form Go's net/netip prints
|
|
origin_asn INTEGER NOT NULL,
|
|
-- The peers whose current route to the prefix has this origin AS: a set
|
|
-- of their numbers in route_peers, as the bitset package's MarshalBinary
|
|
-- writes it.
|
|
peers BLOB NOT NULL,
|
|
-- The newest of those routes and the one before it, the two kept in full.
|
|
-- Each has its peer's number in route_peers, its AS path as a JSON array,
|
|
-- and its time in seconds since 1970, UTC. A route that is not kept has
|
|
-- NULL in its three columns.
|
|
newest_peer INTEGER,
|
|
newest_as_path TEXT,
|
|
newest_time INTEGER,
|
|
older_peer INTEGER,
|
|
older_as_path TEXT,
|
|
older_time INTEGER,
|
|
PRIMARY KEY (prefix, origin_asn)
|
|
) WITHOUT ROWID;
|
|
|
|
-- The peers of the routes table, each with the number it has there.
|
|
CREATE TABLE IF NOT EXISTS route_peers (
|
|
number INTEGER PRIMARY KEY,
|
|
address TEXT NOT NULL UNIQUE
|
|
); |