树莓派编译内核运行dae

dae是在树莓派上作为软路由的一个比较方便的方案,其高度依赖内核eBPF相关模块,树莓派官方内核已经打开了大部分 eBPF 相关选项,但缺少 CONFIG_BPF_STREAM_PARSER 和 BTF,于是启动时会遇到能力检测失败。

我们可以主机上交叉编译 Raspberry Pi 内核、打开 dae 需要的内核选项,并把新内核安装到树莓派启动盘。示例使用 Arch Linux 作为编译环境,目标是 64 位树莓派内核;命令里的 kernel_2712bcm2712_defconfig 对应 Raspberry Pi 5 / BCM2712,如果是其他型号,需要换成对应的内核镜像名和 defconfig。

可以在这里直接下载编译脚本和构建产物。

daed 对内核的要求主要集中在 eBPF 和调试信息上:

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

其中 CONFIG_NET_CLS_BPFCONFIG_NET_SCH_INGRESS 这类选项既可以编进内核,也可以作为模块存在。CONFIG_DEBUG_INFO_BTF 需要构建主机安装 pahole,否则内核构建时无法生成 BTF 信息。

可以先在树莓派上检查当前内核配置:

(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'

树莓派官方内核已经打开了这些选项:

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

真正需要额外打开的是:

CONFIG_BPF_STREAM_PARSER=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_INFO_REDUCED is not set
CONFIG_DEBUG_INFO_BTF=y

在 Arch Linux 上安装交叉编译工具链和 BTF 生成工具:

sudo pacman -Syu base-devel git bc bison flex ncurses openssl aarch64-linux-gnu-gcc pahole

pahole:内核开启 CONFIG_DEBUG_INFO_BTF 时会用它从 DWARF 调试信息生成 BTF。

拉取树莓派维护的内核源码:

git clone --depth=1 https://github.com/raspberrypi/linux
cd linux

为后续命令设置几个变量:

export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
export KERNEL=kernel_2712

KERNEL=kernel_2712 是 Raspberry Pi 5 的内核镜像名。其他 64 位树莓派型号通常不是这个名字,替换前先确认 /boot 分区里的实际内核文件。

先基于 Raspberry Pi 5 的默认配置生成 .config

make bcm2712_defconfig

然后进入菜单配置:

make menuconfig

menuconfig 里直接按 / 搜索下面几个符号名,对照依赖条件打开选项:

BPF_STREAM_PARSER
DEBUG_INFO
DEBUG_INFO_BTF
DEBUG_INFO_REDUCED

开始编译:

make -j"$(nproc)" Image modules dtbs

如果 CONFIG_DEBUG_INFO_BTF 相关步骤报错,优先检查构建主机是否能找到 pahole

pahole --version

把树莓派的SD卡接到构建主机上,先用 lsblk 找到正确的分区:

lsblk -f

示例里假设:

  • /dev/sda1 是 boot 分区。
  • /dev/sda2 是 rootfs 分区。

实际操作时换成自己的设备名:

mkdir -p mnt/boot
mkdir -p mnt/root

sudo mount /dev/sda1 mnt/boot
sudo mount /dev/sda2 mnt/root

先把模块安装进目标系统的 rootfs:

sudo env PATH="$PATH" make -j"$(nproc)" INSTALL_MOD_PATH=mnt/root modules_install

替换内核前先备份旧内核镜像:

sudo cp "mnt/boot/$KERNEL.img" "mnt/boot/$KERNEL-backup.img"

然后安装新内核、设备树和 overlay:

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/

最后卸载分区:

sudo umount mnt/boot
sudo umount mnt/root

把启动盘插回树莓派,开机。

进入树莓派后,确认已经启动到新内核:

uname -a

再检查关键配置:

(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'

重点看这几行是否存在:

CONFIG_BPF_STREAM_PARSER=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_INFO_REDUCED is not set
CONFIG_DEBUG_INFO_BTF=y

若你修改过默认启动内核,在/boot/firmware/config.txt中设置:

[all]
kernel=kernel_2712.img

相关内容