Skip to content

fix(router): Remove VIP translation rows no binding owns - #814

Merged
privateip merged 1 commit into
mainfrom
fix/vipxlat-sweep
Oct 9, 2026
Merged

privateip merged 1 commit into
mainfrom
fix/vipxlat-sweep

Conversation

@privateip

Copy link
Copy Markdown
Collaborator

What was wrong

#809 added the backend slot to the key of each VIP translation ingress row. A router built before #809 wrote its ingress rows with slot 0. Binding teardown looks only for the slot the current code computes, and no periodic sweep ran over the table, so nothing ever removed those slot-0 rows.

Rows orphaned any other way also stayed forever. That includes rows left by a crash, a finalizer cleared by hand, or a manual write.

What changed

The router now sweeps the VIP translation table on every GC tick (5 minutes by default). It skips the first pass at startup, so the binding reconciler has one full interval to rewrite every live binding's rows before anything is deleted.

Each pass:

  1. Snapshots the table's generation.
  2. Lists every service VIP binding on this node, including ones being deleted.
  3. Works out each binding's two rows the same way the reconciler does.
  4. Removes every row outside that set, unless the row was written after the snapshot.

Slot-0 ingress rows are never in the set, so the sweep removes them.

Sometimes a binding's VRF is not on the node yet, or is briefly gone. The sweep then cannot tell which VRF the binding's rows sit in, so it keeps every row that matches the binding's address, port, protocol and slot in any VRF. Deleting those rows would only cause churn. If listing bindings fails, the sweep removes nothing that tick.

Important

The datapath has no slot-0 fallback, so galactic-gateway and galactic-router must be upgraded together across #809. This PR adds no compatibility shim. The gateway configuration guide and the router architecture doc now say this.

Testing

New table-driven unit tests cover these cases:

  • A live binding's slot-0 row is removed and its current rows are kept.
  • Rows no binding claims are removed.
  • A binding whose VRF is missing keeps its rows, but not its slot-0 row.
  • A binding on another node keeps nothing on this node.
  • With no bindings, every row is removed.
  • A failed binding list removes nothing.

I disabled the missing-VRF protection to confirm the tests fail without it. Lint, unit tests and build pass. In a worktree, the YAML formatter fails on .git, so I ran it with a config that excludes .git, and it passed. I did not run the end-to-end tests.

🤖 Generated with Claude Code

@privateip
privateip requested a review from a team as a code owner October 8, 2026 21:46
@privateip
privateip enabled auto-merge October 8, 2026 21:54
galactic-router now sweeps the table on every GC tick after the first pass. controller.VIPXlatSweeper takes the table's generation, lists every ServiceVIPBinding targeting the node, resolves each one's two rows through the same parse and VRF-context lookup the reconciler uses, and calls Reconcile with that live set. Rows registered after the snapshot survive, and skipping the initial pass gives the reconciler a full interval to re-register every live binding first.

A binding whose VRF context does not resolve right now (VRF not yet on the node, or briefly gone) has no known Argument, so every row shaped like one of its rows (direction, slot, protocol, address, port) is kept under any Block and Argument, rather than deleted and written back once it resolves. A binding whose spec does not parse never wrote a row, and any error listing bindings or building the index skips the pass.

resolveVIPBindingRows is split into parseVIPBindingRows and a VRF placement step so the sweep reuses it, and runCmd's GC ticker moves into runGCTicker to stay under the gocyclo limit.

usid.c has no slot-0 fallback, so galactic-gateway and galactic-router must be upgraded together across #799. The docs now say so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@privateip
privateip merged commit db14e37 into main Oct 9, 2026
15 checks passed
@privateip
privateip deleted the fix/vipxlat-sweep branch October 9, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants