[v3.33] [BPF] Keep pre-existing forwarded flows alive when switching to eBPF - #13885
Open
tomastigera wants to merge 1 commit into
Open
Conversation
…-migration-fv [BPF] Keep pre-existing forwarded flows alive when switching to eBPF (cherry picked from commit d803bb9)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Switching the dataplane to eBPF drops pre-existing connections that arrive at a node port and are served by a backend on another node. The connection is silently lost on any node whose filter FORWARD policy is DROP.
A flow that pre-dates eBPF mode is kept alive by the mid-flow fallthrough: the ingress BPF program marks the packet
FALLTHROUGHand lets it into the stack, Linux conntrack applies the translation it already holds, and the next BPF program allows it on theCT_ESTABLISHEDmark. In eBPF mode Felix's FORWARD chain accepts bypass-marked traffic, traffic in fromcali+, and traffic frombpfout.cali, and jumps to the workload dispatch chain for traffic out tocali+. A node port flow with a remote backend enters and leaves on the same host interface, so it matches none of them, collects theCT_ESTABLISHEDmark, falls off the end of the chain and hits the DROP policy. Until the switch it was carried by kube-proxy's own-j KUBE-FORWARDaccept, which Felix deletes as part of its kube-proxy cleanup.INPUT has carried an accept for exactly this since the mechanism was written — the fallthrough was built for host-terminated flows such as the connection to the API server, and FORWARD only ever got the rule that sets the mark for the next program. This adds the matching accept to FORWARD, placed after the to-workload jumps so that workload destinations keep going through the dispatch chain.
FORWARD needs only the accept, not the reject and deny that follow it in INPUT. INPUT is the last word for host-terminated traffic, so it has to decide the unknown-flow case itself. A forwarded packet always meets a further BPF program on the egress interface, and that program already drops a mid-flow packet Linux conntrack does not know:
tc.csetsCALI_ST_SUPPRESS_CT_STATEon the egress miss andcalico_tc_skb_accepted_entrypointreturnsTC_ACT_SHOTfor it even when policy allowed. Denying in FORWARD would pre-empt that decision with less information.Four functional verification specs cover the switch for service traffic, which nothing covered before: a ClusterIP with a local and a remote backend, and a node port with a local and a remote backend. kube-proxy does not run in the FV, so they install the rules it would have written, in the chains Felix deletes on the switch. The node-port-with-remote-backend spec fails without the fix and passes with it.
Release note:
AI assistance: Claude Code wrote the test code, found the root cause, and drafted the fix.