eBPF Talk: bpfsnoop v0.5.0 发布:实现 bpf 版本的 funcgraph 功能
文章目录
bpfsnoop 是一款 bpf 时代的现代化内核函数、内核跟踪点和 bpf 程序的动态追踪工具。
bpfsnoop 发布 v0.5.0 版本,主要更新如下:
- 使用
fentry和fexit实现 bpf 版本的 funcgraph 功能。 - 给
--output-arg新增大量的内置函数。 --filter-pkt和--output-pkt支持xdp_frame参数。- 为每个 tracee 引入 insn/fgraph/stack/lbr/both/pkt 等模式,各不干扰。
bpfsnoop 官网 bpfsnoop.com
1. 使用 fentry 和 fexit 实现 bpf 版本的 funcgraph 功能
先看效果,比如内核协议栈发包时的部分函数调用路径:

P.S. 这是在 v5.15 内核上运行命令 ./bpfsnoop -k '(g)tcp_connect' --fgraph-max-depth 20 --fgraph-include '*:skb' 的结果;在不同版本的内核上运行该命令会有不同的结果。
为 funcgraph 功能新增如下命令行选项:
--output-fgraph:启用 funcgraph 功能。--fgraph-max-depth:设置 funcgraph 的最大深度,默认为 5。--fgraph-exclude:设置 funcgraph 的路径排除规则,查找时会忽略匹配的函数。--fgraph-include:设置 funcgraph 的路径包含规则,在排除规则之外,查找时只包含匹配的函数。--fgraph-extra:设置 funcgraph 的额外匹配规则,同时会应用以上的包含和排除规则。--fgraph-proto: 类似--show-func-proto,输出 funcgraph 的函数调用路径。
因为 funcgraph 功能无法跟踪间接调用的函数,所以在使用时需要注意:
- 该功能有可能导致内核崩溃。
- 没有间接调用的函数的输出结果。
因此,可以使用 --fgraph-extra 选项来添加额外的匹配规则,来跟踪可能被间接调用的函数。
特别:
--fgraph-max-depth选项的最大值为 500,足以覆盖内核的最大函数调用深度。- 巧妙地规避 funcgraph 带来的观察者效应。
- 尽力降低 funcgraph 功能导致内核崩溃的可能性。
推荐:在虚拟机里用来研究内核。
警告:因内核缺陷,使用该功能可能会导致内核挂起/崩溃。
2. 给 --output-arg 新增大量的内置函数
新增以下内置函数,供 --output-arg 选项使用:
pkt: 将一段内核内存使用gopacket解析成网络包。eth/ip4/ip6: 将一段内核内存解析成一个以太网/IPv4/IPv6 地址。eth2/ip42/ip62: 将一段内核内存解析成两个连续的以太网/IPv4/IPv6 地址。port: 将一段内核内存解析成一个端口号。port2: 将一段内核内存解析成两个连续的端口号。slice: 将一段内核内存解析成一个 BTF 类型切片。hex: 将一段内核内存解析成一个十六进制字符串。u8/u16/u32/u64: 将一段内核内存解析成一个无符号整数。s8/s16/s32/s64: 将一段内核内存解析成一个有符号整数。le16/le32/le64: 将一段内核内存解析成一个小端无符号整数。be16/be32/be64: 将一段内核内存解析成一个大端无符号整数。
新增这些内置函数后,--output-arg 选项的使用更加灵活和强大。
使用范例:eBPF Talk: 使用 bpfsnoop 调试 i40e 驱动丢包问题
3. --filter-pkt 和 --output-pkt 支持 xdp_frame 参数
对于网卡驱动,在运行 driver 模式的 XDP 程序之后,可能会将 xdp_buff 转换成 xdp_frame:
|
|
因此,在对网络驱动进行调试时,可以使用 xdp_frame 作为 --filter-pkt 和 --output-pkt 的对象。
4. 为每个 tracee 引入 insn/fgraph/stack/lbr/both/pkt 等模式,各不干扰
-k 选项支持:
(i): insn 模式,动态追踪内核函数的所有指令。(g): fgraph 模式,动态追踪内核函数的函数调用路径。(s): stack 模式,动态追踪内核函数的调用栈。(l): lbr 模式,动态追踪内核函数的 LBR 记录。(b): both 模式,同时使用fentry和fexit动态追踪内核函数。(p): pkt 模式,即--output-pkt选项,输出网络包的五元组信息。
-p 选项支持:
(g): fgraph 模式,动态追踪 bpf 程序的函数调用路径。(s): stack 模式,动态追踪 bpf 程序的调用栈。(l): lbr 模式,动态追踪 bpf 程序的 LBR 记录。(b): both 模式,同时使用fentry和fexit动态追踪 bpf 程序。(p): pkt 模式,即--output-pkt选项,输出 bpf 程序处理的网络包信息。
-t 选项支持:
(s): stack 模式,动态追踪内核跟踪点的调用栈。(l): lbr 模式,动态追踪内核跟踪点的 LBR 记录。(p): pkt 模式,即--output-pkt选项,输出内核跟踪点处理的网络包信息。
当 bpfsnoop 用来调试比较复杂的内核问题时,就需要针对不同的 tracee 使用不同的模式。
总结
bpfsnoop v0.5.0 版本实现了 bpf 版本的 funcgraph 功能,并新增了大量的内置函数供 --output-arg 使用。
bpfsnoop 是一款 bpf 时代的现代化内核函数、内核跟踪点和 bpf 程序的动态追踪工具:
- 支持输出 LBR 记录。
- 支持反汇编内核函数和 bpf prog。
- 支持输出函数调用栈。
- 支持输出带类型信息的参数和带类型的返回值。
- 支持使用复杂的 C 表达式来过滤函数参数的属性。
- 支持根据函数参数来过滤需要动态追踪的内核函数列表。
- 支持使用 pcap-filter(7) 语法来过滤网络包。
- 支持
--output-pkt输出网络包里的五元组信息。 - 支持动态追踪多达 12 个参数的内核函数。
- 支持
--output-arg来输出函数参数的属性,类似于--filter-arg。 - 支持
--output-flamegraph来输出火焰图的折叠后的数据。 - 支持
-t来动态追踪内核跟踪点。 - 在
-k里支持 ‘(i)’ 前缀来动态追踪内核函数的所有指令。 - 支持
--output-arg使用大量内置函数来解析内核内存。 - 支持
--output-fgraph来动态追踪内核函数的调用路径。
未来将支持更多高级功能,敬请期待!
bpfsnoop 项目地址:bpfsnoop。
文章作者 Leon Hwang
上次更新 2025-07-21