XDP (eXpress Data Path) for Go, transpiled, CGo-free.
Can be built without CGo, system libxdp, system libbpf, pkg-config, clang, m4, bpftool, ccgo, or a C compiler.
go.dw1.io/xdp uses generated libxdp code
from the pinned xdp-tools v1.6.3 source and forwards libbpf calls to
go.dw1.io/bpf/abi. It is intended for
Linux XDP control paths, not for hiding the operational risk of XDP. Many calls
require elevated Linux capabilities and can change live packet processing on the
selected interface.
CleanReferences(0) asks
libxdp to clean stale dispatcher references for all interfaces. Pass a positive
ifindex to restrict cleanup.
Generated libxdp support is committed for:
linux/amd64linux/arm64
Unsupported targets fail at compile time with a diagnostic that names
go.dw1.io/bpf/abi as the target matrix source and lists the generated targets.
Install the module in the application that will manage XDP state:
go get go.dw1.io/xdpOpen an object file, attach its XDP program, and detach it when done:
prog, err := xdp.OpenProgramFile("xdp_prog.o", "xdp", xdp.OpenOptions{
KernelLogSize: 64 << 10,
KernelLogLevel: 1,
})
if err != nil {
return err
}
defer prog.Close()
if logText := prog.KernelLog(); logText != "" {
log.Printf("verifier log:\n%s", logText)
}
if err := prog.Attach(ifindex, xdp.AttachModeUnspecified, 0); err != nil {
return err
}
defer func() {
_ = prog.Detach(ifindex, xdp.AttachModeUnspecified, 0)
}()Attach, detach, pin, cleanup, and AF_XDP socket setup calls can require
CAP_BPF, CAP_NET_ADMIN, or root depending on the kernel and distribution.
Use a test interface first.
OpenProgramFile,
FindProgramFile, and
ProgramFromBPFObject
select a program by section name. Use
CreateProgram with
ProgramOptions.ProgramName
when a BPF object should be searched by program name instead.
ProgramOptions rejects
conflicting sources and rejects selectors or open options that libxdp would not
apply to the chosen source.
OpenOptions.KernelLogSize and
OpenOptions.KernelLogLevel
request libbpf verifier/BTF logging for file-backed program creation.
Program.KernelLog
returns the retained log while the program remains open.
Operations return Go errors that preserve errno matching where libxdp or the
kernel provide one. Use errors.Is for errno checks and errors.As for the
package error type when the operation or resource context matters:
var xerr *xdp.Error
if errors.As(err, &xerr) {
log.Printf("%s %s: %s", xerr.Op, xerr.Resource, xerr.Message)
}
if errors.Is(err, syscall.EPERM) {
log.Print("operation needs additional privileges")
}SetLogHandler installs a
process-wide handler for libxdp warning, info, and debug messages and returns a
function that restores the previous handler:
restore := xdp.SetLogHandler(func(msg xdp.LogMessage) {
log.Printf("libxdp %s: %s", msg.Level, strings.TrimSpace(msg.Message))
})
defer restore()The handler receives copied Go strings. Generated callback pointers and C varargs remain internal.
The generated libxdp code preserves upstream environment handling.
LIBXDP_OBJECT_PATH participates in
FindProgramFile and
CreateProgram
object-name searches. LIBXDP_BPFFS selects the bpffs root used by libxdp, and
LIBXDP_BPFFS_AUTOMOUNT controls libxdp's upstream automount behavior.
The package does not load, attach, detach, pin, unpin, clean, mount, or remove
kernel or bpffs state on import. Those effects happen only when calling the
corresponding APIs, such as
Program.Attach,
Program.Detach,
Program.Pin,
CleanReferences,
CreateSocket, or setup
helpers.
Programs returned from a MultiProg
are borrowed views of that multiprog snapshot. Close those
Program wrappers when done. If
MultiProg.Close runs
first, it marks the snapshot closed for new operations and releases the native
snapshot after the outstanding borrowed program wrappers are closed.
CreateUMEM keeps the supplied
byte slice reachable until UMEM.Close
succeeds. Use memory suitable for AF_XDP registration, normally page-aligned
mmap-backed storage sized to whole frames. If UMEMOptions.Size is zero, the
registered size is the length of that packet area.
UMEMOptions.FrameSize,
UMEMOptions.FrameHeadroom,
UMEMOptions.FillSize,
UMEMOptions.CompletionSize,
UMEMOptions.Flags, and
UMEMOptions.TXMetadataLen
are passed through to libxdp; zero values mean libxdp defaults.
UMEM.Options returns those
creation options with Size normalized to the registered byte length.
UMEM.Data returns a borrowed,
mutable slice into the retained packet area and must not be used after the UMEM
is closed.
CreateUMEMWithFD and
UMEMOptions.UseFD pass
an existing UMEM fd to libxdp. After Go validation succeeds, libxdp owns that fd
and may close it even if UMEM creation returns an error.
Sockets borrow the UMEM and ring handles supplied at creation. Keep shared UMEM,
fill, completion, RX, and TX rings open while any socket that uses them remains
open. UMEM.Close returns
EBUSY while open sockets still depend on it; close sockets before closing the
UMEM they use.
Socket.FillRing and
Socket.CompletionRing
return explicitly shared rings when supplied, otherwise they return the socket
UMEM's fill and completion rings. Ring methods return
ErrClosed for closed handles and
structured errors for unattached rings.
Include
SocketInhibitProgramLoad
in SocketOptions.LibxdpFlags
when another control plane has already loaded the XDP program and AF_XDP socket
creation should not ask libxdp to load one automatically.
Generated files and embedded BPF object assets are checked in. Regeneration is only needed when updating the pinned inputs:
make generate
make generate-checkRegeneration reads ABI metadata from the required go.dw1.io/bpf module. The
Makefile uses scripts/prepare-bpf-source to provide libbpf source headers from
GENXDP_BPF_SOURCE_DIR, a full local go.dw1.io/bpf checkout, sibling
../bpf, or a cached checkout of the required module tag. The generator then
verifies that those source inputs match the required module ABI manifests.
The package examples compile during go test and skip runtime work unless
environment variables are provided:
XDP_EXAMPLE_OBJECT, optionalXDP_EXAMPLE_SECTION, andXDP_EXAMPLE_IFINDEXfor program attach/detach and*bpf.Objectinterop.XDP_EXAMPLE_IFINDEXfor multiprog inspection.XDP_EXAMPLE_IFNAMEfor AF_XDP UMEM/socket setup.
Privileged integration tests skip by default and can be enabled with explicit inputs:
XDP_INTEGRATION_OBJECTpoints to an XDP BPF object file.XDP_INTEGRATION_SECTIONoptionally selects the object section.XDP_INTEGRATION_IFINDEXoptionally attaches the program to an interface.XDP_INTEGRATION_IFNAMEcreates an AF_XDP socket on the named interface.
Run them with:
CGO_ENABLED=0 go test -run 'TestIntegration' -v .This module is licensed under the Apache License 2.0. See the LICENSE.