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.

the XDP Tutorial

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

10.10 Exercises

todo