IXDP - A libxdp wrapper API for zero-copy high speed packet processing applications
January 29, 2025
Motivation #
Linux XDP together with eBPF is an unique API which allows to process networking packets in direct communication with the kernel. But there’s some kind of a problem: Its usage, setup and correct handling of the 4 rings per queue and interface is very cumbersome and error-prone.
IXDP is an abstraction layer on top of libxdp which makes implementing networking applications very easy and clear. Its properties are:
- No specific eBPF programming (the default libxdp eBPF program
xsk_def_xdp_prog.c
is automatically in place by libxdp). - interfaces are setup in promiscuous mode and taken completely out of their connection to the Linux IP stack.
- zero-copy operation only (suitable devices and drivers required).
- additional ability to copy packets or to inject arbitrary packets for delivery to the cable on a specific interface.
AF_XDP #
AF_XDP is a raw socket optimized for high performance packet processing and allows zero-copy between kernel and applications. As the socket can be used for both receiving and transmitting, it supports high performance network applications purely in user space.
libxdp #
libxdp is a lightweight library that allows attaching multiple XDP programs to network interfaces and using AF_XDP sockets. It basically exists to faciliate usage and control of the underlying AF_XDP sockets.
IXDP #
IXDP is an API wrapper from Inlab Networks on top of libxdp encapsulating all initialisation and ring processing.
The IXDP packet processing core functions are:
IXDPSetup() #
This function prepares one or multiple NICs for zero-copy packet processing.
The pramaters are:
ifc
interface countifv
an array of ifc interface/NIC namesnqueues
the number of queues to prepare (this equals the number of threads started byIXDPStart(a)
ringsize
the individual size of the RX and TX ring (recommended to use the pre-set maximum as the driver reports)
The function declaration is this:
|
|
IXDPStart() #
This function starts the processing theads, exactly one for each configured queue as specified
at IXDPSetup()
. This has been separated from IXDPSetup()
to allow additional actions in
between (like daemonizing or other initialisation tasks).
|
|
IXDPCallback() #
IXDPCallback() implements the packet processing application (as an unresolved external symbol/function within ixdp.c).
It needs to be fully reentrant since it is executed in parallel by multiple queue processing threads..
During its execution the executing thread is in possession of the packet contents, can modify the contents (located at address) and can extend or shrink the length of the packet by modifying it directly through the provided length_ptr.
The interface parameter contains the interface index where the packet has been received.
If IXDPCallback() returns -1, the packet is dropped - returning a valid interface index results in passing it to the TX ring of this interface (and queue).
The function declaration looks like this:
|
|
IXDPEnqueue() #
This function enqueues an arbitrary packet for transmission on the specified interface (index) as a copy. Calling it from within IXDPCallback() is perfectly valid.
|
|
A simple Bridge #
The following example implements a trivial packet forwarding bridge with one single processing thread:
|
|