This episode dissects the Calico eBPF dataplane: kernel prerequisites, advantages such as direct server return and socket-level policy, the eBPF versus iptables and nftables comparison, and when the right time is to enable it.

In episode 3 we briefly touched on dataplane modes. Now it's time to dissect eBPF thoroughly: what really changes in the kernel, the advantages you can actually feel, the cost you pay, and when you should enable it.
eBPF is the main reason some people choose Cilium, but many don't know that Calico also has a very mature eBPF dataplane. By understanding it, you can pick a dataplane based on needs, not prestige.
eBPF requires a modern Linux kernel and the matching configuration:
Kernel 5.3+ for basic features; 5.13+ for the latest features
CONFIG_BPF -> y
CONFIG_BPF_SYSCALL -> y
CONFIG_BPF_JIT -> y
CONFIG_BPF_UNPRIV_DEFAULT_OFF -> y
CONFIG_DEBUG_INFO_BTF -> yBTF (BPF Type Format) is mandatory because Calico uses CO-RE. Check node readiness with the official script before continuing:
curl -LO https://raw.githubusercontent.com/projectcalico/calico/v3.32.1/scripts/check-kernel-config
chmod +x check-kernel-config
./check-kernel-config /boot/config-$(uname -r)Activation is done through Installation, and it automatically disables kube-proxy:
kubectl patch installation default --type merge \
-p '{"spec":{"dataplane":{"type":"BPF"}}}'
kubectl rollout restart ds/kube-proxy -n kube-system
kubectl get tigerastatus | grep -i bpfdataplane.type: BPF replaces iptables with eBPF programs. Because eBPF handles Service load balancing, kube-proxy is scaled to zero or removed.
In iptables mode, traffic returning from a backend pod passes through the same node as the kube-proxy node (the client node), so there's an extra leg. With DSR, responses are sent directly from the backend node to the client — the return path is shorter, latency drops, and the front node's load is lighter.
iptables: client -> node A -> backend node B -> node A -> client
DSR: client -> node A -> backend node B ------------> clienteBPF allows policy to be evaluated when a socket is opened, rather than when a packet passes through. Applications can know the policy result even before sending the first byte, and connections from local processes can be filtered more precisely.
eBPF programs perform Service load balancing at the kernel level with support for L4 and some L7, replacing the long chains of iptables rules.
Feature iptables/nftables eBPF
Kernel compatibility very broad needs 5.3+ and BTF
DSR not available available
Socket policy not available available
Replace kube-proxy no yes
MTU normal slightly smaller
Migration easy needs trainingNot all Calico features were available in eBPF at first; over the versions, almost everything is now supported. What to check: features that interact with kube-proxy, host endpoints, and some encapsulation modes. Always read the release notes (episode 20) before enabling.
kubectl exec -n calico-system ds/calico-node -- calico-node --version
kubectl get ds -n kube-system kube-proxy
kubectl exec -n calico-system ds/calico-node -- sh -c "ls /sys/fs/bpf"A mounted /sys/fs/bpf and an inactive kube-proxy are signs eBPF is running. To confirm the active dataplane, run kubectl get tigerastatus and look at the calico-node component status.
A safe rollout pattern: try it on a staging cluster with synthetic load, compare metrics, then decide:
kubectl get pods -n calico-system -o wide
kubectl exec -n calico-system ds/calico-node -- sh -c \
"curl -s localhost:9091/metrics | grep calico_felix_"Felix metrics (calico_felix_*) from two identical clusters can be compared to measure dataplane overhead.
Episode 17 closes out the eBPF topic: strict kernel prerequisites, the DSR and socket policy advantages, a real comparison with iptables/nftables, and the decision of when to enable it based on team readiness.
Key takeaways:
Next, in episode 18, we cover GitOps and policy as code — managing Installation, IPPool, BGPPeer, and policy as code with Argo CD or Flux, complete with versioning, a review flow, and phased rollout.