eBPF programming consists of two parts:
- Writing eBPF programs that run in the kernel
- Writing the user space code that manages and interacts with eBPF programs
10.1 Bpftrace
The bpftrace command-line tool converts programs written in this high-level language into eBPF kernel code and provides some output formatting for the results within the terminal.
a nice tutorial that takes you from writing a simple “Hello World” script up to writing more sophisticated scripts that can trace out data read from within kernel data structures.
list the available tracepoints and kprobes on a machine with the -l option
1 | bpftrace -l "*execve*" |
it’s possible to attach to a kprobe called do_execve.
1 | bpftrace -e 'kprobe:do_execve { @[comm] = count(); }' |
The { @[comm] = count(); } part is the script attached to that event.
opensnoop.bt reports on files being opened.
1 | /usr/sbin/opensnoop.bt |
10.2 Language Choices for eBPF in the Kernel
eBPF programs can be written directly in eBPF bytecode, but in practice, most are compiled to bytecode from either C or Rust. These languages have compilers that support eBPF bytecode as a target output.
eBPF bytecode isn’t a suitable target for all compiled languages.
BPF programs are required to be single threaded, so any concurrency features in a language couldn’t be used.
10.3 BCC Python/Lua/C++
10.4 C and Libbpf
If you’re comfortable with programming in C, using libbpf can make a lot of sense.
To write your own libbpf programs in C, the best place to start is libbpf-bootstrap.
libxdp that builds on libbpf to allow for easier development and management of XDP programs.
10.5 Go
10.5.1 Gobpf
Possibly the first serious Golang implementation.
However, it hasn’t been actively maintained for a while.
10.5.2 Ebpf-go
The eBPF Go library included as part of the Cilium project is widely used.
10.5.3 Libbpfgo
The libbpfgo project by Aqua Security implements a Go wrapper around libbpf’s C code, providing utilities for loading and attaching programs and using Go-native features like channels for receiving events.
10.6 Rust
10.6.1 Libbpf-rs
Libbpf-rs is part of the libbpf project, and provides a Rust wrapper around the libbpf C code so that you can write the user space parts of eBPF code in Rust.
10.6.2 Redbpf
Redbpf is a set of Rust crates that interface with libbpf, developed as part of foniod, an eBPF-based security monitoring agent.
10.6.3 Aya
Aya is built in Rust directly to the syscall level, so it doesn’t depend on libbpf.
10.6.4 Rust-bcc
Rust-bcc provides Rust bindings that mimic the BCC project’s Python bindings, along with some Rust implementations of some of the BCC set of tracing tools.
10.7 Testing BPF Programs
There’s a bpf() command, BPF_PROG_RUN, that allows for running an eBPF program from user space for test purposes.
You can also get information about eBPF program performance with some built-in statistics information. Run the following command to enable it:
1 | sysctl -w kernel.bpf_stats_enabled=1 |
10.8 Multiple eBPF Programs
An eBPF program is a function attached to an event in the kernel. Many applications need to track more than one event to achieve their goals.
10.9 Summary
an up-to-date list of the major language projects around eBPF