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
知识星球
星球里的专栏:
《XDP 进阶手册》
