XDP: High-Performance Packet Processing

Khimananda Oli 8 min read Virtualization
XDP: High-Performance Packet Processing

By Khimananda Oli | Last reviewed: August 2026

When standard Linux networking stacks buckle under multi-gigabit traffic or sophisticated DDoS attacks, XDP: High-Performance Packet Processing provides a programmable escape hatch directly inside the network driver. Unlike traditional firewalling that inspects packets after significant kernel overhead, XDP executes eBPF bytecode at the earliest possible point in the ingress path. This capability allows you to drop, redirect, or modify millions of packets per second per core while maintaining full compatibility with existing observability tools like those discussed in our Prometheus metrics monitoring fundamentals guide.

What is XDP: High-Performance Packet Processing and how does it work?

XDP (eXpress Data Path) is not a separate product; it is a hook point within the Linux kernel's network receive path. When a network interface card (NIC) receives a frame via DMA, the kernel typically allocates an sk_buff structure and pushes the packet up through the netfilter, TCP/IP stack, and socket layers. XDP intercepts this flow immediately after the driver reads the descriptor ring but before any expensive metadata allocation occurs.

The mechanism relies on eBPF (extended Berkeley Packet Filter), a virtual machine inside the kernel that guarantees safety through static verification. Your C code compiles to eBPF bytecode, which the verifier checks for infinite loops, out-of-bounds memory access, and invalid instructions. Once verified, the program attaches to the XDP hook. Because this execution happens in the softirq context of the NIC driver, it avoids context switches and cache pollution associated with higher-layer processing.

NIC HardwareXDP Hook(eBPF Program)XDP_DROPKernel StackXDP_REDIRECTDecisions made before sk_buff allocation
XDP: High-Performance Packet Processing intercepts traffic at the NIC driver, enabling drop, pass, or redirect actions before kernel overhead.

In practice, this architecture means you can achieve drop rates exceeding 20 million packets per second (Mpps) on modern hardware, whereas iptables might saturate at 1–2 Mpps on the same CPU. For teams managing infrastructure in Nepal where upstream bandwidth can be expensive and asymmetric, stopping malicious traffic at the edge interface before it consumes routing resources is often the difference between uptime and outage.

How do you write and attach an XDP program safely?

Writing XDP programs requires discipline. The eBPF verifier is strict: no unbounded loops, no pointer arithmetic outside packet bounds, and limited stack usage (512 bytes). Most engineers use the libbpf CO-RE (Compile Once – Run Everywhere) approach with BTF (BPF Type Format) to handle kernel structure differences across versions.

Minimal XDP filter example

This program drops all UDP traffic on port 53 while passing everything else. Note the explicit bounds checking required by the verifier.

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/udp.h>

SEC("xdp")
int xdp_dns_filter(struct xdp_md *ctx) {
    void *data_end = (void *)(long)ctx->data_end;
    void *data     = (void *)(long)ctx->data;

    struct ethhdr *eth = data;
    if ((void *)(eth + 1) > data_end)
        return XDP_PASS;

    if (eth->h_proto != __constant_htons(ETH_P_IP))
        return XDP_PASS;

    struct iphdr *ip = (struct iphdr *)(eth + 1);
    if ((void *)(ip + 1) > data_end)
        return XDP_PASS;

    if (ip->protocol != IPPROTO_UDP)
        return XDP_PASS;

    struct udphdr *udp = (struct udphdr *)((void *)ip + sizeof(*ip));
    if ((void *)(udp + 1) > data_end)
        return XDP_PASS;

    if (udp->dest == __constant_htons(53))
        return XDP_DROP;

    return XDP_PASS;
}

char _license[] SEC("license") = "GPL";

Loading and attaching the program

Never load XDP programs manually in production without testing. Use bpftool or a loader built with libbpf:

  1. Compile with clang: clang -O2 -g -target bpf -c xdp_filter.c -o xdp_filter.o
  2. Verify BTF support: cat /sys/kernel/btf/vmlinux must exist for CO-RE.
  3. Attach to interface: bpftool prog load xdp_filter.o /sys/fs/bpf/xdp_dns type xdp pin /sys/fs/bpf/xdp_dns
  4. Link to device: bpftool net attach xdp pinned /sys/fs/bpf/xdp_dns dev eth0
  5. Verify attachment: ip link show eth0 should display xdp/id:XXX.

A common mistake is forgetting to handle VLAN tags or IPv6. If your production environment uses 802.1Q tagging, your parser must account for the extra 4-byte header or you will misparse every packet. Always test with xdp-bench from the kernel samples before deploying to live interfaces.

XDP vs iptables vs DPDK: Which packet processing approach should you choose?

Choosing the right tool depends on your throughput requirements, operational complexity tolerance, and whether you need kernel integration. I have seen teams adopt DPDK when XDP would have sufficed, resulting in months of unnecessary maintenance burden. Conversely, I have seen iptables configurations that caused packet loss during legitimate traffic spikes because the team underestimated netfilter overhead.

CriteriaXDPiptables/nftablesDPDK
Max throughput (single core)10–25+ Mpps0.5–2 MppsLine-rate (hardware dependent)
Kernel integrationNative (shares stack)NativeBypasses kernel entirely
Development complexityModerate (C/eBPF)Low (declarative rules)High (userspace drivers)
Safety guaranteesVerifier-enforcedKernel module risksUserspace bugs possible
NIC compatibilityDriver-dependentUniversalPMD-specific
Best use caseDDoS, LB, telemetryHost firewall, NATTelco, HFT, dedicated appliances

For most DevOps and SRE teams, XDP offers the optimal balance. It integrates with your existing Cilium eBPF networking for Kubernetes deployments, works alongside systemd and netplan, and doesn't require dedicating entire CPU cores exclusively to polling. Reserve DPDK for scenarios where you are building a dedicated network appliance and can afford to bypass the kernel entirely.

How do you debug and monitor XDP programs in production?

Observability is non-negotiable for XDP. A buggy program can silently drop legitimate traffic or fail open. You cannot rely on tcpdump alone because XDP actions occur before the packet reaches the capture point.

XDP Program(NIC Driver)BPF MapsPerf/Ring BufferTracepointsbpftool / GrafanaCounters & MetricsLog AggregatorSampled Packets
Production XDP observability relies on BPF maps for counters, ring buffers for sampled events, and integration with external monitoring stacks.

Use BPF maps to maintain per-CPU counters for dropped, passed, and redirected packets. Export these via a userspace exporter to Prometheus. For detailed debugging, use ring buffers (preferred over perf buffers in 2026 due to better memory efficiency) to send sampled packet headers to userspace. Always implement a kill switch: attach a secondary XDP program or use bpftool net detach as part of your incident response runbook.

When integrating with broader observability, ensure your XDP metrics align with your SLIs. If you define availability based on successful request processing, your XDP drop counter must distinguish between malicious traffic and legitimate requests. Misclassifying these leads to misleading error budgets. Refer to our guide on defining meaningful SLIs and SLOs for patterns that apply equally to eBPF-based infrastructure.

What are the practical limitations and security considerations of XDP?

XDP is powerful but constrained. Understanding these limits prevents production incidents:

  • Driver support: Not all NIC drivers implement XDP natively. Generic XDP (SKB mode) works universally but loses the performance advantage. Check ethtool -i eth0 and consult the kernel documentation for your specific driver version.
  • Packet modification: You can adjust headers using bpf_xdp_adjust_head, but growing the packet beyond the original buffer size is impossible. Encapsulation protocols that add significant headers may require TC-layer eBPF instead.
  • No stateful inspection: XDP operates statelessly per packet. Connection tracking requires maintaining state in BPF maps, which has memory and concurrency limits. For complex stateful logic, combine XDP (for fast-path filtering) with TC or netfilter (for stateful fallback).
  • Verifier complexity: As programs grow, verification time increases exponentially. Use bounded loops (#pragma unroll) and helper functions judiciously. Kernel 6.x improved verifier intelligence, but complex parsers still hit instruction limits.

Security-wise, treat XDP programs like kernel modules. Only load signed, verified bytecode. Restrict CAP_BPF and CAP_NET_ADMIN capabilities. Audit map contents regularly—an attacker who compromises your loader could inject malicious filtering rules. In regulated environments, document XDP behavior as part of your compliance evidence, just as you would for any security control.

Implementing XDP: High-Performance Packet Processing in your infrastructure

XDP: High-Performance Packet Processing transforms Linux from a general-purpose OS into a programmable dataplane capable of handling modern traffic volumes without specialized hardware. Start small: implement basic rate limiting or protocol filtering on a non-critical interface, measure the impact with proper observability, and iterate. Avoid premature optimization—if iptables handles your current load with headroom, XDP adds complexity you don't yet need.

When you do adopt it, integrate XDP into your existing GitOps and CI/CD workflows. Store eBPF source in version control, automate compilation and verification in your pipeline, and deploy via configuration management. The goal is reproducible, auditable network behavior—not ad-hoc scripts loaded manually at 2 AM during an incident.

If your team needs help designing eBPF-based networking, auditing existing XDP deployments, or integrating high-performance packet processing with your compliance requirements, reach out to discuss your infrastructure challenges. Production-grade XDP requires careful planning, but the payoff in resilience and performance is substantial.

Frequently Asked Questions

XDP is an eBPF-based Linux framework allowing programmable packet processing at the earliest NIC driver hook. It enables filtering, forwarding, or dropping packets before kernel networking stack allocation, achieving multi-million PPS throughput with minimal CPU overhead on modern kernels like 6.12 LTS.

Yes, XDP runs inside the kernel using safe eBPF bytecode while DPDK uses userspace polling and dedicated cores.

Native XDP requires specific driver hooks. Intel ice, mlx5_core, bnxt_en, and igc drivers currently offer full native support. Check ethtool output for xdp-features flag to verify hardware offload capabilities before deploying production XDP programs on your infrastructure.

No, XDP operates below socket layer so it cannot inspect established TCP connections or application payload.

Compile BPF C code with clang, verify using bpftool prog load, then attach via ip link set dev eth0 xdp obj prog.o sec xdp. Always test in SKB mode first, validate return codes, and maintain a fallback path to prevent accidental network isolation during deployment.

Programs must return XDP_PASS, XDP_DROP, XDP_TX, XDP_REDIRECT, or XDP_ABORTED. Returning invalid values causes packet drops and kernel warnings. Use libbpf helpers to ensure correct enum usage and always handle error paths explicitly to avoid silent failures in high-throughput environments.

Some SmartNICs like NVIDIA BlueField and Netronome NFP support XDP offload where eBPF logic executes directly on NIC firmware. This eliminates host CPU involvement entirely but requires vendor-specific toolchains and limited instruction sets compared to standard kernel XDP execution modes.

Enable bpf_trace_printk or use perf_event_output to emit custom metrics from XDP context. Monitor /sys/fs/bpf/maps for counter increments, check dmesg for verifier errors, and validate map pinning persistence across reloads to isolate logic bugs versus infrastructure misconfigurations.

Yes, XDP_REDIRECT supports both single-port and cpumap redirection. Use BPF_MAP_TYPE_DEVMAP for interface-to-interface forwarding or BPF_MAP_TYPE_CPUMAP for CPU-affinity distribution. Ensure target devices have compatible MTU and queue configurations to prevent silent drops during cross-interface traffic steering.

Absolutely, XDP excels at volumetric attack filtering by dropping malicious packets before memory allocation. Deploy rate-limiting maps, SYN cookie validation, and geo-blocking logic directly in XDP to absorb multi-Gbps attacks while preserving legitimate traffic flow through the standard kernel networking stack.

Kernel 4.18 introduced basic XDP stability but 5.15 LTS added critical improvements including bpf_link attachment, better map types, and enhanced verifier safety. For 2026 deployments targeting production environments, use 6.12 LTS which includes latest redirect optimizations and comprehensive driver support matrices.

XDP executes before netfilter so dropped packets never reach iptables chains. Packets returning XDP_PASS continue through normal netfilter processing. Coordinate rule ordering carefully since XDP drops are invisible to conntrack, potentially breaking stateful firewall expectations if not designed holistically.

Yes, use atomic program replacement via bpftool prog attach with BPF_F_REPLACE flag. Pin maps to preserve state across updates and validate new program behavior in shadow mode before cutover. Never detach then reattach as this creates brief unfiltered windows vulnerable to burst traffic.

Expect 10-30 MPPS per core on 25GbE NICs with simple drop logic. Complex parsing reduces throughput proportionally. Measure using xdp-bench tool rather than synthetic tests, account for PCIe bandwidth limits, and baseline against SKB mode to quantify native driver acceleration benefits accurately.

XDP programs run with elevated privileges and can cause complete network outages if buggy. The eBPF verifier prevents unsafe memory access but logic errors remain possible. Restrict loading to root or CAP_BPF users, audit all programs pre-deployment, and implement monitoring to detect anomalous drop rates immediately.