Building a Raspberry Pi Kernel to Run dae
Enable the BPF stream parser and BTF support required by dae on Raspberry Pi by cross-compiling a Raspberry Pi 5 kernel from Arch Linux
dae is a convenient option for using a Raspberry Pi as a software router. It depends heavily on kernel eBPF-related modules. The official Raspberry Pi kernel already enables most eBPF-related options, but it lacks CONFIG_BPF_STREAM_PARSER and BTF, so dae may fail its capability checks during startup.
You can cross-compile the Raspberry Pi kernel on a host machine, enable the kernel options required by dae, and install the new kernel onto the Raspberry Pi boot disk. The example below uses Arch Linux as the build environment and targets a 64-bit Raspberry Pi kernel. The kernel_2712 and bcm2712_defconfig values used in the commands correspond to Raspberry Pi 5 / BCM2712. For other models, replace them with the appropriate kernel image name and defconfig.
You can directly download the build scripts and compiled artifacts here.
Kernel options required by dae
daed mainly requires kernel support for eBPF and debug information:
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_CGROUPS=y
CONFIG_KPROBES=y
CONFIG_NET_INGRESS=y
CONFIG_NET_EGRESS=y
CONFIG_NET_SCH_INGRESS=m
CONFIG_NET_CLS_BPF=m
CONFIG_NET_CLS_ACT=y
CONFIG_BPF_STREAM_PARSER=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_INFO_REDUCED is not set
CONFIG_DEBUG_INFO_BTF=y
CONFIG_KPROBE_EVENTS=y
CONFIG_BPF_EVENTS=y
Options such as CONFIG_NET_CLS_BPF and CONFIG_NET_SCH_INGRESS can either be built into the kernel or provided as modules. CONFIG_DEBUG_INFO_BTF requires pahole to be installed on the build host; otherwise, the kernel build cannot generate BTF information.
You can first check the current kernel configuration on the Raspberry Pi:
(zcat /proc/config.gz || cat /boot/{config,config-$(uname -r)}) | grep -E 'CONFIG_(DEBUG_INFO|DEBUG_INFO_BTF|KPROBES|KPROBE_EVENTS|BPF|BPF_SYSCALL|BPF_JIT|BPF_STREAM_PARSER|NET_CLS_ACT|NET_SCH_INGRESS|NET_INGRESS|NET_EGRESS|NET_CLS_BPF|BPF_EVENTS|CGROUPS)=|# CONFIG_DEBUG_INFO_REDUCED is not set'
The official Raspberry Pi kernel already enables these options:
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_CGROUPS=y
CONFIG_KPROBES=y
CONFIG_NET_INGRESS=y
CONFIG_NET_EGRESS=y
CONFIG_NET_SCH_INGRESS=m
CONFIG_NET_CLS_BPF=y
CONFIG_NET_CLS_ACT=y
CONFIG_KPROBE_EVENTS=y
CONFIG_BPF_EVENTS=y
The options that actually need to be enabled additionally are:
CONFIG_BPF_STREAM_PARSER=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_INFO_REDUCED is not set
CONFIG_DEBUG_INFO_BTF=y
Prepare the cross-compilation environment
On Arch Linux, install the cross-compilation toolchain and the BTF generation tool:
sudo pacman -Syu base-devel git bc bison flex ncurses openssl aarch64-linux-gnu-gcc pahole
pahole: when the kernel has CONFIG_DEBUG_INFO_BTF enabled, it uses this tool to generate BTF from DWARF debug information.
Get the Raspberry Pi kernel source
Clone the kernel source maintained by Raspberry Pi:
git clone --depth=1 https://github.com/raspberrypi/linux
cd linux
Set a few variables for the following commands:
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
export KERNEL=kernel_2712
KERNEL=kernel_2712 is the kernel image name for Raspberry Pi 5. Other 64-bit Raspberry Pi models usually use a different name, so confirm the actual kernel file on the /boot partition before replacing it.
Generate and modify the kernel configuration
First, generate .config from the default Raspberry Pi 5 configuration:
make bcm2712_defconfig
Then open the menu configuration interface:
make menuconfig
In menuconfig, press / and search for the following symbol names directly. Enable the options according to their dependency requirements:
BPF_STREAM_PARSER
DEBUG_INFO
DEBUG_INFO_BTF
DEBUG_INFO_REDUCED
Build the kernel, modules, and device trees
Start the build:
make -j"$(nproc)" Image modules dtbs
If a step related to CONFIG_DEBUG_INFO_BTF fails, first check whether the build host can find pahole:
pahole --version
Mount the Raspberry Pi boot disk
Connect the Raspberry Pi SD card to the build host, then use lsblk to find the correct partitions:
lsblk -f
This example assumes:
/dev/sda1is the boot partition./dev/sda2is the rootfs partition.
Replace these with your actual device names when running the commands:
mkdir -p mnt/boot
mkdir -p mnt/root
sudo mount /dev/sda1 mnt/boot
sudo mount /dev/sda2 mnt/root
Install kernel modules
First, install the modules into the target system’s rootfs:
sudo env PATH="$PATH" make -j"$(nproc)" INSTALL_MOD_PATH=mnt/root modules_install
Install the kernel and device trees
Before replacing the kernel, back up the old kernel image:
sudo cp "mnt/boot/$KERNEL.img" "mnt/boot/$KERNEL-backup.img"
Then install the new kernel, device trees, and overlays:
sudo cp arch/arm64/boot/Image "mnt/boot/$KERNEL.img"
sudo cp arch/arm64/boot/dts/broadcom/*.dtb mnt/boot/
sudo cp arch/arm64/boot/dts/overlays/*.dtb* mnt/boot/overlays/
sudo cp arch/arm64/boot/dts/overlays/README mnt/boot/overlays/
Finally, unmount the partitions:
sudo umount mnt/boot
sudo umount mnt/root
Insert the boot disk back into the Raspberry Pi and boot it.
Verify after boot
After logging into the Raspberry Pi, confirm that it has booted into the new kernel:
uname -a
Then check the key configuration options:
(zcat /proc/config.gz || cat /boot/{config,config-$(uname -r)}) | grep -E 'CONFIG_(DEBUG_INFO|DEBUG_INFO_BTF|KPROBES|KPROBE_EVENTS|BPF|BPF_SYSCALL|BPF_JIT|BPF_STREAM_PARSER|NET_CLS_ACT|NET_SCH_INGRESS|NET_INGRESS|NET_EGRESS|NET_CLS_BPF|BPF_EVENTS|CGROUPS)=|# CONFIG_DEBUG_INFO_REDUCED is not set'
Check especially that these lines exist:
CONFIG_BPF_STREAM_PARSER=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_INFO_REDUCED is not set
CONFIG_DEBUG_INFO_BTF=y
If you have changed the default boot kernel, set this in /boot/firmware/config.txt:
[all]
kernel=kernel_2712.img