Hello-World
Creating the eBPF byte code and loding the program using bpftrace
In this section, you’ll learn how to write, compile, and load a simple eBPF program into the Linux kernel.
bpftrace is already installed in the servers given to you. Please visit bpftrace github for more information.
If you’d like to learn more about the tools, refer to the bpftrace GitHub page and the bpftool documentation.
Starting with bpftrace
You can check that bpftrace
is installed and working properly by running:
bpftrace --version
This should print the installed version number.
Writing a Simple eBPF Program
Let’s start with helloWorld.bpf.c
a minimal program that prints "Hello World"
every time a packet passes through the interface.
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
int counter = 0;
SEC("xdp")
int helloWorld(struct xdp_md *ctx) {
bpf_printk("Hello World %d", counter);
counter++;
return XDP_PASS;
}
char LICENSE[] SEC("license") = "Dual BSD/GPL";
Breakdown of the Code
-
SEC("xdp")
: Places the program in the XDP section, so it can be attached to a network interface. -
bpf_printk()
: Prints messages to the kernel trace buffer (/sys/kernel/debug/tracing/trace_pipe). -
XDP_PASS
: Allows packets to continue through the normal network stack. -
counter
: A simple global integer incremented on each packet to demonstrate persistence. -
char LICENSE[]
: Specifies the license required for kernel compatibility.
Compiling the eBPF Program
eBPF programs must be compiled into bytecode that the eBPF virtual machine can understand.
We use Clang (from LLVM) to compile the program to a .o
object file.
Using the Makefile
provided in this directory, just run:
make
Inspecting the Compiled eBPF Object File
Check that your compiled file is indeed an eBPF object:
file helloWorld.bpf.o
You can disassemble it to view the actual eBPF bytecode using llvm-objdump
:
llvm-objdump-18 -S helloWorld.bpf.o
This will show the assembly instructions that will run inside the eBPF virtual machine.
Loading the Program into the Kernel
Now, let’s load the program into the kernel before attaching it to a network interface.
sudo bpftool prog load helloWorld.bpf.o /sys/fs/bpf/helloWorld
Check that it was successfully loaded:
sudo ls /sys/fs/bpf/
The bpftool utility can list all the programs that are loaded into the kernel. If you try this yourself you’ll probably see several preexisting eBPF programs in this output:
sudo bpftool prog list
You can also filter these programs by name to only list our helloWorld program:
sudo bpftool prog list name helloWorld
The program will be assigned a unique {ID}. This identity is a number assigned to each program as it’s loaded. Knowing the ID, you can ask bpftool to show more information about this program. This time, let’s get the output in prettified JSON format so that the field names are visible, as well as the values:
sudo bpftool prog show id {ID} --pretty
You can also see the translated instructions:
sudo bpftool prog dump xlated name helloWorld
Attaching the Program
We first need to find a network interface to attach our XDP program too. To find your network interfaces:
ip link
Then attach your eBPF program to the loopback interface:
sudo bpftool net attach xdp id {ID} dev lo
Confirm it’s attached:
sudo bpftool net list
Output
The bpf_printk output is written to the kernel tracing buffer. You can view it in real time:
sudo cat /sys/kernel/debug/tracing/trace_pipe
Inspecting Maps
You can list eBPF maps, in our case the global variable counter
, currently loaded in the kernel:
sudo bpftool map list
Detaching and Cleaning Up
When done, detach the program and clean up the pinned object:
sudo bpftool net detach xdp dev lo
sudo rm /sys/fs/bpf/helloWorld
This ensures your kernel and BPF filesystem stay clean.