eBPF:如何生成最小化BTF文件

面临的问题

内容摘录自 :

BTFGen: 让 eBPF 程序可移植发布更近一步 - 深入浅出eBPF

BTFGen: One Step Closer to Truly Portable eBPF Programs

第2个链接是原文,第1个链接为翻译。

eBPF 程序需要访问内核结构来获取需要的数据,因此依赖于内核结构的布局。为特定内核版本编译的 eBPF 程序通常不能在另一个内核版本上工作,这是因为相关的内核数据结构布局可能会发生了变化:比如字段添加、删除,或类型被改变,甚至内核编译配置的改变也会改变整个结构布局。例如,禁用 CONFIG_THREAD_INFO_IN_TASK 会改变 task_struct 的所有成员变量的偏移摘录[1]:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
    /*
     * For reasons of header soup (see current_thread_info()), this
     * must be the first element of task_struct.
     */
    struct thread_info        thread_info;
#endif
    unsigned int            __state;

#ifdef CONFIG_PREEMPT_RT
    /* saved state for "spinlock sleepers" */
    unsigned int            saved_state;
#endif
...

该问题的解决通常是在目标机器使用内核头文件编译 eBPF 程序并进行加载,BCC 项目所使用的正是这种方式。但该方法存在以下问题:

  1. 必须在目标机器上安装占用大量空间的编译器;
  2. 编译程序时需要资源,在某些情况下可能会影响工作负载的调度;
  3. 编译需要相当长的时间,因此事件采集会存在一些延迟;
  4. 依赖于目标机器上安装内核头文件包。

解决

    libbpf + CO-RE 正是解决上述问题而提出的方案,即一次编译即可到处运行,BPF CO-RE (Compile Once – Run Everywhere)[3]介绍了此方案的实现细节。简单的来说,就是在加载BPF程序时通过BTF(包含内核信息的文件类型格式)来知晓内核结构的相关信息。但是,BTF需要在目标内核编译时配置CONFIG_DEBUG_INFO_BTF=y 才能提供,因而一旦目标系统的内核没有开启此选项,那么加载BPF程序将找不到BTF,也就无法实现CO-RE。

    一种解决方案是使用事先生成好的目标内核的BTF文件,连同BPF程序一起发布,在BPF程序加载时指定自带的BTF文件路径。而这种方案的所面临的的问题在于,内核版本众多,需要为所有目标内核制作其BTF文件;二是制作出来的BTF文件大小虽说只有几M,但是当目标内核很多时,累加后的BTF集大小也很大。为此,有以下解决方案:

  • btfhub 一个已经为众多内核生成其对应的BTF文件,比如centos7,8, ubuntu等,详情见仓库[4].

  • btfgen 为BPF程序生成最小化的BTF文件,只保留BTF文件中bpf程序使用的那部分,详情见仓库[5].

图片来源: BTFGen: One Step Closer to Truly Portable eBPF Programs

使用btfgen/bpftool

btfgen和bpftool都可以用于生成最小化的BTF文件。其实本质上两者是一个项目,现在btfgen已经合入bpftool,作为其一个子功能,原项目也不再维护。

btfgen

编译安装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
git clone https://github.com/kinvolk/btfgen.git --recursive
cd btfgen
make
./btfgen --help
Usage: btfgen [OPTION...]

  -i, --input=input          dir with source BTF files to use
      --object=object        path of object file to generate BTFs for
  -o, --output=output        dir to output the result BTF files
  -v, --verbose              display libbpf debug messages
  -?, --help                 Give this help list
      --usage                Give a short usage message

Mandatory or optional arguments to long options are also mandatory or optional

使用之:

1
2
3
./btfgen --inputdir=/tmp/demo/input \
          --outputdir=/tmp/demo/min_btf_out \
          --object=/home/anolis/dev/tcpstates/tcpstates.bpf.o 

bpftool

btfhub里包含了一个使用bpftool生成最小化btf的脚本.

见: https://github.com/kinvolk/inspektor-gadget/blob/v0.4.2/tools/btfgen.sh

目前btfgen已经合并到bpftool,可以使用bpftool来生成最小化BTF文件.

1
2
3
4
5
git clone --recurse-submodules https://github.com/libbpf/bpftool.git
git submodule update --init
cd src
make 
make install 

使用之:

1
2
3
bpftool gen min_core_btf /tmp/demo/input/vmlinux.btf \
/tmp/demo/min_btf_out/vmlinux.btf \
/home/anolis/dev/tcpstates/tcpstates.bpf.o 

在代码中使用生成后的最小化BTF文件:

1
2
 LIBBPF_OPTS(bpf_object_open_opts, open_opts, 
 .btf_custom_path = "/tmp/demo/min_btf_out/vmlinux.btf");

重新编译运行:

1
2
3
4
5
6
7
8
[root@localhost build]# ./tcpstates 
SKADDR           PID     COMM       LADDR           LPORT RADDR           RPORT OLDSTATE    -> NEWSTATE    MS
ffff96d21a693600 1099095 node       192.168.107.181 0     20.50.73.10     443   CLOSE       -> SYN_SENT    0.000
ffff96d21a693600 0       swapper/3  192.168.107.181 40404 20.50.73.10     443   SYN_SENT    -> ESTABLISHED 229.687
ffff96d21a693600 0       swapper/3  192.168.107.181 40404 20.50.73.10     443   ESTABLISHED -> CLOSE_WAIT  951.627
ffff96d21a693600 1099095 node       192.168.107.181 40404 20.50.73.10     443   CLOSE_WAIT  -> LAST_ACK    1.482
ffff96d21a693600 1099095 node       192.168.107.181 40404 20.50.73.10     443   LAST_ACK    -> LAST_ACK    0.165
ffff96d21a693600 1099038 node       192.168.107.181 40404 20.50.73.10     443   LAST_ACK    -> CLOSE       0.067

参考链接

  1. BTFGen: 让 eBPF 程序可移植发布更近一步 - 深入浅出eBPF

  2. kinvolk/btfgen

  3. BPF CO-RE (Compile Once – Run Everywhere)

  4. GitHub - aquasecurity/btfhub: BTFhub, in collaboration with the BTFhub Archive repository, supplies BTF files for all published kernels that lack native support for embedded BTF. This joint effort ensures that even kernels without built-in BTF support can effectively leverage the benefits of eBPF programs, promoting compatibility across various kernel versions.

  5. kinvolk/btfgen

Licensed under CC BY-NC-SA 4.0
哦吼是一首歌。
Built with Hugo
Theme Stack designed by Jimmy