Update (2019/01/10): This post explains how to build a kernel with AF_XDP support (rather than XDP support). XDP support in the kernel is made available through CONFIG_BPF_SYSCALL. XDP is shipped in the kernel since v4.8, and it’s usually enabled by default. AF_XDP is a new socket address family that relies on XDP to pass a packet from kernel-space directly to user-space using zero-copy. Thanks to Quentin Monet for the correction.

This post is the first one of a series about XDP (eXpress Data Path), the brand-new kernel component for doing fast packet processing.

Lately I’ve been in the quest of adding XDP support in Snabb. This work was actually started by one of our Coding Experience students, Konrad Djimeli. Unfortunately Konrad had to leave before completing his Coding Experience, so I picked up his work and finished it. The posts ahead are an attempt to summarize my findings about XDP. In this one, I explain how to get a kernel ready for starting with XDP.

Building a kernel with XDP support is simply a matter of enabling that feature in the kernel’s .config file (CONFIG_XDP_SOCKETS=y). If you’re familiar with building kernels and installing them, you’re done. Besides enabling this option, there’s nothing else you need to do.

However, if you’re not familiar with the process of building a kernel, a recap might be handy. In my case, it was ages since the last time I built a kernel. Here some instructions:

First things first, fetch the Linux kernel source code:

$ git clone https://github.com/torvalds/linux.git 

You can chose whether to build master or any of the latest kernel releases. In my case, I went with v4.19:

$ git checkout v4.19 -b v4.19

Now you should run make menuconfig and pick the features you’d like to build in your kernel. Once you’re done, a configuration file with the selected options will be written in .config. However, there’s an easier way if what you really need is a .config file to start with. Simply copy the configuration file of some other kernel in your system (each kernel in /boot has its corresponding .config file).

$ uname -r
4.15.0-43-generic
$ cp /boot/config-4.15.0-43-generic ./.config

Edit .config and add XDP support:

CONFIG_XDP_SOCKETS=y

And we start building now:

$ sudo make -j4 && sudo make modules_install INSTALL_MOD_STRIP=1

That’s very standard, except for INSTALL_MOD_STRIP. What’s that for? Once the kernel is built, in some cases the initrd image is so big it doesn’t fit in /boot. If you have trouble with that, simply remove the table symbols of the binary to make it smaller. That’s what INSTALL_MOD_STRIP does. The size of initrd will be considerably reduced, likely fitting in /boot.

Lastly, run make install to actually install your kernel. That command also updates Grub, so no need to run it manually.

$ sudo make install

Optionally, run make headers_install if you plan to use the kernel’s header files from an user-space program.

Regarding the brand new kernel, it’s recommended to not make it your default kernel until you’ve verified it works. Once you’ve checked that, make it the default by following these steps:

  • List Grub’s menu entries by running the following command: grep -i "menuentry_id_option" /boot/grub/grub.cfg. The literal after menuentry_id_option is the kernel’s identifier. For instance, gnulinux-4.19.0-advanced-886d53cd-5893-4e51-ac10-2282e653e0b9.
  • Edit /etc/default/grub and set GRUB_DEFAULT to the kernel’s identifier. In my case, GRUB_DEFAULT=gnulinux-4.19.0-advanced-886d53cd-5893-4e51-ac10-2282e653e0b9.
  • Run sudo update-grub, to apply the changes.

We are ready now to use XDP to process packets. But how to do that will be the subject of a new post.