深入理解 BPF:一个阅读清单
~ 更新于 2017-11-02 ~
什么是 BPF?
BPF,及 伯克利包过滤器 B erkeley P acket F ilter ,最初构想提出于 1992 年,其目的是为了提供一种过滤包的方法,并且要避免从内核空间到用户空间的无用的数据包复制行为。它最初是由从用户空间注入到内核的一个简单的字节码构成,它在那个位置利用一个校验器进行检查 —— 以避免内核崩溃或者安全问题 —— 并附着到一个套接字上,接着在每个接收到的包上运行。几年后它被移植到 Linux 上,并且应用于一小部分应用程序上(例如,tcpdump
)。其简化的语言以及存在于内核中的即时编译器(JIT),使 BPF 成为一个性能卓越的工具。
然后,在 2013 年,Alexei Starovoitov 对 BPF 进行彻底地改造,并增加了新的功能,改善了它的性能。这个新版本被命名为 eBPF (意思是 “extended BPF”),与此同时,将以前的 BPF 变成 cBPF(意思是 “classic” BPF)。新版本出现了如映射和 尾调用 tail call 这样的新特性,并且 JIT 编译器也被重写了。新的语言比 cBPF 更接近于原生机器语言。并且,在内核中创建了新的附着点。
感谢那些新的钩子,eBPF 程序才可以被设计用于各种各样的情形下,其分为两个应用领域。其中一个应用领域是内核跟踪和事件监控。BPF 程序可以被附着到探针(kprobe),而且它与其它跟踪模式相比,有很多的优点(有时也有一些缺点)。
另外一个应用领域是网络编程。除了套接字过滤器外,eBPF 程序还可以附加到 tc(Linux 流量控制工具)的入站或者出站接口上,以一种很高效的方式去执行各种包处理任务。这种使用方式在这个领域开创了一个新的天地。
并且 eBPF 通过使用为 IO Visor 项目开发的技术,使它的性能进一步得到提升:也为 XDP(“eXpress Data Path”)添加了新的钩子,XDP 是不久前添加到内核中的一种新式快速路径。XDP 与 Linux 栈组合,然后使用 BPF ,使包处理的速度更快。
甚至一些项目,如 P4、Open vSwitch,考虑 或者开始去接洽使用 BPF。其它的一些,如 CETH、Cilium,则是完全基于它的。BPF 是如此流行,因此,我们可以预计,不久之后,将围绕它有更多工具和项目出现 …
深入理解字节码
就像我一样:我的一些工作(包括 BEBA)是非常依赖 eBPF 的,并且在这个网站上以后的几篇文章将关注于这个主题。按理说,在深入到细节之前,我应该以某种方式去介绍 BPF —— 我的意思是,真正的介绍,在第一节所提供的简要介绍上更多地介绍在 BPF 上开发的新功能:什么是 BPF 映射?尾调用?内部结构是什么样子?等等。但是,在这个网站上已经有很多这个主题的介绍了,而且,我也不希望去写另一篇 “BPF 介绍” 的重复文章。
毕竟,我花费了很多的时间去阅读和学习关于 BPF 的知识,因此,在这里我们将要做什么呢,我收集了非常多的关于 BPF 的阅读材料:介绍、文档,也有教程或者示例。这里有很多的材料可以去阅读,但是,为了去阅读它,首先要去 找到 它。因此,为了能够帮助更多想去学习和使用 BPF 的人,现在的这篇文章给出了一个资源清单。这里有各种阅读材料,它可以帮你深入理解内核字节码的机制。
资源
简介
这篇文章中下面的链接提供了 BPF 的基本概述,或者,一些与它密切相关的一些主题。如果你对 BPF 非常陌生,你可以在这些介绍文章中挑选出一篇你喜欢的文章去阅读。如果你已经理解了 BPF,你可以针对特定的主题去阅读,下面是阅读清单。
关于 BPF
关于 eBPF 的常规介绍:
- 全面介绍 eBPF(Matt Flemming,on LWN.net,December 2017): 一篇写的很好的,并且易于理解的,介绍 eBPF 子系统组件的概述文章。
- 利用 BPF 和 XDP 实现可编程的内核网络数据路径 (Daniel Borkmann, OSSNA17, Los Angeles, September 2017): 快速理解所有的关于 eBPF 和 XDP 的基础概念的最好讲稿中的一篇(主要是关于网络处理的)
- BSD 包过滤器 (Suchakra Sharma, June 2017): 一篇非常好的介绍文章,主要是关于跟踪方面的。
- BPF:跟踪及更多(Brendan Gregg, January 2017): 主要内容是跟踪使用案例相关的。
- Linux BPF 的超强功能 (Brendan Gregg, March 2016): 第一部分是关于 火焰图 flame graph 的使用。
- IO Visor(Brenden Blanco, SCaLE 14x, January 2016): 介绍了 IO Visor 项目。
- 大型机上的 eBPF(Michael Holzheu, LinuxCon, Dubin, October 2015)
- 在 Linux 上新的(令人激动的)跟踪新产品(Elena Zannoni, LinuxCon, Japan, 2015)
- BPF — 内核中的虚拟机(Alexei Starovoitov, February 2015): eBPF 的作者写的一篇讲稿。
- 扩展 extended BPF (Jonathan Corbet, July 2014)
BPF 内部结构:
- Daniel Borkmann 正在做的一项令人称奇的工作,它用于去展现 eBPF 的 内部结构,尤其是,它的关于 随同 tc 使用 的几次演讲和论文。
- 使用 tc 的 cls_bpf 的高级可编程和它的最新更新(netdev 1.2, Tokyo, October 2016): Daniel 介绍了 eBPF 的细节,及其用于隧道和封装、直接包访问和其它特性。
- 自 netdev 1.1 以来的 cls_bpf/eBPF 更新 (netdev 1.2, Tokyo, October 2016, part of this tc workshop)
- 使用 cls_bpf 实现完全可编程的 tc 分类器 (netdev 1.1, Sevilla, February 2016): 介绍 eBPF 之后,它提供了许多 BPF 内部机制(映射管理、尾调用、校验器)的见解。对于大多数有志于 BPF 的人来说,这是必读的!全文在这里。
- Linux tc 和 eBPF (fosdem16, Brussels, Belgium, January 2016)
- eBPF 和 XDP 攻略和最新更新 (fosdem17, Brussels, Belgium, February 2017) 这些介绍可能是理解 eBPF 内部机制设计与实现的最佳文档资源之一。
IO Visor 博客 有一些关于 BPF 的值得关注技术文章。它们中的一些包含了一点营销讨论。
内核跟踪:总结了所有的已有的方法,包括 BPF:
- 邂逅 eBPF 和内核跟踪 (Viller Hsiao, July 2016): Kprobes、uprobes、ftrace
- Linux 内核跟踪(Viller Hsiao, July 2016): Systemtap、Kernelshark、trace-cmd、LTTng、perf-tool、ftrace、hist-trigger、perf、function tracer、tracepoint、kprobe/uprobe …
关于 事件跟踪和监视,Brendan Gregg 大量使用了 eBPF,并且就其使用 eBPFR 的一些案例写了极好的文档。如果你正在做一些内核跟踪方面的工作,你应该去看一下他的关于 eBPF 和火焰图相关的博客文章。其中的大多数都可以 从这篇文章中 访问,或者浏览他的博客。
介绍 BPF,也介绍 Linux 网络的一般概念:
- Linux 网络详解 (Thomas Graf, LinuxCon, Toronto, August 2016)
- 内核网络攻略 (Thomas Graf, LinuxCon, Seattle, August 2015)
硬件 卸载 offload (LCTT 译注:“卸载”是指原本由软件来处理的一些操作交由硬件来完成,以提升吞吐量,降低 CPU 负荷。):
- eBPF 与 tc 或者 XDP 一起支持硬件卸载,开始于 Linux 内核版本 4.9,是由 Netronome 提出的。这里是关于这个特性的介绍:eBPF/XDP 硬件卸载到 SmartNICs(Jakub Kicinski 和 Nic Viljoen, netdev 1.2, Tokyo, October 2016)
- 一年后出现的更新版: 综合 XDP 卸载——处理边界案例(Jakub Kicinski 和 Nic Viljoen,netdev 2.2 ,Seoul,November 2017)
- 我现在有一个简短的,但是在 2018 年的 FOSDEM 上有一个更新版: XDP 硬件卸载的挑战(Quentin Monnet,FOSDEM 2018,Brussels,February 2018)
关于 cBPF:
- BSD 包过滤器:一个用户级包捕获的新架构 (Steven McCanne 和 Van Jacobson, 1992): 它是关于(经典)BPF 的最早的论文。
- BPF 的 FreeBSD 手册 是理解 cBPF 程序有用的资源。
- 关于 cBPF,Daniel Borkmann 做至少两个演讲,一是,在 2013 年 mmap 中,BPF 和 Netsniff-NG,以及 在 2014 中关于 tc 和 cls_bpf 的的一个非常完整的演讲。
- 在 Cloudflare 的博客上,Marek Majkowski 提出的他的 与 iptables 的
xt_bpf
模块一起使用 BPF 字节码。值得一提的是,从 Linux 内核 4.10 开始,eBPF 也是通过这个模块支持的。(虽然,我并不知道关于这件事的任何讨论或者文章) - Libpcap 过滤器语法
关于 XDP
在 IO Visor 网站上的 XDP 概述。
eXpress Data Path (XDP) (Tom Herbert, Alexei Starovoitov, March 2016): 这是第一个关于 XDP 的演讲。
BoF - BPF 能为你做什么? (Brenden Blanco, LinuxCon, Toronto, August 2016)。
eXpress Data Path (Brenden Blanco, Linux Meetup at Santa Clara, July 2016): 包含一些(有点营销的意思?)基准测试结果!使用单一核心:
- ip 路由丢弃: ~3.6 百万包每秒(Mpps)
- 使用 BPF,tc(使用 clsact qdisc)丢弃: ~4.2 Mpps
- 使用 BPF,XDP 丢弃:20 Mpps (CPU 利用率 < 10%)
- XDP 重写转发(在端口上它接收到的包):10 Mpps(测试是用 mlx4 驱动程序执行的)。
Jesper Dangaard Brouer 有几个非常好的幻灯片,它可以从本质上去理解 XDP 的内部结构。
- XDP − eXpress Data Path,介绍及将来的用法 (September 2016): “Linux 内核与 DPDK 的斗争” 。未来的计划(在写这篇文章时)它用 XDP 和 DPDK 进行比较。
- 网络性能研讨 (netdev 1.2, Tokyo, October 2016): 关于 XDP 内部结构和预期演化的附加提示。
- XDP – eXpress Data Path, 可用于 DDoS 防护 (OpenSourceDays, March 2017): 包含了关于 XDP 的详细情况和使用案例,以及 性能测试 的 性能测试结果 和 代码片断,以及使用 eBPF/XDP(基于一个 IP 黑名单模式)的用于 基本的 DDoS 防护。
- 内存 vs. 网络,激发和修复内存瓶颈 (LSF Memory Management Summit, March 2017): 提供了许多 XDP 开发者当前所面对 内存问题 的许多细节。不要从这一个开始,但如果你已经理解了 XDP,并且想去了解它在页面分配方面的真实工作方式,这是一个非常有用的资源。
- XDP 能为其它人做什么(netdev 2.1, Montreal, April 2017),及 Andy Gospodarek: 普通人怎么开始使用 eBPF 和 XDP。这个演讲也由 Julia Evans 在 她的博客 上做了总结。
- XDP 能为其它人做什么,第二版(netdev 2.2, Seoul, November 2017),同一个作者: 该演讲的修订版本,包含了新的内容。