Introduction to XDP

eXpress Data Path (XDP) is a high-performance packet processing feature in the Linux kernel. XDP allows network packets to be processed at the earliest possible point in the kernel, directly in the network driver, before they reach the networking stack. This enables use cases such as DDoS mitigation, load balancing, and custom packet filtering with minimal latency and overhead.

XDP Programs

XDP programs are small, efficient routines written in the eBPF language. These programs define how incoming packets should be handled and are executed in the kernel context, providing very low latency. XDP programs can inspect, modify, or make decisions about each packet, such as whether to drop, pass, or redirect it. They are typically written in C and compiled to eBPF bytecode using tools like clang/LLVM.

Once compiled, XDP programs can be loaded into the kernel and attached to network interfaces. The logic inside the program determines which XDP action is returned for each packet.

A variety of tools and libraries support XDP program development. The clang/LLVM toolchain compiles C code to eBPF bytecode. For loading and managing XDP programs, libbpf provides user-space APIs, while xdp-tools offers utilities like xdp-loader and xdpdump. Additional tools such as bpftool and bcc assist with inspection, management, and rapid prototyping. These resources streamline the development and deployment of XDP programs.

XDP Actions

When an XDP program processes a packet, it returns an action code that determines what happens to the packet. The most common actions are:

XDP_PASS

The XDP_PASS action allows the packet to continue through the normal Linux networking stack. Use this when you want to let the packet be processed as usual.

XDP_DROP

The XDP_DROP action discards the packet immediately. This is useful for filtering unwanted or malicious traffic at a very early stage, reducing system load.

XDP_XMIT

The XDP_XMIT action transmits the packet out of the same network interface it arrived on, bypassing the networking stack. This can be used for advanced forwarding or packet reflection scenarios.

XDP_REDIRECT

The XDP_REDIRECT action forwards the packet to another network interface or to a user-space application via AF_XDP sockets. This is commonly used for load balancing, traffic steering, or high-performance packet capture.

Configuring XDP

To use XDP, you write an eBPF program that defines how packets should be handled. This program can be attached to a network interface using the ip command. The eBPF program can be loaded in different modes, each determining where and how the XDP program is executed:

  • Native Mode (xdpdrv): In this mode, the XDP program is loaded directly into the network driver. This provides the highest performance and lowest latency, as packets are processed as soon as they arrive from the hardware, before entering the kernel networking stack. Native mode requires that the network driver supports XDP.

  • Generic Mode (xdpgeneric): If the network driver does not support native XDP, the program can be loaded in generic mode. Here, XDP runs within the generic networking stack, after the packet has been processed by the driver and converted into a socket buffer.

  • Offload Mode (xdpoffload): In offload mode, the XDP program is loaded onto the network interface card (NIC) itself, provided the hardware and its driver support this feature. This allows packet processing to occur entirely on the NIC, freeing up CPU resources and potentially increasing throughput.

For example, to attach an XDP program to an interface in driver mode using the ip command:

# ip link set dev eth0 xdpdrv obj xdp_prog.o

To detach the XDP program:

# ip link set dev eth0 xdpdrv off

The switch drivers lan966x and lan969x only support the xdpdrv mode.

You need root privileges to load or unload XDP programs. The eBPF program (xdp_prog.o in the example) must be compiled beforehand.

For example eBPF programs and tutorials, see the XDP Tutorial on GitHub.