Guides

eBPF XDP

eBPF XDP: The Basics and a Quick Tutorial

What is eBPF XDP?

eBPF is an extended version of the Berkeley Packet Filter (BPF). It is an abstract virtual machine (VM) that runs within the Linux kernel, much like the Java Virtual Machine (JVM) can run applications in a controlled environment. eBPF can execute user-defined programs inside a sandbox in the kernel—it is typically used to enable developers to write low-level monitoring, tracing, or networking programs in Linux in a way that ensures optimal performance.

eXpress Data Path (XDP) is a framework that makes it possible to perform high-speed packet processing within BPF applications. To enable faster response to network operations, XDP runs a BPF program as soon as possible, usually immediately as a packet is received by the network interface.

In this article, you will learn:

The Need for XDP in eBPF

XDP is a technology that allows developers to attach eBPF programs to low-level hooks, implemented by network device drivers in the Linux kernel, as well as generic hooks that run after the device driver.

XDP can be used to achieve high-performance packet processing in an eBPF architecture, primarily using kernel bypass. This greatly reduces the overhead needed for the kernel, because it does not need to process context switches, network layer processing, interrupts, and so on. Control of the network interface card (NIC) is transferred to an eBPF program. This is especially important if you are working at higher network speeds—10 Gbps and above.

However, the kernel bypass method has some drawbacks:

  • eBPF programs have to write their own drivers. This creates extra work for developers.
  • XDP programs run before packets are parsed. This means that eBPF programs must directly implement functionality they need to do their job, without relying on the kernel.

These limitations created the need for XDP. XDP makes it easier to implement high-performance networking in eBPF, by allowing eBPF programs to directly read and write network packet data, and determine how to process the packets, before reaching the kernel level.

How XDP Works

XDP programs can be directly attached to a network interface. Whenever a new packet is received on the network interface, XDP programs receive a callback, and can perform operations on the packet very quickly.

You can connect an XDP program to an interface using the following models:

  • Generic XDP – XDP programs are loaded into the kernel as part of the ordinary network path. This does not provide full performance benefits, but is an easy way to test XDP programs or run them on generic hardware that does not provide specific support for XDP.
  • Native XDP – The XDP program is loaded by the network card driver as part of its initial receive path. This also requires support from the network card driver.
  • Offloaded XDP – The XDP program loads directly on the NIC, and executes without using the CPU. This requires support from the network interface device.

Here are some of the operations an XDP program can perform with the packets it receives, once it is connected to a network interface:

  • XDP_DROP – Drops and does not process the packet. eBPF programs can analyze traffic patterns and use filters to update the XDP application in real time to drop specific types of packets (for example, malicious traffic).
  • XDP_PASS – Indicates that the packet should be forwarded to the normal network stack for further processing. The XDP program can modify the content of the package before this happens.
  • XDP_TX – Forwards the packet (which may have been modified) to the same network interface that received it.
  • XDP_REDIRECT – Bypasses the normal network stack and redirects the packet via another NIC to the network.

Use Cases for XDP

Here are a few common use cases for XDP in eBPF.

DDoS Mitigation and Firewalling

One of the basic functions of XDP in eBPF is to use XDP_DROP, which tells the driver to drop packets at an early stage. This lets you apply a variety of efficient network strategies, while keeping the cost of each packet very low.

This is great for situations where you need to deal with any type of DDoS attack, but more generally, using XDP, eBPF can implement any type of firewall policy with very little overhead. XDP can handle these scenarios, for example, by scrubbing illegitimate traffic and forwarding legitimate packets to their destination using XDP_TX.

XDP can either be deployed in a standalone network appliance, or distributed to multiple nodes that protect the host. The latter scenario can be implemented using XDP_PASS or cpumap XDP_REDIRECT. To boost performance, you can use offloaded XDP, which shifts the already small cost of each data packet entirely to the NIC, which is processed at wire speed.

Forwarding and Load Balancing

Another major use case for XDP is the use of XDP_TX or XDP_REDIRECT operations for packet forwarding and load balancing. Data packets can be manipulated by BPF programs running on the XDP layer. BPF helpers—functions used by BPF programs to interact with the system or with the context in which they operate—can be used to increase or decrease the headroom of data packets, to encapsulate and decapsulate data packets before sending them back.

There are two common ways to implement a load balancer:

  • You can use XDP_TX to forward packets using the same NIC by which it was received
  • You can use XDP_REDIRECT to forward packets to a different network interface

Monitoring and Flow Sampling

XDP is commonly used for packet monitoring, sampling, and other forms of network analysis. It can be used, for example, to monitor traffic on an intermediate node in the path of an end host, or in conjunction with any of the above use cases.

For complex packet analysis, XDP maps network packets (either truncated or full payloads) and custom metadata to eBPF programs. This can also support situations where only initial data in the flow is analyzed, and then bypasses monitoring when it determines the traffic is legitimate.

The flexibility provided by BPF with XDP lets you implement any type of custom monitoring or sampling.

Quick Tutorial: Running Your First XDP Program

This section is abbreviated from the full tutorial by Hangbin Liu of Red Hat.

 

Step 1: Install development environment

Install the required packages using the following code:

$ sudo dnf install clang llvm gcc libbpf libbpf-devel libxdp libxdp-devel xdp-tools bpftool kernel-headers

 

Step 2: Write a simple XDP program

The following C program uses the xdp_drop command to drop all data packets.

Including the linux/bpf.h header provides access to XDP commands. The SEC macro places part of the compiled object in a specific section within the Executable and Linkable Format (ELF) file.

 

Step 3: Build the eBPF program

You can use the clang utility to build the program, as follows:

$ clang -O2 -g -Wall -target bpf -c xdp_drop.c -o xdp_drop.o

You can use the command llvm-objdump to show the ELF code generated by the clang command. The -h flag lets you show all sections in the object.

 

Step 4: Load the BPF program

Before proceeding, it is important to use Linux veth (Virtual Ethernet Device) for testing. The test program drops all packets, so if you run it on your default interface, you will lose connectivity.

You can load the BPF object like this:

$ sudo ip link set veth1 xdpgeneric obj xdp_drop.o sec xdp_drop

However, this method does not support type maps (using the BTF format), which are needed for more advanced operations. To enable it, you can use the xdp-loader utility.

Here is how to load the object on a veth interface with xdp-loader. The -m sbk flag is used for generic XDP loading, which does not require a compliant hardware device.

$ sudo xdp-loader load -m skb -s xdp_drop veth1 xdp_drop.o

 

Step 5: Display status for running BPF programs

Depending on how you ran the BPF object, there will be either one program running (if you used the ip command) or two programs (if you used xdp-loader, which runs both the loader utility itself and your custom program).

Here is how to show running BPF programs and activity on your virtual ethernet interface.

The xdp-loader utility has its own status command that can show XDP programs currently running.

 

Step 6: Unload the XDP program

If you loaded the program using ip command, unload it like this. Note you should use the same flags you used when loading the program.

$ sudo ip link set veth1 xdpgeneric off

If you used xdp-loader, to unload XDP programs, use this command:

$ sudo xdp-loader unload -a veth1

 

Step 7: Perform more advanced actions

Now that you understand how to create and load a minimal XDP program, see the code below, which analyzes traffic and drops only IPv6 packets.

Calico eBPF Data Plane

Calico offers support for multiple data planes, including standard Linux, Windows HNS, and Linux eBPF. Compared to the standard Linux networking data plane, Calico’s eBPF data plane scales to higher throughput, uses less CPU per GBit, and has native support for Kubernetes services (without needing kube-proxy).

The data plane’s native support for Kubernetes services achieves the following:

  • Reduces first packet latency for packets to services
  • Preserves external client source IP addresses all the way to the pod
  • Supports Direct Server Return (DSR) for more efficient service routing
  • Uses less CPU than kube-proxy to keep the data plane in sync

With Calico, you can easily load and unload the eBPF data plane to suit your needs. Calico offers you the ability to leverage eBPF as needed, as an additional control to build your Kubernetes cluster security.

Beyond the three data planes Calico currently supports, there are plans to add support for even more data planes in the near future, including Vector Packet Processing (VPP). Calico lets the user decide what works best for what they need to do.

 

Next steps:

 

Join our mailing list​

Get updates on blog posts, workshops, certification programs, new releases, and more!