A live route is identified by prefix, origin AS and peer, but in BGP a peer has at most one route per prefix. Two cases leave a stale route behind.
Where: internal/database/schema.sql (UNIQUE(prefix, origin_asn, peer_ip) on both live route tables), UpsertLiveRouteBatch and DeleteLiveRouteBatch in internal/database/database.go, and HandleMessage in internal/routewatch/prefixhandler.go.
A peer announces a prefix with origin AS 64500, later announces the same prefix with origin AS 64501. In BGP the second replaces the first. Here the second is inserted as a new row and the first stays, so the prefix shows two routes from that peer, one of them gone.
One RIS UPDATE can carry both announcements and withdrawals. HandleMessage gives every withdrawal in it the origin AS of the message's AS path, which belongs to the announced prefixes. DeleteLiveRouteBatch then deletes only a row with that origin, and the withdrawn route, whose origin differs, stays.
Failure scenario: an IP lookup or /prefix/... reports an origin AS the prefix no longer has, or two origins for one peer, which looks like a hijack that is not happening.
Severity: critical
Definition of done
A live route is identified by prefix and peer: the unique constraint in schema.sql is (prefix, peer_ip) (pre-1.0, no migration), an announcement replaces that peer's row for the prefix whatever its origin, and a withdrawal removes that peer's row for the prefix without looking at an origin AS.
Tests that fail before the fix for both cases above; the in-memory counts and prefix distribution stay exact.
Code that only existed for the origin match is removed rather than left unused.
make check passes.
Model: opus-5-5
A live route is identified by prefix, origin AS and peer, but in BGP a peer has at most one route per prefix. Two cases leave a stale route behind.
Where: `internal/database/schema.sql` (`UNIQUE(prefix, origin_asn, peer_ip)` on both live route tables), `UpsertLiveRouteBatch` and `DeleteLiveRouteBatch` in `internal/database/database.go`, and `HandleMessage` in `internal/routewatch/prefixhandler.go`.
- A peer announces a prefix with origin AS 64500, later announces the same prefix with origin AS 64501. In BGP the second replaces the first. Here the second is inserted as a new row and the first stays, so the prefix shows two routes from that peer, one of them gone.
- One RIS UPDATE can carry both announcements and withdrawals. `HandleMessage` gives every withdrawal in it the origin AS of the message's AS path, which belongs to the announced prefixes. `DeleteLiveRouteBatch` then deletes only a row with that origin, and the withdrawn route, whose origin differs, stays.
Failure scenario: an IP lookup or `/prefix/...` reports an origin AS the prefix no longer has, or two origins for one peer, which looks like a hijack that is not happening.
Severity: critical
## Definition of done
- A live route is identified by prefix and peer: the unique constraint in `schema.sql` is `(prefix, peer_ip)` (pre-1.0, no migration), an announcement replaces that peer's row for the prefix whatever its origin, and a withdrawal removes that peer's row for the prefix without looking at an origin AS.
- Tests that fail before the fix for both cases above; the in-memory counts and prefix distribution stay exact.
- Code that only existed for the origin match is removed rather than left unused.
- `make check` passes.
Model: opus-5-5
clawbot
self-assigned this 2026-10-14 14:33:44 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
A live route is identified by prefix, origin AS and peer, but in BGP a peer has at most one route per prefix. Two cases leave a stale route behind.
Where:
internal/database/schema.sql(UNIQUE(prefix, origin_asn, peer_ip)on both live route tables),UpsertLiveRouteBatchandDeleteLiveRouteBatchininternal/database/database.go, andHandleMessageininternal/routewatch/prefixhandler.go.HandleMessagegives every withdrawal in it the origin AS of the message's AS path, which belongs to the announced prefixes.DeleteLiveRouteBatchthen deletes only a row with that origin, and the withdrawn route, whose origin differs, stays.Failure scenario: an IP lookup or
/prefix/...reports an origin AS the prefix no longer has, or two origins for one peer, which looks like a hijack that is not happening.Severity: critical
Definition of done
schema.sqlis(prefix, peer_ip)(pre-1.0, no migration), an announcement replaces that peer's row for the prefix whatever its origin, and a withdrawal removes that peer's row for the prefix without looking at an origin AS.make checkpasses.Model: opus-5-5