check / check (push) Canceled after 0s
The routing table in memory now holds every route, so the two per-peer route tables go, with every write, delete, count and read that served them. The prefix handler applies each update to the table, writes the table's changes every second, and stores each new prefix with its first-seen time. The peer delete, its retry on the next flush and the updates held for it go too. The types and errors of the server's answers move to internal/server. The image's memory settings fit a full table of about 1 GB: GOMEMLIMIT of 2.5 GiB, a 512 MiB page cache for the writing connection, and SQLite heap limits of 768 MiB and 1 GiB. The README describes the new table, its database copy and the memory budget. Model: opus-5-5
117 lines
3.5 KiB
Go
117 lines
3.5 KiB
Go
package database
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// ASN represents an Autonomous System Number with its metadata including
|
|
// handle, description, WHOIS data, and first/last seen timestamps.
|
|
//
|
|
//nolint:tagliatelle // field names are the existing JSON API
|
|
type ASN struct {
|
|
ASN int `json:"asn"`
|
|
Handle string `json:"handle"`
|
|
Description string `json:"description"`
|
|
// WHOIS parsed fields
|
|
ASName string `json:"as_name,omitempty"`
|
|
OrgName string `json:"org_name,omitempty"`
|
|
OrgID string `json:"org_id,omitempty"`
|
|
Address string `json:"address,omitempty"`
|
|
CountryCode string `json:"country_code,omitempty"`
|
|
AbuseEmail string `json:"abuse_email,omitempty"`
|
|
AbusePhone string `json:"abuse_phone,omitempty"`
|
|
TechEmail string `json:"tech_email,omitempty"`
|
|
TechPhone string `json:"tech_phone,omitempty"`
|
|
RIR string `json:"rir,omitempty"` // ARIN, RIPE, APNIC, LACNIC, AFRINIC
|
|
RIRRegDate *time.Time `json:"rir_registration_date,omitempty"`
|
|
RIRLastMod *time.Time `json:"rir_last_modified,omitempty"`
|
|
WHOISRaw string `json:"whois_raw,omitempty"`
|
|
// Timestamps. They are zero, and left out of JSON, for an AS that has no
|
|
// record in the asns table.
|
|
FirstSeen time.Time `json:"first_seen,omitzero"`
|
|
LastSeen time.Time `json:"last_seen,omitzero"`
|
|
WHOISUpdatedAt *time.Time `json:"whois_updated_at,omitempty"`
|
|
}
|
|
|
|
// Prefix represents an IP prefix (CIDR block) with its IP version (4 or 6)
|
|
// and the time it was first seen.
|
|
type Prefix struct {
|
|
Prefix string
|
|
IPVersion int // 4 or 6
|
|
FirstSeen time.Time
|
|
}
|
|
|
|
// Announcement represents a BGP announcement or withdrawal event,
|
|
// containing the prefix, AS path, origin ASN, peer ASN, next hop, and timestamp.
|
|
type Announcement struct {
|
|
ID uuid.UUID
|
|
PrefixID uuid.UUID
|
|
PeerASN int
|
|
OriginASN int
|
|
Path string // JSON-encoded AS path
|
|
NextHop string
|
|
Timestamp time.Time
|
|
IsWithdrawal bool
|
|
}
|
|
|
|
// ASNPeering represents a peering relationship between two ASNs,
|
|
// stored with the lower ASN as ASA and the higher as ASB.
|
|
type ASNPeering struct {
|
|
ID uuid.UUID
|
|
ASA int
|
|
ASB int
|
|
FirstSeen time.Time
|
|
LastSeen time.Time
|
|
}
|
|
|
|
// SeenTimes is the earliest and the latest time one batch of updates saw an AS,
|
|
// a peer or a peering. A row the batch adds is stored first seen at First and
|
|
// last seen at Last. A row already stored takes First as its first_seen only
|
|
// when First is earlier, and Last as its last_seen only when Last is later.
|
|
type SeenTimes struct {
|
|
First time.Time
|
|
Last time.Time
|
|
}
|
|
|
|
// Add makes t the earliest time of s when it is earlier than First, and the
|
|
// latest when it is later than Last. The zero SeenTimes holds no time yet, so
|
|
// the first Add sets both.
|
|
func (s *SeenTimes) Add(t time.Time) {
|
|
if s.First.IsZero() || t.Before(s.First) {
|
|
s.First = t
|
|
}
|
|
|
|
if s.Last.IsZero() || t.After(s.Last) {
|
|
s.Last = t
|
|
}
|
|
}
|
|
|
|
// PeerUpdate represents parameters for updating a peer. PeerASN and
|
|
// MessageType are those of the peer's latest update.
|
|
type PeerUpdate struct {
|
|
PeerIP string
|
|
PeerASN int
|
|
MessageType string
|
|
Seen SeenTimes
|
|
}
|
|
|
|
// ASNWHOISUpdate contains WHOIS data for updating an ASN record.
|
|
type ASNWHOISUpdate struct {
|
|
ASN int
|
|
ASName string
|
|
OrgName string
|
|
OrgID string
|
|
Address string
|
|
CountryCode string
|
|
AbuseEmail string
|
|
AbusePhone string
|
|
TechEmail string
|
|
TechPhone string
|
|
RIR string
|
|
RIRRegDate *time.Time
|
|
RIRLastMod *time.Time
|
|
WHOISRaw string
|
|
}
|