Skip to content

Operations

How to set up an environment for the tutorial, compile and run lessons, debug eBPF programs, and verify readiness. Commands below are taken from the lesson sources themselves (primarily lesson 1's documented workflow) — not invented.

Prerequisites

  • A Linux system with kernel >= 4.8; the project recommends Ubuntu (23.10-era or newer) with kernel 5.15+ or 6.2+, and notes that some advanced lessons need 6.12+ (sched_ext) up to bleeding-edge features.
  • Root/sudo access for loading programs and reading trace output.
  • Basic C knowledge and familiarity with processes and syscalls.

Environment Setup

Install compiler tooling on Debian/Ubuntu as documented in lesson 1:

sudo apt install clang llvm

Typical additional packages for libbpf-based lessons (11 onward):

sudo apt install libelf-dev libclang-dev clang-tools gcc-multilib

Grab the two eunomia-bpf tools used by early lessons. ecli runs compiled artifacts; ecc compiles kernel-side code into distributable packages:

$ wget https://aka.pw/bpf-ecli -O ecli && chmod +x ./ecli
$ ./ecli -h
Usage: ecli [--help] [--version] [--json] [--no-cache] url-and-args

$ 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]

On aarch64 use the dedicated binaries instead: ecc-aarch64 and ecli-aarch64.

No local toolchain at all? The Docker image route compiles any directory containing *.bpf.c and headers:

docker run -it -v `pwd`/:/src/ ghcr.io/eunomia-bpf/ecc-`uname -m`:latest

Get the Tutorial Source

git clone https://github.com/eunomia-bpf/bpf-developer-tutorial.git
cd bpf-developer-tutorial/src/<lesson-dir>

Each lesson directory is independent — build one, not the repo.

Compile and Run a Lesson (lesson 1 walkthrough)

  1. Compile kernel-side BPF code to a distributable package:
$ ./ecc minimal.bpf.c
Compiling bpf object...
Packing ebpf object and config into package.json...
  1. Run it (eBPF attach requires root):
$ sudo ./ecli run package.json
Running eBPF program...
  1. Observe tracepoint output from the write syscall tracepoint via the tracing pipe:
$ sudo cat /sys/kernel/debug/tracing/trace_pipe | grep "BPF triggered sys_enter_write"
<...>-3840345 [010] d... 3220701.101143: bpf_trace_printk: write system call from PID 3840345.
  1. Generate traffic to trigger events if quiet:
echo "test" > /tmp/test.txt

Stop ecli with Ctrl+C; events stop immediately.

Run Prebuilt Tools Without Compiling

Distribute-or-consume pattern using OCI images directly:

$ sudo ./ecli run ghcr.io/eunomia-bpf/execve:latest
[79130] node -> /bin/sh -c which ps
[79131] sh -> which ps
...

ecli --no-cache <url> forces refetch of remote packages.

Debugging Recipes

  • List loaded BPF programs and confirm attachment:
sudo bpftool prog list
  • Enumerate available syscall tracepoints when choosing a SEC() hook name:
sudo ls /sys/kernel/debug/tracing/events/syscalls/
  • See live program output (shared globally by all eBPF programs — grep is expected):
sudo cat /sys/kernel/debug/tracing/trace_pipe
  • Check whether eBPF is exposing BTF for CO-RE (most lessons require it):
ls /sys/kernel/btf/vmlinux && zcat /proc/config.gz | grep DEBUG_INFO_BTF

Common Issues

Tracing silently off

No trace_pipe output despite "Running eBPF program..." is usually the tracing subsystem being disabled by distro defaults. Enable it:

$ sudo sh -c 'echo 1 > /sys/kernel/debug/tracing/tracing_on'

bpf_printk limitations taught in lesson 1

Max three format arguments, globally shared pipe, measurable overhead at high event rates — production tools move to ring buffers/perf arrays (lessons 7-8).

  • Missing /sys/kernel/btf/vmlinux — kernel built without CONFIG_DEBUG_INFO_BTF; CO-RE lessons will fail verification. Use a distro kernel with BTF enabled.
  • Permission denied attaching — most hooks require root; XDP/tc lessons additionally target a real interface (--dev eth0 style flags per lesson README).
  • arm64 fentry errors on older kernels — lesson-level baselines differ per architecture (see compatibility matrix): fentry x86_64 needs 5.5 but arm64 needs 6.0.

Beyond ad-hoc runs

When graduating past single-file examples, use the org starter templates (C/libbpf, Go/cilium-ebpf, Rust/libbpf-rs, eunomia). Each template ships a one-command Makefile build, containerized environment Dockerfile, and GitHub Actions CI for build/test/release, removing environment setup entirely from new projects.

For the scheduling track, verify sched_ext availability before running scheduler lessons:

grep SCHED_CLASS_EXT /proc/config.gz 2>/dev/null || uname -r   # requires kernel 6.12+