Skip to content

fix(usid): Deliver inbound traffic to tap and veth Instances that share a VPC on one node - #534

Merged
scotwells merged 1 commit into
mainfrom
fix/usid-per-interface-egress-kind
Sep 13, 2026
Merged

scotwells merged 1 commit into
mainfrom
fix/usid-per-interface-egress-kind

Conversation

@scotwells

Copy link
Copy Markdown
Contributor

Summary

A general-purpose Instance could become unreachable as soon as a unikernel Instance joined the same VPC on the same node. Inbound connections to it timed out, and no drop counter recorded the loss. With this change, both kinds of Instance receive inbound traffic, whatever order they attach in.

Cause

The datapath picks one of two kernel redirect methods to deliver decapsulated traffic. Veth attachments (unikernel Instances) use a method that crosses into the Instance's network namespace. Tap attachments (general-purpose Instances) need the plain method. That choice was stored once per VPC per node, so the last attachment to register decided it for every attachment in the VPC. When a veth registered after a tap, the kernel silently discarded every packet sent to the tap. The staging outage on eris-giune in VPC b followed exactly that order.

Fix

  • The redirect choice now belongs to each attachment's host-side interface. It is recorded when the attachment is added, removed when it is deleted, and verified by the CNI CHECK operation.
  • The choice lives in a new datapath map. No existing map changes layout, so rolling this out does not force the loader to recreate maps and wipe live routing state.
  • An interface with no entry uses the plain redirect method. This covers attachments added before this change and any upgrade window before the new map is pinned. According to the kernel source, a plain redirect into a veth's host-side end is forwarded into the peer namespace, so it delivers to both kinds. The only cost is skipping the peer method's faster path. A test confirms this against a real kernel.
  • During an upgrade, CNI ADD runs with the new CNI binary before the new datapath is loaded. In that window, ADD logs a missing map instead of failing, so Instances keep starting during the rollout.

Testing

A new datapath test sends real SRv6 frames through the program into tap and veth devices. Against the current main datapath, it reproduces the outage: the tap attachment is black-holed when the veth registers last. With this change, both attachments receive traffic in both registration orders, each through the expected redirect method. Other tests cover the no-entry fallback, deletion of one attachment's entry, and loading a pin set from the previous build without losing routing state.

Related

🤖 Generated with Claude Code

Inbound SRv6 traffic chose its redirect helper from a value shared by every
attachment in a VPC on a node, so whichever attachment type registered last
decided delivery for all of them. A general-purpose Instance (tap) sharing a
VPC and node with a unikernel Instance (veth) was silently black-holed once
the veth attached.

The redirect choice now comes from a new per-interface map keyed by the
resolved egress interface, written at CNI ADD, removed at DEL, and verified
by CHECK. Existing pinned maps keep their layout, so a rollout does not wipe
routing state. An interface without an entry uses plain bpf_redirect, which
delivers to taps and, through the host-side veth's transmit path, into a
veth's peer namespace.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@scotwells
scotwells requested a review from a team as a code owner September 13, 2026 01:55
@scotwells
scotwells requested review from ecv and privateip September 13, 2026 01:55
@scotwells
scotwells merged commit c0f7628 into main Sep 13, 2026
12 checks passed
@scotwells
scotwells deleted the fix/usid-per-interface-egress-kind branch September 13, 2026 02:25
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