xsk-core is a hard fork of the original xsk-rs project.
The fork is intended for applications that need a small, predictable AF_XDP
binding. The UMEM and socket APIs remain largely unchanged from xsk-rs, so
existing code can continue to use Umem, Socket, fill queues, completion
queues, receive queues, and transmit queues in the same general way.
The main architectural change is the descriptor model. FrameDesc is intended
to be only a thin Rust layer over libxdp's libxdp_sys::xsk descriptor API.
It carries the same essential descriptor data that is exchanged with the
kernel:
addr: u64— the UMEM offset of the packet data;length: u32— the packet data length; andoptions: u32— descriptor options such as multi-buffer continuation.
FrameDesc does not own packet memory and does not interpret packet contents.
Applications that need packet views, protocol parsing, or headroom management
should provide those concerns at a higher layer.
- Renamed the crate to
xsk-coreand reset its version to0.1.0to mark the fork boundary. - Reworked
FrameDescto use the native AF_XDP field types:u64addresses,u32lengths, andu32options. - Frame headroom is shaped by several cooperating layers—the kernel, NIC
driver, eBPF program, and user-space application—and each layer's
requirements must be respected when using
xsk-core; see headroom.md for a detailed explanation. - Replaced the former two-part
SegmentLengthsrepresentation with the single packet length used byxdp_desc. - Replaced
with_lengths(headroom, data)withwith_length(data)and exposed directaddr(),length(), andoptions()accessors. - Updated RX queue handling to copy descriptor address, length, and options
directly from libxdp without narrowing conversions, and changed completion
queue consumption to return frame addresses directly through
&mut [u64]and&mut u64APIs. - Changed
FillQueueproduction to accept&[u64]frame addresses, with matching single-address and wakeup variants. - Optimized fill and completion queue batches by splitting wrapped rings into at most two contiguous ranges and copying each range in bulk.
- Simplified UMEM frame layout and address calculations around the native descriptor offset model.
- Removed the old high-level UMEM frame data and cursor accessors from the core API. Packet memory access and packet construction belong to the application or protocol layer using this crate.
- Removed integration tests that depended on the removed high-level frame-memory API.
On Linux, xsk-core backs each UMEM with a memfd and maps that file into the
process address space. The original mapping is used by AF_XDP as usual, while
additional mappings can alias the same pages without copying packet data.
This makes it possible for multiple execution environments, such as Wasm
instances, to share one UMEM while keeping their virtual address layouts
independent.
Umem::backing_fd() returns a duplicated raw file descriptor for the backing
memfd. The caller owns the returned descriptor and must close it, or convert
it immediately into an owned descriptor such as std::os::fd::OwnedFd. The
descriptor can be passed to mmap() with MAP_SHARED at another address; the
mapping must cover the same UMEM length and begin at file offset zero.
The file descriptor is only an alternative handle to the existing pages. It
does not create another AF_XDP UMEM registration, and descriptor addresses
remain offsets relative to the original UMEM. The original Umem must remain
alive while aliases are in use, and all mappings must obey the normal AF_XDP
ownership rules described below.
The original project remains the reference for the inherited AF_XDP socket and
UMEM design. This repository deliberately diverges in descriptor and memory
access handling, so code that directly uses SegmentLengths, Umem::data,
Umem::data_mut, Umem::headroom, or the frame cursor API must be adapted to
the new layering.
For AF_XDP background and kernel-level details, see the Linux AF_XDP documentation.
The ownership rules of AF_XDP still apply:
- Do not access a frame after submitting its descriptor to the fill queue or transmit ring until the descriptor is returned through the completion queue or receive ring.
- Do not use a descriptor from one UMEM to access another UMEM.
- Treat descriptor addresses as offsets within the UMEM associated with the descriptor.
cargo build
cargo test --lib
Building and using AF_XDP sockets requires Linux, libxdp, and the appropriate kernel and interface configuration. Operations that create veth pairs or bind AF_XDP sockets may require elevated privileges.
This fork retains the MIT license of the original project. See LICENSE.