XDP (eXpress Data Path)
In plain English
Plain definition
A kernel hook that lets eBPF programs process network packets right at the NIC driver, before the kernel builds its normal packet structures, for extremely fast filtering and forwarding decisions.
XDP attaches an eBPF program directly to a NIC driver’s RX queue callback, executing on the raw xdp_buff structure immediately after DMA completes, prior to the kernel constructing an sk_buff. This positioning is the entire point: sk_buff allocation, GRO/GSO handling, netfilter traversal, and socket demultiplexing are all comparatively expensive, and XDP programs can make a forwarding decision before any of that work happens. A program returns one of a small set of verdicts—XDP_DROP, XDP_PASS, XDP_TX (bounce back out the same interface), XDP_REDIRECT (send to another interface or into an AF_XDP socket), or XDP_ABORTED. Because the program is JIT-compiled eBPF verified for termination and memory safety, it can run in the driver’s NAPI poll loop without risking kernel stability.
There are three distinct operating modes with very different performance envelopes. Native XDP requires explicit driver support (ixgbe, mlx5, i40e, virtio_net, etc.) and runs inside the driver’s poll routine, achieving tens of millions of packets per second per core. Offloaded XDP pushes the program onto SmartNIC hardware entirely, removing host CPU from the path for supported verdicts. Generic XDP is a software fallback that runs the hook later, after sk_buff allocation, for drivers lacking native support—this preserves the API but forfeits nearly all the performance benefit, and is easy to enable accidentally by attaching to an unsupported interface, producing misleading benchmark results.
The dominant production use cases are DDoS mitigation (dropping malicious flows before they consume any further kernel resources), software load balancing (Facebook’s Katran and Cloudflare’s L4 balancer redirect packets via consistent hashing at the XDP layer), and as the accelerated data plane underneath Cilium’s Kubernetes CNI, where XDP handles NodePort/LoadBalancer traffic and DDoS filtering while regular eBPF tc hooks handle the rest of the policy graph. A critical edge case is that XDP operates below the point where iptables/netfilter, tc qdiscs, and even standard socket buffering apply—an XDP_DROP is invisible to tcpdump on the standard capture path unless the program explicitly maintains counters or uses bpf_trace_printk/perf events for observability. Programs also cannot easily access reassembled fragments or perform stateful reassembly cheaply—complex flow tracking requires BPF maps (LRU hash maps, per-CPU arrays) shared with companion tc-layer or userspace programs, and map contention under high packet rates becomes its own tuning problem.
The architectural tradeoff is that XDP trades generality for throughput: it is unsuitable for anything requiring the full stack’s connection tracking, TLS termination, or complex L7 parsing, and pushing too much stateful logic into it reintroduces the verifier complexity and per-packet map lookup costs it was meant to avoid. Teams adopting it must also account for driver support fragmentation, the silent native-vs-generic mode downgrade, and the operational reality that debugging dropped or redirected packets requires BPF-aware tooling (bpftool, bpftrace) rather than conventional network diagnostics.