Skip to content

fix(agent): capture ScaleToZero wake frames in the runtime host netns - #106

Merged
syscod3 merged 1 commit into
mainfrom
fix/scaletozero-wake-runtime-netns
Sep 24, 2026
Merged

syscod3 merged 1 commit into
mainfrom
fix/scaletozero-wake-runtime-netns

Conversation

@syscod3

@syscod3 syscod3 commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

Problem

The nightly datapath E2E has failed every night since 2026-08-29. The wake-on-traffic hook opened its AF_PACKET socket inside the agent pod, but the impbr-* bridges and VM TAPs live in the host network namespace (owned by the runtime DaemonSet, hostNetwork: true). A pod-side socket can never see bridged overlay traffic — CI logs prove it: framesSeen increments while lastDstIP is always 10.244.x/10.96.x/127.0.0.1, never the target VM's 10.45.0.x. The wake frame is sent, never observed, the VM never wakes, the test times out.

This is the same class of bug as #99 (TAP stats read from the wrong namespace), which moved stats to the runtime RPC. The wake capture was left behind.

Fix

Mirror the #99 pattern — capture on the runtime, consume via RPC:

  • runtimeapi: WakeHits backend method + RPC — drains destination IPs observed on the host since the previous call.
  • noderuntime: host-netns AF_PACKET capture (ETH_P_ALL — the ptype_all/br_handle_frame analysis is preserved; IPv4 filtered in userspace). Capture starts lazily on first poll and lives for the process lifetime.
  • agent: NewLinuxScaleToZeroWithRuntime now wires a runtimeWakeSource that polls WakeHits at interval/2 (wake registers well inside the 2-minute E2E resume window) instead of opening a pod-side socket.

Verification

  • New unit test (linux): pod-traffic-only poll must NOT signal the wake registry; the poll carrying 10.45.0.3 must signal it. Passes.
  • go build on linux and darwin; golangci-lint clean on the touched packages (no new issues vs main baseline).
  • Full go test ./internal/agent/ hits a pre-existing envtest/etcd sandbox failure identically on clean main; CI is the gate there.
  • After merge: nightly datapath should go green (wake path exercised end-to-end with real Firecracker + KVM).

The wake-on-traffic hook opened its AF_PACKET socket inside the agent pod.
The impbr-* bridges and VM TAPs live in the host network namespace (owned
by the runtime DaemonSet, hostNetwork: true), so the pod-side socket only
ever saw pod traffic (loopback, pod veths, Service IPs) — never the
overlay frames a suspended ScaleToZero VM must be woken by. The nightly
datapath E2E failure streak since 2026-08-29 shows it directly: framesSeen
increments while lastDstIP is always 10.244.x/10.96.x/127.0.0.1, never the
target VM's 10.45.0.x.

Mirror the PR #99 pattern used for TAP stats: capture on the runtime (host
netns) and expose it over the existing runtime RPC.

- runtimeapi: WakeHits backend method + RPC (drains observed destination IPs)
- noderuntime: host-netns AF_PACKET capture (ETH_P_ALL — preserved the
  ptype_all/br_handle_frame analysis; do not simplify to ETH_P_IP)
- agent: NewLinuxScaleToZeroWithRuntime now wires a runtimeWakeSource that
  polls WakeHits at interval/2 instead of opening a pod-side socket
@syscod3
syscod3 merged commit f5e1087 into main Sep 24, 2026
16 checks passed
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.

1 participant