Skip to content

[v3.32] [BPF] Re-wire SetTriggerFn on syncer swap in proxy.SetSyncer#12743

Merged
tomastigera merged 1 commit into
projectcalico:release-v3.32from
tomastigera:auto-pick-of-#12701-upstream-release-v3.32
May 12, 2026
Merged

[v3.32] [BPF] Re-wire SetTriggerFn on syncer swap in proxy.SetSyncer#12743
tomastigera merged 1 commit into
projectcalico:release-v3.32from
tomastigera:auto-pick-of-#12701-upstream-release-v3.32

Conversation

@tomastigera
Copy link
Copy Markdown
Contributor

Description

Cherry-pick of #12701 to release-v3.32. proxy.New() wires the syncer's expand-NodePort fixup callback via dp.SetTriggerFn(p.runner.Run). proxy.SetSyncer() swaps in a fresh syncer (e.g. on a host-IP change inside KubeProxy.run()) but did not re-wire that callback. After any host-IP change the new syncer's expand-NodePort fixup goroutine resolves previously-missed routes for ExternalTrafficPolicy=Local NodePort backends, but cannot schedule the dataplane Apply that would program them — the fix-up is silently lost until something else piggybacks an Apply.

Pre-existing bug (kp.run() always created a fresh syncer and called SetSyncer on it); #12667 made it plain to read because the first call now goes through proxy.New() which sets the trigger, leaving the asymmetry with SetSyncer obvious. Caught on the v3.31 backport review (#12693).

Fix

Have SetSyncer call s.SetTriggerFn(p.runner.Run) on the new syncer, under the same lock as the dpSyncer swap, mirroring proxy.New().

Test

Regression test in proxy_test.go swaps a syncer via SetSyncer, verifies the new syncer received a non-nil trigger callback, and confirms invoking it schedules an Apply. The test fails on master / 3.32 / 3.31 before this change.

Related issues/PRs

Cherry-pick of #12701. Follow-up to #12667; pairs with #12694 (already merged on this branch).

Release Note

ebpf - Fix kube-proxy losing the NodePort externalTrafficPolicy=Local route-fixup trigger after a syncer swap, which could cause stale NAT entries on remote backends.

Reminder for the reviewer

  • release-note-required
  • docs-not-required (no user-facing config change; bug fix)

proxy.New() wires the syncer's expand-NodePort fixup callback to the
proxy's runner via dp.SetTriggerFn(p.runner.Run). proxy.SetSyncer()
swaps in a fresh syncer (e.g. on a host-IP change inside
KubeProxy.run()) but did not re-wire that callback. Result: after any
host-IP change the new syncer's expand-NodePort fixup goroutine
resolves previously-missed routes for ExternalTrafficPolicy=Local
NodePort backends, but cannot schedule the dataplane Apply that would
program them — the fix-up is silently lost until something else
piggybacks an Apply.

Pointed out by review on the v3.31 backport (projectcalico#12693) of projectcalico#12667; the
asymmetry is pre-existing (it was equally broken before projectcalico#12667
restructured run()) but became plain to read after the restructure.

Make SetSyncer call s.SetTriggerFn(p.runner.Run) on the new syncer
under the same lock as the dpSyncer swap, mirroring what proxy.New()
does for the initial syncer.

Add a regression test that swaps a syncer via SetSyncer and verifies
the new syncer received a non-nil trigger callback that schedules an
Apply when invoked. The test fails on master before this change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 12, 2026 16:17
@tomastigera tomastigera requested a review from a team as a code owner May 12, 2026 16:17
@marvin-tigera marvin-tigera added this to the Calico v3.32.1 milestone May 12, 2026
@marvin-tigera marvin-tigera added release-note-required Change has user-facing impact (no matter how small) docs-pr-required Change is not yet documented labels May 12, 2026
@tomastigera tomastigera added the docs-not-required Docs not required for this change label May 12, 2026
@marvin-tigera marvin-tigera removed the docs-pr-required Change is not yet documented label May 12, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes an eBPF kube-proxy regression where swapping the dataplane syncer via proxy.SetSyncer() failed to re-wire the syncer’s “route-fixup” trigger callback, causing NodePort externalTrafficPolicy=Local route-fixups to be unable to schedule a dataplane Apply after host-IP changes.

Changes:

  • Re-wire DPSyncer.SetTriggerFn(p.runner.Run) inside proxy.SetSyncer() under the syncer swap lock, mirroring proxy.New().
  • Add a regression test to validate that a syncer swap re-arms the trigger and that invoking it schedules an Apply.
  • Extend the test mock syncer to record the trigger function passed via SetTriggerFn.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
felix/bpf/proxy/proxy.go Ensures SetSyncer re-wires the new syncer’s trigger callback so route-fixup can schedule Applies after a swap.
felix/bpf/proxy/proxy_test.go Adds regression coverage for trigger wiring on syncer swap and updates the mock syncer to capture the trigger function.

@tomastigera tomastigera merged commit efae0cc into projectcalico:release-v3.32 May 12, 2026
10 checks passed
@tomastigera tomastigera deleted the auto-pick-of-#12701-upstream-release-v3.32 branch May 12, 2026 22:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs-not-required Docs not required for this change release-note-required Change has user-facing impact (no matter how small)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants