How-to Guides¶
Task recipes for working through the bpf-developer-tutorial: preparing a host, building and running eunomia-bpf and libbpf lessons, checking kernel prerequisites for the newer lessons, debugging, and cleaning up. Commands come from the upstream lesson READMEs and CI workflow (read 2026-09-25). Package lists and version facts are in Reference: Toolchain Requirements.
Prerequisites¶
- A Linux host with kernel 4.8 or later. Lesson 1 suggests 5.15+ or 6.2+ and a recent Ubuntu. Lesson 0 recommends 5.15+ or 6.9+ for full feature coverage (BPF arena, tokens). Individual lessons need up to 7.0 (see Reference: Kernel Baseline Spread).
- Root or sudo access for loading programs and reading trace output.
- Basic C knowledge and familiarity with processes and system calls.
Match the CI baseline
Upstream CI builds every libbpf lesson on ubuntu-24.04 with distro clang/llvm. Using the same release (or a newer one with an HWE kernel) avoids most toolchain surprises.
Isolate a Practice Environment¶
- Use a disposable VM. Ubuntu 24.04 matches the CI runner. Snapshot it before the security lessons (24-28, 34, 51) so you can roll back.
- Use a mainline test VM for bleeding-edge lessons. Lessons 52 (7.0), 54 (6.19) and 53 (6.16) need very recent kernels. Do not run them on production or daily-driver systems.
- Keep networking lessons off your uplink. XDP, tc, TCX and qdisc lessons attach to a named interface. Use veth pairs or loopback where the lesson allows it (lesson 50 defaults to loopback).
- Use an emulator for Android. Lesson 22 used an Android Studio emulator image, which keeps experiments off a personal handset.
- Check the unprivileged-BPF setting. The lessons assume privileged loading anyway, so leaving unprivileged BPF disabled is fine:
Install the Toolchain¶
For the libbpf-based lessons (11 onward), install clang, libelf and zlib as lesson 11 documents:
# Debian/Ubuntu
sudo apt install clang libelf1 libelf-dev zlib1g-dev
# Fedora/CentOS
sudo dnf install clang elfutils-libelf elfutils-libelf-devel zlib-devel
To mirror the full CI package set on Ubuntu 24.04:
sudo apt-get install -y --no-install-recommends \
libelf1 libelf-dev zlib1g-dev make git clang llvm pkg-config \
build-essential dwarves linux-headers-generic-hwe-24.04
For the eunomia-bpf lessons (1-10), lesson 1 only needs clang and llvm plus the two eunomia-bpf binaries. ecc compiles kernel-side code into a package. ecli runs packages:
$ sudo apt install clang llvm
$ wget https://aka.pw/bpf-ecli -O ecli && chmod +x ./ecli
$ wget https://github.com/eunomia-bpf/eunomia-bpf/releases/latest/download/ecc && chmod +x ./ecc
$ ./ecc -h
eunomia-bpf compiler
Usage: ecc [OPTIONS] <SOURCE_PATH> [EXPORT_EVENT_HEADER]
The eunomia-bpf README also documents downloading ecli directly from https://github.com/eunomia-bpf/eunomia-bpf/releases/latest/download/ecli. ecc also needs libclang. On aarch64 use ecc-aarch64 and ecli-aarch64.
ecli -h output changed
Lesson 1 still shows the old one-line usage (ecli [--help] [--version] [--json] [--no-cache] url-and-args). Current releases (v1.0.38, 2026-03-08) print subcommands run, push and pull. The remote HTTP mode (ecli client, ecli-server) was removed in March 2026.
No local toolchain at all? The Docker image compiles any directory containing *.bpf.c and headers:
Get the Tutorial Source¶
Clone with submodules. The libbpf lessons build against the vendored bpftool (which carries libbpf) and blazesym submodules:
git clone https://github.com/eunomia-bpf/bpf-developer-tutorial.git
cd bpf-developer-tutorial
git submodule update --init --recursive
Each lesson directory is independent: build one lesson, not the whole repo.
Compile and Run an eunomia-bpf Lesson¶
Lesson 1 walkthrough (src/1-helloworld):
-
Compile the kernel-side program into a package:
-
Run it as root:
-
In another terminal, read the tracepoint output:
-
If the output is quiet, generate some writes:
Stop ecli with Ctrl+C. Events stop immediately.
Compile and Run a libbpf Lesson¶
Lesson 11 (src/11-bootstrap) is the reference pattern for every Makefile-based lesson:
$ cd src/11-bootstrap
$ make
BPF .output/bootstrap.bpf.o
GEN-SKEL .output/bootstrap.skel.h
CC .output/bootstrap.o
BINARY bootstrap
$ sudo ./bootstrap
Build from the repository root the way CI does, with a timed smoke run:
The Rust profiler in lesson 12 uses the same make entry point but needs Rust and Cargo installed first:
Run Prebuilt Tools Without Compiling¶
ecli can pull and run a precompiled program from an OCI registry:
$ sudo ./ecli run ghcr.io/eunomia-bpf/execve:latest
[79130] node -> /bin/sh -c which ps
[79131] sh -> which ps
Prefer local builds for anything sensitive (see Explanation: Artifact Supply Chain).
Check Kernel Prerequisites¶
Confirm BTF is available for CO-RE (most lessons from 2 onward need it):
ls -l /sys/kernel/btf/vmlinux
zcat /proc/config.gz 2>/dev/null | grep CONFIG_DEBUG_INFO_BTF || grep CONFIG_DEBUG_INFO_BTF /boot/config-$(uname -r)
Check a lesson-specific option before building. Replace the option name with the one from Reference: Kernel Config Options:
grep -E 'CONFIG_SCHED_CLASS_EXT|CONFIG_NET_XGRESS|CONFIG_NET_SCH_BPF|CONFIG_BPF_LSM' /boot/config-$(uname -r)
For BPF LSM lessons (19, 54), bpf must also be in the active LSM list:
Run the sched_ext Lessons¶
Lesson 44 builds scx_simple from the kernel source tree on a 6.12+ kernel with CONFIG_SCHED_CLASS_EXT=y:
uname -r # needs 6.12 or later
cd linux/tools/sched_ext && make # inside a matching kernel source tree
sudo ./scx_simple -f # -f selects FIFO mode, -v verbose
While it runs, the kernel reports sched_ext state in sysfs:
Terminate the scx_simple process to return all tasks to the default scheduler. SysRq-S also switches back, and SysRq-D triggers a debug dump.
Build the 2026 Lessons (50-54)¶
These lessons build from the repository root with make, following the lesson READMEs:
make -C src/50-tcx && sudo src/50-tcx/tcx_demo # monitors loopback until Ctrl+C
make -C src/54-exec-image-inspector clean
make -C src/54-exec-image-inspector -j2
Lesson 51 defaults to a dry run. Only --apply destroys connections:
If lesson 53 is killed before cleanup and leaves a bpf_pacer root qdisc behind, find the interface that shows it and remove it:
Debugging Recipes¶
-
List loaded BPF programs and confirm attachment:
-
Enumerate syscall tracepoints when choosing a
SEC()hook name: -
Watch
bpf_printkoutput (shared by all BPF programs, so filter it):
Clean Up After Experiments¶
Lesson 28 teaches that pinned programs outlive their launcher. Check for residue instead of assuming teardown:
sudo bpftool prog show
sudo bpftool map show
sudo bpftool link show
ls /sys/fs/bpf/
sudo rm -f /sys/fs/bpf/<pinned-path> # only pins you created
Common Issues¶
Tracing silently off
No trace_pipe output despite "Running eBPF program..." usually means tracing is disabled. Enable it:
bpf_printk limits (lesson 1)
At most three format arguments, a globally shared pipe and measurable overhead at high event rates. Real tools move to perf event arrays and ring buffers (lessons 7-8).
- Missing
/sys/kernel/btf/vmlinux: the kernel was built withoutCONFIG_DEBUG_INFO_BTF. CO-RE lessons will fail to load. Use a distro kernel with BTF enabled. - Syscall tracepoint attach fails with "No such file or directory": the kernel lacks
CONFIG_FTRACE_SYSCALLS. Lesson 22 hit this on the Android emulator kernel. - Permission denied attaching: most hooks require root. XDP/tc lessons also need a real or veth interface named on the command line.
- fentry errors on arm64: fentry needs 5.5 on x86_64 but 6.0 on arm64 (lesson 3).
- Build errors about
bpf_session_cookieor file dynptr kfuncs: lessons 52 and 54 carry workarounds for the vendoredvmlinux.h. Rebuild from a clean tree (make clean) with updated submodules before patching anything.
Start Your Own Project¶
When you move past single-lesson examples, start from an org template: libbpf-starter-template (C), cilium-ebpf-starter-template (Go), libbpf-rs-starter-template (Rust) or eunomia-template. Each ships a one-command Makefile, a Dockerfile that publishes to GitHub Packages, and GitHub Actions for build, test and release. The README's example of running a template-built image:
Sources¶
- bpf-developer-tutorial: README,
.github/workflows/test-libbpf.yml, lesson READMEs 1, 11, 12, 22, 28, 44, 50-54 (read 2026-09-25) - eunomia-bpf README (install commands,
eclisubcommands, removal of the remote HTTP mode) - Linux kernel sched_ext documentation (
/sys/kernel/sched_ext/state, SysRq behavior)