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
83 lines
2.7 KiB
Go
83 lines
2.7 KiB
Go
// Package database provides SQLite storage for BGP routing data: ASNs,
|
|
// prefixes, announcements, peerings and BGP peers. Its routes table holds a
|
|
// copy of the whole routing table that internal/routetable keeps in memory.
|
|
package database
|
|
|
|
import (
|
|
"context"
|
|
"net/netip"
|
|
"time"
|
|
|
|
"git.eeqj.de/sneak/routewatch/internal/routetable"
|
|
)
|
|
|
|
// Stats contains database statistics: counts of ASNs, prefixes, peerings and
|
|
// peers, and the file size.
|
|
type Stats struct {
|
|
ASNs int
|
|
Prefixes int
|
|
IPv4Prefixes int
|
|
IPv6Prefixes int
|
|
Peerings int
|
|
Peers int
|
|
FileSizeBytes int64
|
|
}
|
|
|
|
// Store defines the interface for database operations. It provides methods for
|
|
// managing ASNs, prefixes, announcements, peerings, BGP peers, and the copy of
|
|
// the routing table. Implementations must be safe for concurrent use.
|
|
//
|
|
//nolint:interfacebloat // the one seam handlers and tests depend on
|
|
type Store interface {
|
|
// ASN operations
|
|
GetOrCreateASN(number int, timestamp time.Time) (*ASN, error)
|
|
GetOrCreateASNBatch(asns map[int]SeenTimes) error
|
|
|
|
// Prefix operations
|
|
GetOrCreatePrefix(prefix string, timestamp time.Time) (*Prefix, error)
|
|
UpdatePrefixesBatch(prefixes map[string]time.Time) error
|
|
|
|
// Announcement operations
|
|
RecordAnnouncement(announcement *Announcement) error
|
|
|
|
// Peering operations
|
|
RecordPeering(asA, asB int, seen SeenTimes) error
|
|
|
|
// Statistics
|
|
GetStats() (Stats, error)
|
|
GetStatsContext(ctx context.Context) (Stats, error)
|
|
|
|
// Peer operations
|
|
UpdatePeer(peerIP string, peerASN int, messageType string, timestamp time.Time) error
|
|
UpdatePeerBatch(peers map[string]PeerUpdate) error
|
|
|
|
// Routing table operations: the database's copy of the table in memory
|
|
WriteRouteChanges(changes []routetable.Change, newPeers map[string]uint) error
|
|
ReadRouteTable(ctx context.Context) (*routetable.Table, error)
|
|
|
|
// ASN WHOIS operations
|
|
GetNextStaleASN(ctx context.Context, staleThreshold time.Duration) (int, error)
|
|
UpdateASNWHOIS(ctx context.Context, update *ASNWHOISUpdate) error
|
|
GetWHOISStats(ctx context.Context, staleThreshold time.Duration) (*WHOISStats, error)
|
|
|
|
// AS and prefix detail operations
|
|
GetAS(ctx context.Context, asn int) (*ASN, bool, error)
|
|
GetLastSeenASes(ctx context.Context) (*ASN, *ASN, error)
|
|
GetASWHOIS(ctx context.Context, asn int) (*ASN, error)
|
|
GetPrefixFirstSeen(ctx context.Context, prefix netip.Prefix) (time.Time, error)
|
|
GetASPeers(asn int) ([]ASPeer, error)
|
|
GetASPeersContext(ctx context.Context, asn int) ([]ASPeer, error)
|
|
|
|
// Lifecycle
|
|
Close() error
|
|
|
|
// Maintenance operations
|
|
Vacuum(ctx context.Context) error
|
|
Analyze(ctx context.Context) error
|
|
Checkpoint(ctx context.Context) error
|
|
Ping(ctx context.Context) error
|
|
}
|
|
|
|
// Ensure Database implements Store
|
|
var _ Store = (*Database)(nil)
|