blob: d5648f59f6f397d3f773cb8d9ff0533359674a63 [file] [log] [blame]
BPF vmtest Tool
===============
https://gcc.gnu.org/wiki/BPFRunTimeTests
This directory contains a Python script for running BPF programs or shell commands
under a live Linux kernel using QEMU virtual machines.
USAGE
=====
Before using the tool, you must set the directory where vmtest will look for
kernels and store kernel artifacts. You can do this in two ways:
1. Set the VMTEST_DIR environment variable
2. Use the --vmtest-dir flag with each command
Note: This is required to use the tool.
Available Options
-----------------
usage: main.py [-h] [-v DEBUG|INFO|WARNING|ERROR] [--vmtest-dir DIR] {bpf,vmtest,kernel} ...
BPF vmtest tool
positional arguments:
{bpf,vmtest,kernel} Available commands
bpf BPF program management
vmtest Run VM tests
kernel Kernel management
options:
-h, --help show this help message and exit
-v DEBUG|INFO|WARNING|ERROR, --log-level DEBUG|INFO|WARNING|ERROR
Log level
--vmtest-dir DIR Directory for vmtest artifacts (or set VMTEST_DIR env variable)
COMMANDS
========
kernel subcommand
-----------------
Manage kernel builds for use in virtual machines. You must build a
kernel before using it.
Build a kernel:
python main.py --vmtest-dir="/home/user/.bpf-vmtest-tool" kernel build 6.15
The tool downloads and builds the specified kernel version from
https://www.kernel.org/pub/linux/kernel and stores the build artifacts in
$VMTEST_DIR/kernels/linux-6.15-x86_64. Specifically, it stores bpftool,
libbpf.a, bzImage-6.15-x86_64, and vmlinux.h, which are used when compiling
BPF programs instead of relying on the host system.
List available kernels:
python main.py --vmtest-dir="/home/user/.bpf-vmtest-tool" kernel list
Remove kernels:
python main.py --vmtest-dir="/home/user/.bpf-vmtest-tool" kernel remove 6.15-x86_64
Note: If the architecture is omitted, the host architecture is assumed. For
example, 6.15 is treated as 6.15-x86_64 on an x86_64 system.
vmtest subcommand
-----------------
Run BPF programs and commands inside a QEMU virtual machine with a live kernel.
Options:
-k VERSION, --kernel VERSION
Kernel version to boot in the VM. Must be a kernel previously built using
the "kernel build" subcommand. The kernel version should match the format
used during build (e.g., 6.15-x86_64 or just 6.15 for host architecture).
Required: Yes
-r PATH, --rootfs PATH
Path to a root filesystem directory to mount in the VM.
If not specified, the host's root filesystem (/) is mounted by default.
Required: No
Default: / (host root filesystem)
See "Creating a Custom Rootfs" section below for how to build a rootfs from
a container image.
--bpf-src PATH
BPF C source file to compile and load. Mutually exclusive with --bpf-obj.
--bpf-obj PATH
Pre-compiled BPF object to load. Mutually exclusive with --bpf-src.
-c COMMAND, --command COMMAND
Shell command to run in VM.
At least one of --bpf-src, --bpf-obj, or --command is required.
Examples:
Run a shell command inside a live kernel VM:
python main.py vmtest -k 6.15 -c "uname -a"
Load and run a BPF source file with custom rootfs:
python main.py vmtest -k 6.15 --bpf-src fail.c -r $HOME/rootfs/debian-rootfs
The tool compiles the source file using BPF_CC with BPF_CFLAGS and the
kernel-specific vmlinux.h, then generates a skeleton from the compiled BPF
object using bpftool and compiles it with a generated loader to produce
the final userspace binary.
Load a precompiled BPF object file:
python main.py vmtest -k 6.15 --bpf-obj fail.bpf.o
The tool follows the same steps to generate the final userspace binary, except
it skips the BPF object compilation step.
Creating a Custom Rootfs:
You can build a rootfs from a container image using this script:
#!/usr/bin/env bash
set -euo pipefail
ROOT="$HOME/rootfs"
IMAGE_NAME="debian-bookworm-rootfs"
CTR_NAME="debian-rootfs-ctr"
cat <<'EOF' | podman build -t "$IMAGE_NAME" -
FROM debian:bookworm
RUN apt-get update && \
apt-get install -y --no-install-recommends \
libelf1 \
qemu-guest-agent \
&& \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
EOF
CTR_ID=$(podman create --name "$CTR_NAME" "$IMAGE_NAME")
podman export -o "$ROOT/deb.tar" "$CTR_ID"
tar -xf "$ROOT/deb.tar" -C "$ROOT/debian-rootfs"
podman rm "$CTR_NAME"
echo "Debian rootfs ready at: $ROOT/debian-rootfs"
After running this script, use the rootfs with:
python main.py vmtest -k 6.15 -r $HOME/rootfs/debian-rootfs -c "uname -a"
bpf subcommand
--------------
Compile BPF source code to bytecode using kernel-specific headers.
Options:
compile
Compile a BPF C source file to a BPF object file.
-k VERSION, --kernel VERSION
Kernel version to use for compilation. The tool will use the vmlinux.h
header from this kernel for the compilation.
Required: Yes
-o OUTPUT, --output OUTPUT
Output path for the compiled BPF object file.
Required: Yes
Example:
python main.py --vmtest-dir="/home/user/.bpf-vmtest-tool" bpf compile \
invalid-memory-access.c -k 6.15 -o /tmp/invalid-memory-access.bpf.o
The compilation stage can be modified using the BPF_CFLAGS environment variable
(default: -c)
Example :
BPF_CFLAGS="-O2 -E" python main.py --vmtest-dir="/home/user/.bpf-vmtest-tool" \
bpf compile invalid-memory-access.c -k 6.15 -o /tmp/invalid-memory-access.bpf.o
LIMITATIONS
===========
- Only x86_64 architecture is currently supported
DEPENDENCIES
============
- Python >= 3.9
- vmtest >= v0.18.0 (https://github.com/danobi/vmtest)
- QEMU
- qemu-guest-agent (on guest filesystem)
For compiling kernels:
- pahole
- See https://docs.kernel.org/process/changes.html#current-minimal-requirements
For compiling and loading BPF programs:
- libbpf
- gcc-bpf-unknown-none (https://gcc.gnu.org/wiki/BPFBackEnd#Where_to_find_GCC_BPF)
BUILD FLAGS
===========
You can customize compiler settings using environment variables:
- BPF_CC: Compiler for the BPF program (default: bpf-unknown-none-gcc)
- BPF_CFLAGS: Extra flags for BPF program compilation (default: "-O2 -Wall -Werror -c")
- BPF_INCLUDES: Include paths for BPF (default: "-I/usr/local/include -I/usr/include")
- VMTEST_CC: Compiler for the user-space loader (default: gcc)
- VMTEST_CFLAGS: Flags for compiling the loader (default: "-g -Wall -Werror")
- VMTEST_LDFLAGS: Linker flags for the loader (default: "-lelf -lz")
Example usage:
BPF_CFLAGS="-O3 -g" BPF_CC="/bpf-gcc-build/gcc/xgcc" \
python main.py vmtest -k 6.15 --bpf-src fail.c
DEVELOPMENT
===========
Development dependencies are specified in pyproject.toml and can be installed
using any suitable Python virtual environment manager.
To run the test suite:
python3 -m pytest