Store the routing table in the database (part of #122)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
A new routes table holds one row per prefix and origin AS: the peer set as the bitset's bytes, and the two kept routes, each with its peer's number, AS path and time in seconds. A new route_peers table holds each peer's number and address. WriteRouteChanges writes one TakeChanges result in a transaction. ReadRouteTable reads both tables into a new routing table, through the new Table.Load, which records no change. It fails on a row that names a peer number missing from route_peers. Nothing uses them yet. Model: opus-5-5
This commit was merged in pull request #186.
This commit is contained in:
@@ -218,6 +218,53 @@ func (t *Table) PeerDown(peer string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Load puts one prefix and origin AS pair that the database holds into the
|
||||
// table, as startup does with each row it reads. The change's peers join the
|
||||
// pair's peer set, and its routes are kept as an announcement's would be.
|
||||
// Unlike an update, Load records no change, so TakeChanges does not hand the
|
||||
// pair back to be written again. Loading a pair twice changes nothing.
|
||||
//
|
||||
// The caller makes sure that every peer change names, in its peer set or in
|
||||
// its routes, has a number in Params.PeerNumbers.
|
||||
func (t *Table) Load(change Change) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
// A removed pair has no peers, and a pair without peers is not in the
|
||||
// table.
|
||||
if change.Peers == nil || change.Peers.None() || !change.Prefix.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
prefix := change.Prefix.Masked()
|
||||
o := t.findOrAddOrigin(prefix, change.OriginASN)
|
||||
wasWithoutKeptRoute := o.withoutKeptRoute()
|
||||
|
||||
for peer := range change.Peers.EachSet() {
|
||||
if !o.peers.Test(peer) {
|
||||
o.peers.Set(peer)
|
||||
|
||||
t.familyOf(prefix.Addr()).routes++
|
||||
t.peerPrefixes[peer]++
|
||||
}
|
||||
}
|
||||
|
||||
// Oldest first, as they were announced, so that two routes with the same
|
||||
// time are kept in the order they had.
|
||||
for _, r := range slices.Backward(change.Routes) {
|
||||
peer := t.peerNumbers[r.Peer]
|
||||
|
||||
t.dropKeptRoute(o, peer)
|
||||
t.keepIfNewest(o, route{
|
||||
peer: peer,
|
||||
path: slices.Clone(r.ASPath),
|
||||
time: r.Time,
|
||||
})
|
||||
}
|
||||
|
||||
t.countOriginWithoutKeptRoute(o, wasWithoutKeptRoute)
|
||||
}
|
||||
|
||||
// TakeChanges returns the prefix and origin AS pairs that changed since it last
|
||||
// ran, in prefix order, each with its current content. It also returns the
|
||||
// peers numbered since then, by address. It then clears both records.
|
||||
@@ -413,6 +460,17 @@ func (t *Table) recordChange(
|
||||
) {
|
||||
t.changed[pair{prefix: prefix, asn: o.asn}] = struct{}{}
|
||||
|
||||
t.countOriginWithoutKeptRoute(o, wasWithoutKeptRoute)
|
||||
|
||||
if o.peers.None() {
|
||||
t.removeOrigin(prefix, o)
|
||||
}
|
||||
}
|
||||
|
||||
// countOriginWithoutKeptRoute brings the count of origins without a kept route
|
||||
// up to date after a change to o. wasWithoutKeptRoute says whether o was such
|
||||
// an origin before the change.
|
||||
func (t *Table) countOriginWithoutKeptRoute(o *origin, wasWithoutKeptRoute bool) {
|
||||
if wasWithoutKeptRoute {
|
||||
t.originsWithoutKeptRoute--
|
||||
}
|
||||
@@ -420,10 +478,6 @@ func (t *Table) recordChange(
|
||||
if o.withoutKeptRoute() {
|
||||
t.originsWithoutKeptRoute++
|
||||
}
|
||||
|
||||
if o.peers.None() {
|
||||
t.removeOrigin(prefix, o)
|
||||
}
|
||||
}
|
||||
|
||||
// countKeptTime adds delta to the number of kept routes with time at.
|
||||
|
||||
Reference in New Issue
Block a user