Free — no signup required

How XDP Works: Actions and Verdicts

3 min read

The Traffic Cop at the City Gate

An XDP program is a C function that receives a pointer to the packet context (struct xdp_md) and returns one of four verdict codes. Think of it as a traffic cop standing at the city gate — every vehicle (packet) must pass the cop before entering the city (kernel stack), and the cop can wave it through, turn it around, redirect it, or simply destroy it.

The Four XDP Verdicts:

1. XDP_DROP — "Trash it immediately."
The packet is discarded at the driver level. No memory is allocated. No CPU cycles are spent on further processing. This is the fastest possible outcome.
- Use case: DDoS mitigation. Cloudflare uses XDP to drop hundreds of millions of malicious packets per second with negligible CPU impact. A volumetric UDP flood that would saturate a server's CPU through normal kernel processing becomes trivial to absorb.

2. XDP_TX — "Send it back out the same interface."
The packet is immediately retransmitted on the same NIC it arrived on, potentially after modification.
- Use case: Implementing a load balancer that receives a packet, rewrites the destination MAC address, and hairpins it back out. Facebook's Katran load balancer uses this pattern.

3. XDP_REDIRECT — "Send it somewhere else."
The packet is redirected to a different NIC, a different CPU core's queue, or directly into a user-space application via an AF_XDP socket (a zero-copy socket type designed specifically for XDP).
- Use case: Advanced packet forwarding between interfaces, or delivering raw packets to a user-space application (like a custom DPDK-style app) without the full kernel stack overhead.

4. XDP_PASS — "I don't care. Let the kernel handle it."
The packet proceeds up the normal Linux networking stack, gets its sk_buff, and is processed by iptables, routing, and eventually a standard socket. This is the default for any traffic your XDP program doesn't need to intercept.
- Use case: SSH traffic, HTTP requests to Nginx, DNS responses — anything that should be handled by standard Linux applications.

XDP_PASS is the architectural superpower. It means you can deploy XDP selectively. Your XDP program drops attack traffic at line rate while simultaneously passing legitimate traffic to a completely unmodified Nginx or PostgreSQL instance. DPDK cannot do this — it's all or nothing.

eBPF Maps: Sharing State

XDP programs are stateless by themselves, but they can read from and write to eBPF maps — key-value data structures shared between the XDP program and user space. This is how you make XDP programs dynamic:

  • A user-space control plane updates a map with a blocklist of IP addresses.
  • The XDP program reads the map on every packet and drops matching IPs.
  • No kernel recompilation. No service restart. The update takes effect in microseconds.

Common map types used with XDP:
- BPF_MAP_TYPE_HASH — IP blocklists, connection tracking tables.
- BPF_MAP_TYPE_ARRAY — Counters, statistics per CPU core.
- BPF_MAP_TYPE_LPM_TRIE — Longest-prefix match for CIDR-based routing rules.

Interview Tip

Interviewers frequently ask: "How do you update an XDP firewall rule without restarting the program?" The answer is eBPF maps. The XDP program is loaded once and runs continuously. A separate user-space process (your control plane) updates a BPF_MAP_TYPE_HASH map containing blocked IPs. The XDP program performs a map lookup on every packet — if the source IP is in the map, it returns XDP_DROP. This decouples the data plane (XDP program) from the control plane (your management process), which is the same architectural principle used in SDN.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free