This work presents a P4 compiler backend targeting XDP, the eXpress Data Path. P4 is a domain-specific language describing how packets are processed by the data plane of a programmable network elements, including network interface cards, appliances, and virtual switches. With P4, programmers focus on defining the protocol parsing, matching, and action executions, instead of the platform-specific language or implementation details.
XDP is designed for users who want programmability as well as performance. XDP allows users to write a C-like packet processing program and loads into the device driver's receiving queue. When the device observes an incoming packet, before hanging the packet to the Linux stack, the user-defined XDP program is triggered to execute against the packet payload, making the decision as early as possible.
We bring together the benefits of the two: P4 and XDP. To get started, first you need to setup the P4-16 compiler, then this project is an extension to the P4-16. To execute the XDP, you need Linux kernel version >= 4.10.0-rc7+ due to some BPF verifier limitations
Please see Dockerfile. There is also a public docker image available as u9012063/p4xdp
$ docker pull u9012063/p4xdp
will pull the latest image. However, the XDP BPF code has dependency on your kernel version. Currently for some complicated cases we require kernel >= 4.10.0-rc7. So a vagrant box is also provided with kernel 4.10.0-rc8.
$ vagrant up $ vagrant ssh ubuntu@ubuntu-xenial:~$ sudo su root@ubuntu-xenial:/home/ubuntu# docker images REPOSITORY TAG IMAGE ID CREATED SIZE u9012063/p4xdp latest 3c77fbbd84e5 41 hours ago 2.469 GB root@ubuntu-xenial:/home/ubuntu# docker run -it -u root --privileged <IMAGE ID>
Will boot this VM, pull the docker image, and you can try p4c-xdp.
First you need to follow the installation guide of P4-16 When you have P4-16 compiler, then add this project as an extension. Assuming you have P4-16 at your dir ~/p4c/, to setup P4C-XDP:
cd ~/p4c/ mkdir extensions cd extensions git clone https://github.com/vmware/p4c-xdp.git
Now that you have cloned p4c-xdp at ~/p4c/extensions/p4c-xdp, the next step is to recompile p4c:
cd ~/p4c/ mkdir -p build cd build/ cmake .. make
This generates a p4c-xdp binary in ~/p4c/build. Next create a soft link to the binary:
cd ~/p4c/extensions/p4c-xdp ln -s ~/p4c/build/p4c-xdp p4c-xdp
And a soft link to the xdp test target and the test runtime:
cd ~/p4c/extensions/p4c-xdp ln -s ~/p4c/backends/ebpf/targets/xdp_target.py xdp_target.py ln -s ~/p4c/backends/ebpf/run-ebpf-test.py run-ebpf-test.py
Now you can run the p4c-xdp tests:
cd ~/p4c/build/ make check-xdp
This will check your llvm and clang version, compile all .p4 files, generate .c files, and load them into the kernel to be checked by the BPF verifier.
XDP: eXpress Data Path
XDP is a packet processing mechanism implemented within the device driver with eBPF. Currently to compile a P4 to C program, uses
# ./p4c-xdp --target xdp -o <output_c_file> <input_p4> ./p4c-xdp --target xdp -o /tmp/xdp1.c xdp1.p4
then you need to compile the xdp1.c to eBPF bytecode, xdp1.o, then loaded into your driver. To compile a single .c file
clang -Wno-unused-value -Wno-pointer-sign \ -Wno-compare-distinct-pointer-types \ -Wno-gnu-variable-sized-type-not-at-end \ -Wno-tautological-compare \ -O2 -emit-llvm -g -c /tmp/xdp1.c -o -| llc -march=bpf -filetype=obj -o /tmp/xdp1.o
Then loaded into driver with XDP support
ip link set dev $DEV xdp obj xdp1.o verb
to unload the XDP object
ip link set dev $DEV xdp off
Please see the tests folder Simply run 'make' will start the build
Related BPF/XDP work
- Dive into BPF: a list of reading material, Quentin Monnet link
- BPF: Next Generation of Programmable Datapath by Thomas Graf, OVS Conf 2016 video
- Fast Programmable Networks & Encapsulated Protocols, David S. Miller, netdev 1.2 video
- Remove the private kernel patch requirement when latest kernel with BPF fixed is ready
- Apply the workaround of BPF_MAX_STACK
- Control plane example using perf_event_output