On 17/10/25 00:34, David Faust wrote:
On 10/12/25 21:26, Piyush Raj wrote:
This patch adds the bpf-vmtest-tool subdirectory under contrib which tests
BPF programs under a live kernel using a QEMU VM. It automatically
builds the specified kernel version with eBPF support enabled
and stores it under "~/.bpf-vmtest-tool", which is reused for future
invocations.
It can also compile BPF C source files or BPF bytecode objects and
test them against the kernel verifier for errors. When a BPF program
is rejected by the kernel verifier, the verifier logs are displayed.
$ python3 main.py -k 6.15 --bpf-src assets/ebpf-programs/fail.c
BPF program failed to load
Verifier logs:
btf_vmlinux is malformed
0: R1=ctx() R10=fp0
0: (81) r0 = *(s32 *)(r10 +4)
invalid read from stack R10 off=4 size=4
processed 1 insns (limit 1000000) max_states_per_insn 0 total_states 0
peak_states 0 mark_read 0
See the README for more examples.
The script uses vmtest (https://github.com/danobi/vmtest) to boot
the VM and run the program. By default, it uses the host's root
("/") as the VM rootfs via the 9p filesystem, so only the kernel is
replaced during testing.
Tested with Python 3.9 and above.
This looks good to me, but please wait for Jose or another reviewer.
I have some usability suggestions inline below but none are blockers,
they can all wait to be addressed in the future.
contrib/ChangeLog:
* bpf-vmtest-tool/README: New file.
* bpf-vmtest-tool/bpf.py: New file.
* bpf-vmtest-tool/config.py: New file.
* bpf-vmtest-tool/kernel.py: New file.
* bpf-vmtest-tool/main.py: New file.
* bpf-vmtest-tool/pyproject.toml: New file.
* bpf-vmtest-tool/tests/test_cli.py: New file.
* bpf-vmtest-tool/utils.py: New file.
* bpf-vmtest-tool/vm.py: New file.
Signed-off-by: Piyush Raj <[email protected]>
---
contrib/bpf-vmtest-tool/README | 78 ++++++++
contrib/bpf-vmtest-tool/bpf.py | 199 ++++++++++++++++++++
contrib/bpf-vmtest-tool/config.py | 18 ++
contrib/bpf-vmtest-tool/kernel.py | 209 ++++++++++++++++++++++
contrib/bpf-vmtest-tool/main.py | 103 +++++++++++
contrib/bpf-vmtest-tool/pyproject.toml | 36 ++++
contrib/bpf-vmtest-tool/tests/test_cli.py | 167 +++++++++++++++++
contrib/bpf-vmtest-tool/utils.py | 27 +++
contrib/bpf-vmtest-tool/vm.py | 154 ++++++++++++++++
9 files changed, 991 insertions(+)
create mode 100644 contrib/bpf-vmtest-tool/README
create mode 100644 contrib/bpf-vmtest-tool/bpf.py
create mode 100644 contrib/bpf-vmtest-tool/config.py
create mode 100644 contrib/bpf-vmtest-tool/kernel.py
create mode 100644 contrib/bpf-vmtest-tool/main.py
create mode 100644 contrib/bpf-vmtest-tool/pyproject.toml
create mode 100644 contrib/bpf-vmtest-tool/tests/test_cli.py
create mode 100644 contrib/bpf-vmtest-tool/utils.py
create mode 100644 contrib/bpf-vmtest-tool/vm.py
diff --git a/contrib/bpf-vmtest-tool/README b/contrib/bpf-vmtest-tool/README
new file mode 100644
index 00000000000..599e3529aa8
--- /dev/null
+++ b/contrib/bpf-vmtest-tool/README
@@ -0,0 +1,78 @@
+This directory contains a Python script to run BPF programs or shell commands
+under a live Linux kernel using QEMU virtual machines.
+
+USAGE
+=====
+
+To run a shell command inside a live kernel VM:
+
+ python main.py -k 6.15 -r / -c "uname -a"
+
+To run a BPF source file in the VM:
+
+ python main.py -k 6.15 --bpf-src fail.c
+
+To run a precompiled BPF object file:
+
+ python main.py -k 6.15 --bpf-obj fail.bpf.o
+
+The tool will download and build the specified kernel version from:
+
+ https://www.kernel.org/pub/linux/kernel
+
+A prebuilt `bzImage` can be supplied using the `--kernel-image` flag.
IMO it's easy to miss the -v/--log-level flag, and that by default it
will not print any informational messages while downloading and building
the kernel.
It might be better to set --log-level=INFO by default, and turn it off
when invoking from the testsuite. That way a user running the tool
directly has by default more indication of what's going on.
I agree, not printing anything by default during kernel builds isn’t a
good idea, especially since it’s a long-running task. I’ll fix this in
the next revision.
In general it would be good to describe the available options and their
defaults here.
Thanks for catching that. I’ll update the README in the next revision as
well.
+
+NOTE
+====
+- Only x86_64 is supported
+- Only "/" (the root filesystem) is currently supported as the VM rootfs when
+running or testing BPF programs using `--bpf-src` or `--bpf-obj`.
+
+DEPENDENCIES
+============
+
+- Python >= 3.9
+- vmtest >= v0.18.0 (https://github.com/danobi/vmtest)
+ - QEMU
+ - qemu-guest-agent
+
+For compiling kernel
+- https://docs.kernel.org/process/changes.html#current-minimal-requirements
+For compiling and loading BPF programs:
+
+- libbpf
+- bpftool
+- gcc-bpf-unknown-none
+ (https://gcc.gnu.org/wiki/BPFBackEnd#Where_to_find_GCC_BPF)
+- vmlinux.h
+ Can be generated using:
+
+ bpftool btf dump file /sys/kernel/btf/vmlinux format c > \
+ /usr/local/include/vmlinux.h
+
+ Or downloaded from https://github.com/libbpf/vmlinux.h/tree/main
+
+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")
+- 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)
+- VMTEST_LDFLAGS: Linker flags for the loader (default: -lelf -lz -lbpf)
+
+Example usage:
+
+ BPF_CFLAGS="-O3 -g" CFLAGS="-O2" python main.py -k 6.15 --bpf-src fail.c
+
+DEVELOPMENT
+===========
+
+Development dependencies are specified in `pyproject.toml`, which can be used
+with any suitable Python virtual environment manager.
+
+To run the test suite:
+
+ python3 -m pytest
--- 8< ---