Berkeley Packet Filter, BPF 提供了强大的网络包过滤规则,可以确定应该检查哪些流量、忽略哪些流量等,而内核近几年发展的 Extended BPF, eBPF 实际上将应用范围,处理效率进行了更新。
eBPF 是 Linux 内核近几年最为引人注目的特性之一,通过一个内核内置的字节码虚拟机,完成数据包过滤、调用栈跟踪、耗时统计、热点分析等等高级功能。
简介
BPF 的目的是尽量早的过滤掉不需要的报文,所以,会通过用户空间的一些工具 (例如 tcpdump),通过 bpf()
系统 API 将指令发送到内核。而内核为了防止恶意代码,会先进行静态扫描,然后再加载运行。
最开始的 BPF 只用于网络包的过滤,而过滤器的执行是基于寄存器的虚拟机。
BPF
实际上 tcpdump 命令所使用的 libpcap 库是基于 BPF 的,在使用相关参数过滤报文时 (例如 host 192.168.1.1
tcp and port 80
等),这些表达式会被编译成 BPF 指令。
可以通过 -d
参数,将对应的指令显示出来。
# tcpdump -d -i eth0 tcp and port 80
eBPF
原有的 BPF(Classic BPF, cBPF) 依然支持,而 eBPF 设计了更丰富的指令集、增加了寄存器,更接近于真实硬件,性能大幅提高。
The original patch that added support for eBPF in the 3.15 kernel showed that eBPF was up to four times faster on x86-64 than the old classic BPF (cBPF) implementation for some network filter microbenchmarks, and most were 1.5 times faster.
RHEL 8 采用的是 4.18 内核版本,支持 eBPF、cgroup V2 等比较新的特性,对于 CentOS 7 来说,需要先升级内核版本以及开发库。
调试工具
使用 bpftool
工具可以查看当前已经加载的 eBPF 程序,通过 yum install bpftool
命令安装,不过要注意内核版本。
在最新的内核源码里应该包含了该工具的源码,需要手动编译,也可以使用 bcc-tools
中的 /usr/share/bcc/tools/bpflist
命令查看。
# /usr/share/bcc/tools/bpflist
PID COMM TYPE COUNT
13159 killsnoop prog 2
13159 killsnoop map 2
示例
在内核代码的 samples/bpf
目录下,包含了一个 libbpf 的库,可以不用直接调用 bpf() 接口。
参考
- 性能分析的大牛 Brendan Gregg 提供了很多参考资料,包括了 Linux Extended BPF Tracing Tools 以及 Golang bcc/BPF Function Tracing 。