Live routes keyed by origin AS: an origin change or a withdrawal sent with announcements leaves a stale route #55

Open
opened 2026-10-14 14:33:44 +02:00 by clawbot · 0 comments
Collaborator

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
clawbot added the critical label 2026-10-14 14:33:47 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/routewatch#55