ebpf-go Documentation
repository·main·Indexed 27 days ago
https://github.com/cilium/ebpfA pure Go library for loading, compiling, and debugging eBPF programs, designed for integration into long-running processes. It includes the bpf2go tool for compiling C source files into eBPF bytecode and generating Go glue code, as well as specialized packages for assembly (asm), linking (link), perf events (perf), ring buffers (ringbuf), BTF data (btf), and BPF filesystem interaction (pin).
What's inside ebpf-go
- ebpf-go is a pure Go library designed for loading, compiling, and debugging eBPF programs. It is intended for use in long-running processes and maintains minimal external dependencies. It provides tools for working with eBPF programs written in either C or assembly.
Understand the eBPF Object Loading Workflow
mainThe library provides an eBPF object (ELF) loader compatible with upstream
libbpfandiproute2. The workflow follows these stages:- ELF: The compiled eBPF C program (via
clang). - CollectionSpec: An intermediate Go representation of the ELF containing
ProgramSpec,MapSpec, andTypes. - Collection: The actual resources (Maps and Programs) loaded into the kernel.
- Links: Connections between Maps, Programs, and kernel resources.
You typically obtain a
CollectionSpecby callingLoadCollectionSpecand then load it into the kernel to create aCollection.- ELF: The compiled eBPF C program (via
Understanding Compile Once - Run Everywhere (CO-RE)
mainWhile
bpf2goproduces standalone binaries, they are not automatically compatible with all kernel versions or distributions due to changes in kernel internal data structures and compile-time configurations.To achieve universal interoperability, use Compile Once - Run Everywhere (CO-RE) techniques. CO-RE relies on BPF Type Format (BTF) information provided by the kernel, which allows memory accesses to be adjusted dynamically right before the eBPF program is loaded into the kernel.
Understand eBPF object lifecycle and Go Garbage Collection
mainIn
cilium/ebpf, eBPF resources likeMap,Program, andlink/Linkare modeled around underlying Linux file descriptors.Because Go is a garbage-collected language, the runtime will automatically call
Close()on the underlying file descriptor when the Go object is no longer reachable.Warning: If you create an object inside a function but do not return it to the caller, the garbage collector may reclaim it and close the file descriptor unexpectedly, detaching the eBPF program or destroying the resource.
Manage eBPF object lifetimes via Pinning
mainTo prevent eBPF objects (Maps, Programs, or Links) from being destroyed when your Go process exits, you can use pinning. This associates the resource with a file in the BPF File System (
bpffs).- Persistence: Pins allow objects to persist after the Go process exits, enabling sharing between processes (e.g., inspecting a map with
bpftool). - Removal: To remove a pin, use the standard
rmcommand on the pin path. If the object was previously pinned and you are holding it in Go, you can callMap.Unpin,Program.Unpin, orLink.Unpin. - Limitation: Pins do not persist through a system reboot.
- Persistence: Pins allow objects to persist after the Go process exits, enabling sharing between processes (e.g., inspecting a map with
Generate Go scaffolding from eBPF C code using bpf2go
mainThe
bpf2gotool automates the compilation of eBPF C code and generates Go scaffolding to interact with Maps and Programs.- Create a C file (e.g.,
counter.c) for your eBPF program. Ensure C files are excluded from standard Go builds by using appropriate build tags if necessary. - Create a Go file (e.g.,
gen.go) containing a//go:generatedirective that callsbpf2go. - Initialize your Go module and add
bpf2goas a tool dependency. - Run
go generateto produce the.o(object) and.go(scaffolding) files.
//go:generate bpf2go -type counter counter.cgo mod init ebpf-test go mod tidy go get -tool github.com/cilium/ebpf/cmd/bpf2go go generate- Create a C file (e.g.,
Prerequisites for eBPF development in Go
mainTo develop eBPF applications using this library, ensure your environment meets the following requirements:
- Linux kernel: Version 5.7 or later (required for
bpf_linksupport). - LLVM: Version 11 or later (includes
clangandllvm-strip). - libbpf headers:
- Debian/Ubuntu:
libbpf-dev - Fedora:
libbpf-devel
- Debian/Ubuntu:
- Linux kernel headers:
- AMD64 Debian/Ubuntu:
linux-headers-amd64 - Fedora:
kernel-devel - Note for Debian: You may need to run
ln -sf /usr/include/asm-generic/ /usr/include/asmto ensure<asm/types.h>is discoverable.
- AMD64 Debian/Ubuntu:
- Go compiler: A version compatible with the project's Go module.
- Linux kernel: Version 5.7 or later (required for
Use eBPF for Windows with source compatibility
mainThe library provides preliminary support for the [eBPF for Windows] runtime. While it offers source compatibility (allowing you to use the same Go APIs as on Linux), it does not provide feature parity or binary compatibility. Many APIs will returnErrNotSupportedon Windows, and eBPF programs compiled for Linux cannot be used on Windows.Declare and use Global Variables in BPF
mainNon-const global variables are mutable and can be modified by both the BPF program and the user space application. They are typically used for stateful data like metrics, counters, or rate limiting.
Best Practice: Like constants, declare global variables as
volatilein BPF C to ensure the compiler reliably allocates them in the ELF data section, making them accessible to user space.Interaction Patterns
1. Before Loading (Initialization)
To ensure a variable is populated before the BPF program executes, use the
VariableSpecmethods found inCollectionSpec.Variablesor injected viaLoadAndAssign.2. After Loading (Runtime Access)
Once the program is loaded, use the
Variableabstraction to interact with the data:- Read: Use
Variable.Get()to retrieve the current value. - Write: Use
Variable.Set(value)to modify the value at runtime.
Variables can be found in the
Collection.Variablesfield or injected usingLoadAndAssign.- Read: Use
Install the ebpf Go library
mainTo add
github.com/cilium/ebpfas a dependency to your existing Go module, run thego getcommand from within your module's directory. This library is self-contained and does not depend on C, libbpf, or other non-standard Go libraries, making it suitable for portable tools across various architectures.go get github.com/cilium/ebpfUse bpf2go with go generate
mainInvoke
bpf2gousing the//go:generatedirective. The tool compiles a C source file into eBPF bytecode and emits Go files containing the bytecode for both little-endian (_bpfel.go) and big-endian (_bpfeb.go) systems. You can pass additional arguments to the underlying compiler using the--separator.Syntax:
//go:generate go tool bpf2go <stem> <path/to/src.c> -- <compiler_flags>//go:generate go tool bpf2go foo path/to/src.c -- -I/path/to/includeDeclare and use Runtime Constants in BPF
mainRuntime constants are used for configuration values (e.g., network addresses, timeouts) that influence BPF program functionality. In BPF C, these are declared as
const. The BPF verifier performs dead code analysis on these constants, which can improve performance and allow for portable code by removing unused paths.Important: When declaring global variables that need to be accessed from user space, it is common practice to use the
volatilequalifier. This prevents the compiler from optimizing the variable away, ensuring it is correctly allocated in the ELF data section so user space can modify it.To modify a constant from Go before loading the program, use
VariableSpec.Seton the variable found inCollectionSpec.Variables.