Translated by qhwdw

This commit is contained in:
qhwdw 2018-04-02 13:09:48 +08:00
parent 1b907b07c6
commit ff92e7ea70

View File

@ -63,23 +63,23 @@
# 什么是 BPF? # 什么是 BPF?
BPF是伯克利包过滤器**B**erkeley **P**acket **F**ilter的第一个字母的组合,最初构想于 1992 年,是为了提供一种过滤包的方法,以避免从内核到用户空间的无用的数据包副本。它最初是由从用户空间注入到内核的一个简单的字节码构成,它在哪里通过一个校验器进行检查 — 以避免内核崩溃或者安全问题 — 并附加到一个套接字上,然后运行在每个接收到的包上。几年后它被移植到 Linux 上并且应用于一小部分应用程序上例如tcpdump。简化的语言以及存在于内核中的即时编译器JIT使 BPF 成为一个性能卓越的工具。 BPF是伯克利包过滤器**B**erkeley **P**acket **F**ilter的第一个字母的组合,在 1992 年提出最初的设想,它的目的是为了提供一种过滤包的方法,并且要避免这种从内核空间到用户空间的没用的数据包复制行为。它最初是由从用户空间注入到内核的一个简单的字节码构成,它在那个位置利用一个校验器进行检查 —— 以避免内核崩溃或者安全问题 —— 并附加到一个套接字上,接着在每个接收到的包上运行。几年后它被移植到 Linux 上并且应用于一小部分应用程序上例如tcpdump。简化的语言以及存在于内核中的即时编译器JIT使 BPF 成为一个性能卓越的工具。
然后,在 2013 年Alexei Starovoitov 对 BPF 进行彻底地改造,并增加了新的功能,改善了它的性能。这个新版本被命名为 eBPF (意思是 “extended BPF”同时将以前的变成 cBPF意思是 “classic” BPF。出现了如映射maps和 tail 调用calls。JIT 编译器被重写了。新的语言比 cBPF 更接近于原生机器语言。并且,在内核中创建了新的附加点。 然后,在 2013 年Alexei Starovoitov 对 BPF 进行彻底地改造,并增加了新的功能,改善了它的性能。这个新版本被命名为 eBPF (意思是 “extended BPF”与此同时,将以前的 BPF 变成 cBPF意思是 “classic” BPF。新版本出现了如映射和尾调用这样的新特性并且 JIT 编译器也被重写了。新的语言比 cBPF 更接近于原生机器语言。并且,在内核中创建了新的附加点。
感谢那些新的钩子eBPF 程序才可以被设计用于各种各样的使用案例它分为两个应用领域。其中一个应用领域是内核跟踪和事件监控。BPF 程序可以被附加到 kprobes且它与其它跟踪模式相比,有很多的优点(有时也有一些缺点)。 感谢那些新的钩子eBPF 程序才可以被设计用于各种各样的使用案例它分为两个应用领域。其中一个应用领域是内核跟踪和事件监控。BPF 程序可以被附加到探针,而且它与其它跟踪模式相比,有很多的优点(有时也有一些缺点)。
其它的应用领域是网络程序。除了套接字过滤器eBPF 程序可以附加到 tcLinux 流量控制工具) ingress 或者 egress 接口,并且用一种高效的方式去执行各种包处理任务。它在这个领域打开了一个新的思路 另外一个应用领域是网络编程。除了套接字过滤器外eBPF 程序还可以附加到 tcLinux 流量控制工具)的入站或者出站接口上,以一种很高效的方式去执行各种包处理任务。这种使用方式在这个领域开创了一个新的天地
并且 eBPF 的性能通过为 IO Visor 项目开发的技术进一步得到提升:也为 XDP“eXpress Data Path”增加了新的钩子它是不久前增加到内核中的一种新的快速路径。XDP 与 Linux 栈一起工作,并且依赖 BPF 去执行更快的包处理 并且 eBPF 通过使用为 IO Visor 项目开发的技术,使它的性能进一步得到提升:也为 XDP“eXpress Data Path”添加了新的钩子XDP 是不久前添加到内核中的一种新式快速路径。XDP 与 Linux 栈组合,然后使用 BPF ,使包处理的速度更快
甚至一些项目,如 P4、Open vSwitch、[考虑][155] 或者开始去接近approachBPF。其它的一些如 CETH、Cilium则是完全基于它的。BPF 是如此流行,因此,我们可以预计到不久后,将围绕它有很多工具和项目出现 … 甚至一些项目,如 P4、Open vSwitch[考虑][155] 或者开始去接洽使用 BPF。其它的一些如 CETH、Cilium则是完全基于它的。BPF 是如此流行,因此,我们可以预计,不久之后,将围绕它有更多工具和项目出现 …
# 深入理解字节码 # 深入理解字节码
就像我一样:我的一些工作(包括 [BEBA][156])是非常依赖 eBPF 的,并且在这个网站上以后的几篇文章将关注于这个主题。从逻辑上说,在这篇文章中我在深入到细节之前,希望以某种方式去介绍 BPF — 我的意思是,一个真正的介绍,更多的在 BPF 上开发的功能,它在开始节已经提供了一些简短的摘要:什么是 BPF 映射? Tail 调用?内部结构是什么样子?等等。但是,在这个网站上已经有很多这个主题的介绍了,并且,我也不希望去创建 “另一个 BPF 介绍” 的重复的文章。 就像我一样:我的一些工作(包括 [BEBA][156])是非常依赖 eBPF 的,并且在这个网站上以后的几篇文章将关注于这个主题。这篇文章的基本逻辑是,在深入到细节之前,我希望以某种方式去介绍 BPF —— 我的意思是,更多地介绍在 BPF 上开发的新功能,它在开始节已经提供了一些简短的概述:什么是 BPF 映射?尾调用?内部结构是什么样子?等等。但是,在这个网站上已经有很多这个主题的介绍了,而且,我也不希望去写另一篇 “BPF 介绍” 的重复文章。
毕竟,我花费了很多的时间去阅读和学习关于 BPF 的知识,并且,也是这么做的,因此,在这里我们将要做的是,我收集了非常多的关于 BPF 的阅读材料:介绍、文档、也有教程或者示例。这里有很多的材料可以去阅读,但是,为了去阅读它,首先要去 _找到_ 它。因此,为了能够帮助更多想去学习和使用 BPF 的人,现在的这篇文章是介绍了一个资源列表。这里有各种阅读材料,它可以帮你深入理解内核字节码的机制。 毕竟,我花费了很多的时间去阅读和学习关于 BPF 的知识,因此,在这里我们将要做什么呢,我收集了非常多的关于 BPF 的阅读材料:介绍、文档、也有教程或者示例。这里有很多的材料可以去阅读,但是,为了去阅读它,首先要去 _找到_ 它。因此,为了能够帮助更多想去学习和使用 BPF 的人,现在的这篇文章是介绍了一个资源清单。这里有各种阅读材料,它可以帮你深入理解内核字节码的机制。
# 资源 # 资源
@ -93,10 +93,13 @@ BPF是伯克利包过滤器**B**erkeley **P**acket **F**ilter的第
关于 eBPF 的简介: 关于 eBPF 的简介:
* [*全面介绍 eBPF*][193]Matt Flemmingon LWN.netDecember 2017
一篇写的很好的,并且易于理解的,介绍 eBPF 子系统组件的概述文章。
* [_利用 BPF 和 XDP 实现可编程的内核网络数据路径_][53]  (Daniel Borkmann, OSSNA17, Los Angeles, September 2017): * [_利用 BPF 和 XDP 实现可编程的内核网络数据路径_][53]  (Daniel Borkmann, OSSNA17, Los Angeles, September 2017):
快速理解所有的关于 eBPF 和 XDP 的基础概念的许多文章中的一篇(大多数是关于网络处理的) 快速理解所有的关于 eBPF 和 XDP 的基础概念的许多文章中的一篇(大多数是关于网络处理的)
* [BSD 包过滤器][54] (Suchakra Sharma, June 2017):  * [*BSD 包过滤器*][54] (Suchakra Sharma, June 2017): 
一篇非常好的介绍文章,大多数是关于跟踪方面的。 一篇非常好的介绍文章,大多数是关于跟踪方面的。
* [_BPF跟踪及更多_][55]  (Brendan Gregg, January 2017): * [_BPF跟踪及更多_][55]  (Brendan Gregg, January 2017):
@ -119,7 +122,7 @@ BPF是伯克利包过滤器**B**erkeley **P**acket **F**ilter的第
**BPF 内部结构** **BPF 内部结构**
* Daniel Borkmann 正在做的一项令人称奇的工作,它用于去展现 eBPF 的 **内部结构**特别是通过几次关于 **eBPF 用于 tc **演讲和论文。 * Daniel Borkmann 正在做的一项令人称奇的工作,它用于去展现 eBPF 的 **内部结构**尤其是,它的关于 **eBPF 用于 tc ** 的几次演讲和论文。
* [_使用 tc 的 cls_bpf 的高级可编程和它的最新更新_][30]  (netdev 1.2, Tokyo, October 2016): * [_使用 tc 的 cls_bpf 的高级可编程和它的最新更新_][30]  (netdev 1.2, Tokyo, October 2016):
Daniel 介绍了 eBPF 的细节,它使用了隧道和封装、直接包访问、和其它特性。 Daniel 介绍了 eBPF 的细节,它使用了隧道和封装、直接包访问、和其它特性。
@ -134,7 +137,7 @@ BPF是伯克利包过滤器**B**erkeley **P**acket **F**ilter的第
这些介绍可能是理解 eBPF 内部机制设计与实现的最佳文档资源之一。 这些介绍可能是理解 eBPF 内部机制设计与实现的最佳文档资源之一。
[**IO Visor 博客**][157] 有一些关于 BPF 感兴趣的技术文章。它们中的一些包含了许多营销讨论。 [***IO Visor 博客***][157] 有一些关于 BPF 感兴趣的技术文章。它们中的一些包含了许多营销讨论。
**内核跟踪**:总结了所有的已有的方法,包括 BPF **内核跟踪**:总结了所有的已有的方法,包括 BPF
@ -144,7 +147,7 @@ BPF是伯克利包过滤器**B**erkeley **P**acket **F**ilter的第
* [_Linux 内核跟踪_][63]  (Viller Hsiao, July 2016): * [_Linux 内核跟踪_][63]  (Viller Hsiao, July 2016):
Systemtap、Kernelshark、trace-cmd、LTTng、perf-tool、ftrace、hist-trigger、perf、function tracer、tracepoint、kprobe/uprobe … Systemtap、Kernelshark、trace-cmd、LTTng、perf-tool、ftrace、hist-trigger、perf、function tracer、tracepoint、kprobe/uprobe …
关于 **事件跟踪和监视**Brendan Gregg 使用 eBPF 的一些心得,它使用 eBPFR 的一些案例,他做的非常出色。如果你正在做一些内核跟踪方面的工作,你应该去看一下他的关于 eBPF 和火焰图相关的博客文章。其中的大多数都可以 [从这篇文章中][158] 访问,或者浏览他的博客。 关于 **事件跟踪和监视**Brendan Gregg 使用 eBPF 的一些心得,它使用 eBPFR 的一些案例,他做的非常出色。如果你正在做一些内核跟踪方面的工作,你应该去看一下他的关于 eBPF 和火焰图相关的博客文章。其中的大多数都可以 *[从这篇文章中][158]* 访问,或者浏览他的博客。
介绍 BPF也介绍 **Linux 网络的一般概念** 介绍 BPF也介绍 **Linux 网络的一般概念**
@ -154,24 +157,30 @@ BPF是伯克利包过滤器**B**erkeley **P**acket **F**ilter的第
**硬件 offload**译者注offload 是指原本由软件来处理的一些操作交由硬件来完成,以提升吞吐量,降低 CPU 负荷。): **硬件 offload**译者注offload 是指原本由软件来处理的一些操作交由硬件来完成,以提升吞吐量,降低 CPU 负荷。):
* eBPF 与 tc 或者 XDP 一起支持硬件 offload开始于 Linux 内核版本 4.9,并且由 Netronome 提出的。这里是关于这个特性的介绍:[eBPF/XDP hardware offload to SmartNICs][147] (Jakub Kicinski 和 Nic Viljoen, netdev 1.2, Tokyo, October 2016) * eBPF 与 tc 或者 XDP 一起支持硬件 offload开始于 Linux 内核版本 4.9,并且由 Netronome 提出的。这里是关于这个特性的介绍:[*eBPF/XDP hardware offload to SmartNICs*][147] (Jakub Kicinski 和 Nic Viljoen, netdev 1.2, Tokyo, October 2016)
* 年后出现的更新版:
[*综合的关于 XDP offload 处理边界的案例*][194](Jakub Kicinski 和 Nic Viljoennetdev 2.2 SeoulNovember 2017)
* 我现在有一个简短的,但是在 2018 年的 FOSDEM 上有一个更新版:
[*XDP 硬件 Offload 的挑战*][195](Quentin MonnetFOSDEM 2018BrusselsFebruary 2018)
关于 **cBPF** 关于 **cBPF**
* [_BSD 包过滤器一个用户级包捕获的新架构_][66] (Steven McCanne 和 Van Jacobson, 1992) * [_BSD 包过滤器一个用户级包捕获的新架构_][66] (Steven McCanne 和 Van Jacobson, 1992)
它是关于classicBPF 的最早的论文。 它是关于classicBPF 的最早的论文。
* [关于 BPF 的 FreeBSD 手册][67] 是理解 cBPF 程序的可用资源。 * *[关于 BPF 的 FreeBSD 手册][67]* 是理解 cBPF 程序的可用资源。
* 关于 cBPF,Daniel Borkmann 实现的至少两个演示,[一是,在 2013 年 mmap 中BPF 和 Netsniff-NG][68],以及 [在 2014 中关于 tc 和 cls_bpf 的的一个非常完整的演示][69]。 * 关于 cBPFDaniel Borkmann 实现的至少两个演示,[*一是,在 2013 年 mmap 中BPF 和 Netsniff-NG*][68],以及 *[在 2014 中关于 tc 和 cls_bpf 的的一个非常完整的演示][69]*
* 在 Cloudflare 的博客上Marek Majkowski 提出的它的 [BPF 字节码与 **iptables** 的 `xt_bpf` 模块一起的应用][70]。值得一提的是,从 Linux 内核 4.10 开始eBPF 也是通过这个模块支持的。(虽然,我并不知道关于这件事的任何讨论或者文章) * 在 Cloudflare 的博客上Marek Majkowski 提出的它的 *[BPF 字节码与 **iptables** 的 `xt_bpf` 模块一起的应用][70]*。值得一提的是,从 Linux 内核 4.10 开始eBPF 也是通过这个模块支持的。(虽然,我并不知道关于这件事的任何讨论或者文章)
* [Libpcap 过滤器语法][71] * [*Libpcap 过滤器语法*][71]
### 关于 XDP ### 关于 XDP
* 在 IO Visor 网站上的 [XDP 概述][72]。 * 在 IO Visor 网站上的 *[XDP 概述][72]*
* [_eXpress Data Path (XDP)_][73]  (Tom Herbert, Alexei Starovoitov, March 2016): * [_eXpress Data Path (XDP)_][73]  (Tom Herbert, Alexei Starovoitov, March 2016):
这是第一个关于 XDP 的演示。 这是第一个关于 XDP 的演示。
@ -214,7 +223,7 @@ BPF是伯克利包过滤器**B**erkeley **P**acket **F**ilter的第
### 关于 基于 eBPF 或者 eBPF 相关的其它组件 ### 关于 基于 eBPF 或者 eBPF 相关的其它组件
* [_在边上的 P4_][77]  (John Fastabend, May 2016): * [_在边上的 P4_][77]  (John Fastabend, May 2016):
提出了使用 **P4**,一个包处理的描述语言,使用 BPF 去创建一个高性能的可编程交换机。 提出了使用 **P4**,一个包处理的描述语言,使用 BPF 去创建一个高性能的可编程交换机。
* 如果你喜欢音频的介绍,这里有一个相关的 [OvS Orbit 片断(#11),叫做 _在边缘上的 **P4**_][78],日期是 2016 年 8 月。OvS Orbit 是对 Ben Pfaff 的访谈,它是 Open vSwitch 的其中一个核心维护者。在这个场景中John Fastabend 是被访谈者。 * 如果你喜欢音频的介绍,这里有一个相关的 [OvS Orbit 片断(#11),叫做 _在边缘上的 **P4**_][78],日期是 2016 年 8 月。OvS Orbit 是对 Ben Pfaff 的访谈,它是 Open vSwitch 的其中一个核心维护者。在这个场景中John Fastabend 是被访谈者。
@ -233,34 +242,40 @@ BPF是伯克利包过滤器**B**erkeley **P**acket **F**ilter的第
在不同的演示中重复了大量的内容如果有疑问就选最近的一个。Daniel Borkmann 作为 Google 开源博客的特邀作者,也写了 [Cilium 简介][80]。 在不同的演示中重复了大量的内容如果有疑问就选最近的一个。Daniel Borkmann 作为 Google 开源博客的特邀作者,也写了 [Cilium 简介][80]。
* 这里也有一个关于 **Cilium** 的播客节目:一个 [OvS Orbit episode (#4)][81],它是 Ben Pfaff 访谈 Thomas Graf 2016 年 5 月),和 [另外一个 Ivan Pepelnjak 的播客][82],仍然是 Thomas Graf 的与 eBPF、P4、XDP 和 Cilium 2016 年 10 月)。 * 这里也有一个关于 **Cilium** 的播客节目:一个 *[OvS Orbit episode (#4)][81]*,它是 Ben Pfaff 访谈 Thomas Graf 2016 年 5 月),和 *[另外一个 Ivan Pepelnjak 的播客][82]*,仍然是 Thomas Graf 的与 eBPF、P4、XDP 和 Cilium 2016 年 10 月)。
* **Open vSwitch** (OvS),它是 **Open Virtual Network**OVN一个开源的网络虚拟化解决方案相关的项目正在考虑在不同的层次上使用 eBPF它已经实现了几个概念验证原型 * **Open vSwitch** (OvS),它是 **Open Virtual Network**OVN一个开源的网络虚拟化解决方案相关的项目正在考虑在不同的层次上使用 eBPF它已经实现了几个概念验证原型
* [使用 eBPF 的 Offloading OVS 流处理器][48] (William (Cheng-Chun) Tu, OvS conference, San Jose, November 2016) * [*使用 eBPF 的 Offloading OVS 流处理器*][48] (William (Cheng-Chun) Tu, OvS conference, San Jose, November 2016)
* [将 OVN 的灵活性与 IOVisor 的高效率相结合][49] (Fulvio Risso, Matteo Bertrone and Mauricio Vasquez Bernal, OvS conference, San Jose, November 2016) * *[将 OVN 的灵活性与 IOVisor 的高效率相结合][49]* (Fulvio Risso, Matteo Bertrone and Mauricio Vasquez Bernal, OvS conference, San Jose, November 2016)
据我所知,这些 eBPF 的使用案例看上去仅处于提议阶段(并没有合并到 OvS 的主分支中),但是,看它带来了什么将是非常有趣的事情。 据我所知,这些 eBPF 的使用案例看上去仅处于提议阶段(并没有合并到 OvS 的主分支中),但是,看它带来了什么将是非常有趣的事情。
* XDP 的设计对分布式拒绝访问DDoS攻击是非常有用的。越来越多的演示都关注于它。例如从 Cloudflare 中的人们的讨论([_XDP in practice: integrating XDP in our DDoS mitigation pipeline_][83])或者从 Facebook 上([_Droplet: DDoS countermeasures powered by BPF + XDP_][84])在 netdev 2.1 会议上,在 Montreal、Canada、在 2017 年 4 月,都存在这样的很多使用案例。 * XDP 的设计对分布式拒绝访问DDoS攻击是非常有用的。越来越多的演示都关注于它。例如从 Cloudflare 中的人们的讨论([_XDP in practice: integrating XDP in our DDoS mitigation pipeline_][83])或者从 Facebook 上([_Droplet: DDoS countermeasures powered by BPF + XDP_][84])在 netdev 2.1 会议上,在 Montreal、Canada、在 2017 年 4 月,都存在这样的很多使用案例。
* Kubernetes 可以用很多种方式与 eBPF 交互。这里有一篇关于 *[在 Kubernetes 中使用 eBPF][196]* 的文章,它解释了现有的产品 (CiliumWeave Scope) 如何支持 eBPF 与 Kubernetes 一起工作并且进一步描述了在容器部署环境中eBPF 感兴趣的交互内容是什么。
* [_CETH for XDP_][85] Yan Chan 和 Yunsong Lu、Linux Meetup、Santa Clara、July 2016 * [_CETH for XDP_][85] Yan Chan 和 Yunsong Lu、Linux Meetup、Santa Clara、July 2016
**CETH**,是由 Mellanox 发起的为实现更快的网络 I/O 而主张的通用以太网驱动程序架构。 **CETH**,是由 Mellanox 发起的为实现更快的网络 I/O 而主张的通用以太网驱动程序架构。
* [**VALE 交换机**][86],另一个虚拟交换机,它可以与 netmap 框架结合,有 [一个 BPF 扩展模块][87]。 * [***VALE 交换机***][86],另一个虚拟交换机,它可以与 netmap 框架结合,有 *[一个 BPF 扩展模块][87]*
* **Suricata**,一个开源的入侵检测系统,它的捕获旁通特性 [似乎是依赖于 eBPF 组件][88] * **Suricata**,一个开源的入侵检测系统,它的捕获旁通特性 [*似乎是依赖于 eBPF 组件*][88]
[*Suricate 文档的 eBPF 和 XDP 部分*][197]
[*SEPTun-Mark-II*][198] (Suricata Extreme 性能调优指南 — Mark II)Published by Michal Purzynski 和 Peter Manev in March 2018
[*介绍这个特性的博客文章*][199] Published by Éric Leblond in September 2016
[_The adventures of a Suricate in eBPF land_][89]  (Éric Leblond, netdev 1.2, Tokyo, October 2016) [_The adventures of a Suricate in eBPF land_][89]  (Éric Leblond, netdev 1.2, Tokyo, October 2016)
[_eBPF and XDP seen from the eyes of a meerkat_][90]  (Éric Leblond, Kernel Recipes, Paris, September 2017) [_eBPF and XDP seen from the eyes of a meerkat_][90]  (Éric Leblond, Kernel Recipes, Paris, September 2017)
当使用原生驱动的 XDP 时,这个项目要求实现非常高的性能。
* [InKeV: 对于 DCN 的内核中分布式网络虚拟化][91] (Z. Ahmed, M. H. Alizai and A. A. Syed, SIGCOMM, August 2016): * [*InKeV: 对于 DCN 的内核中分布式网络虚拟化*][91] (Z. Ahmed, M. H. Alizai and A. A. Syed, SIGCOMM, August 2016):
**InKeV** 是一个基于 eBPF 的虚拟网络、目标数据中心网络的数据路径架构。它最初由 PLUMgrid 提出,并且声称相比基于 OvS 的 OpenStack 解决方案可以获得更好的性能。 **InKeV** 是一个基于 eBPF 的虚拟网络、目标数据中心网络的数据路径架构。它最初由 PLUMgrid 提出,并且声称相比基于 OvS 的 OpenStack 解决方案可以获得更好的性能。
* [_**gobpf** - 从 Go 中利用 eBPF_][92] Michael Schubert, fosdem17, Brussels, Belgium, February 2017 * [_**gobpf** - 从 Go 中利用 eBPF_][92] Michael Schubert, fosdem17, Brussels, Belgium, February 2017
“一个从 Go 中的库,可以去创建、加载和使用 eBPF 程序” “一个从 Go 中的库,可以去创建、加载和使用 eBPF 程序”
* [**ply**][93] 是为 Linux 实现的一个小的但是非常灵活的开源动态 **跟踪器**,它的一些特性非常类似于 bcc 工具,是受 awk 和 dtrace 启发,但使用一个更简单的语言。它是由 Tobias Waldekranz 写的。 * [***ply***][93] 是为 Linux 实现的一个小的但是非常灵活的开源动态 **跟踪器**,它的一些特性非常类似于 bcc 工具,是受 awk 和 dtrace 启发,但使用一个更简单的语言。它是由 Tobias Waldekranz 写的。
* 如果你读过我以前的文章,你可能对我在这篇文章中的讨论感兴趣,[使用 eBPF 实现 OpenState 接口][151],关于包状态处理,在 fosdem17 中。 * 如果你读过我以前的文章,你可能对我在这篇文章中的讨论感兴趣,[使用 eBPF 实现 OpenState 接口][151],关于包状态处理,在 fosdem17 中。
@ -272,33 +287,33 @@ BPF是伯克利包过滤器**B**erkeley **P**acket **F**ilter的第
### 关于 BPF ### 关于 BPF
* **BPF 的规范**(包含 classic 和 extended 版本)可以在 Linux 内核的文档中,和特定的文件 [linux/Documentation/networking/filter.txt][94] 中找到。BPF 使用以及它的内部结构也被记录在那里。此外,当加载 BPF 代码失败时,在这里可以找到 **被校验器抛出的错误信息**,这有助于你排除不明确的错误信息。 * **BPF 的规范**(包含 classic 和 extended 版本)可以在 Linux 内核的文档中,和特定的文件 *[linux/Documentation/networking/filter.txt][94]* 中找到。BPF 使用以及它的内部结构也被记录在那里。此外,当加载 BPF 代码失败时,在这里可以找到 **被校验器抛出的错误信息**,这有助于你排除不明确的错误信息。
* 此外,在内核树中,在 eBPF 那里有一个关于 **常见的问 & 答** 的文档,它在文件 [linux/Documentation/bpf/bpf_design_QA.txt][95] 中。 * 此外,在内核树中,在 eBPF 那里有一个关于 **常见的问 & 答** 的文档,它在文件 [*linux/Documentation/bpf/bpf_design_QA.txt*][95] 中。
* … 但是,内核文档是非常难懂的,并且非常不容易阅读。如果你只是去查找一个简单的 eBPF 语言的描述,可以去 IO Visor 的 GitHub 仓库,那儿有 [它的 **概括性描述**][96]。 * … 但是,内核文档是非常难懂的,并且非常不容易阅读。如果你只是去查找一个简单的 eBPF 语言的描述,可以去 IO Visor 的 GitHub 仓库,那儿有 [***它的概括性描述***][96]。
* 顺便说一下IO Visor 项目收集了许多 **关于 BPF 的资源**。大部分,分别在 bcc 仓库的 [文档目录][97] 中,和 [bpf-docs 仓库][98] 的整个内容中,它们都在 GitHub 上。注意,这个非常好的 [BPF **参考指南**][99] 包含一个详细的 BPF C 和 bcc Python 的 helper 的描述。 * 顺便说一下IO Visor 项目收集了许多 **关于 BPF 的资源**。大部分,分别在 bcc 仓库的 *[文档目录][97]* 中,和 *[bpf-docs 仓库][98]* 的整个内容中,它们都在 GitHub 上。注意,这个非常好的 *[BPF **参考指南**][99]* 包含一个详细的 BPF C 和 bcc Python 的 helper 的描述。
* 想深入到 BPF那里有一些必要的 **Linux 手册页**。第一个是 [`bpf(2)` man page][100] 关于 `bpf()` **系统调用**,它用于从用户空间去管理 BPF 程序和映射。它也包含一个 BPF 高级特性的描述(程序类型、映射、等等)。第二个是主要去处理希望去附加到 tc 接口的 BPF 程序:它是 [`tc-bpf(8)` man page][101],它是 **使用 BPF 和 tc** 的一个参考,并且包含一些示例命令和参考代码。 * 想深入到 BPF那里有一些必要的 **Linux 手册页**。第一个是 [*`bpf(2)` man 页面*][100] 关于 `bpf()` **系统调用**,它用于从用户空间去管理 BPF 程序和映射。它也包含一个 BPF 高级特性的描述(程序类型、映射、等等)。第二个是主要去处理希望去附加到 tc 接口的 BPF 程序:它是 [*`tc-bpf(8)` man 页面*][101],它是 **使用 BPF 和 tc** 的一个参考,并且包含一些示例命令和参考代码。
* Jesper Dangaard Brouer 发起了一个 **更新 eBPF Linux 文档** 的尝试,包含 **不同的映射**。[他有一个草案][102],欢迎去贡献。一旦完成,这个文档将被合并进 man 页面并且进入到内核文档。 * Jesper Dangaard Brouer 发起了一个 **更新 eBPF Linux 文档** 的尝试,包含 **不同的映射**。[*他有一个草案*][102],欢迎去贡献。一旦完成,这个文档将被合并进 man 页面并且进入到内核文档。
* Cilium 项目也有一个非常好的 [**BPF 和 XDP 参考指南**][103],它是由核心的 eBPF 开发者写的,它被证明对于 eBPF 开发者是极其有用的。 * Cilium 项目也有一个非常好的 [***BPF 和 XDP 参考指南***][103],它是由核心的 eBPF 开发者写的,它被证明对于 eBPF 开发者是极其有用的。
* David Miller 在 [xdp-newbies][152] 邮件列表中发了几封关于 eBPF/XDP 内部结构的富有启发性的电子邮件。我找不到一个单独的地方收集它们的链接,因此,这里是一个列表: * David Miller 在 *[xdp-newbies][152]* 邮件列表中发了几封关于 eBPF/XDP 内部结构的富有启发性的电子邮件。我找不到一个单独的地方收集它们的链接,因此,这里是一个列表:
* [bpf.h 和你 …][50] * [*bpf.h 和你 …*][50]
* [Contextually speaking…][51] * [*Contextually speaking…*][51]
* [BPF 校验器概述][52] * [*BPF 校验器概述*][52]
最后一个可能是目前来说关于校验器的最佳的总结。 最后一个可能是目前来说关于校验器的最佳的总结。
* Ferris Ellis 发布的 [一个关于 **eBPF 的系列博客文章**][104]。作为我写的这个短文,第一篇文章是关于 eBPF 的历史背景和未来期望。接下来的文章将更多的是技术方面,和前景展望。 * Ferris Ellis 发布的 *[一个关于 **eBPF 的系列博客文章**][104]*。作为我写的这个短文,第一篇文章是关于 eBPF 的历史背景和未来期望。接下来的文章将更多的是技术方面,和前景展望。
* [一个 **每个内核版本的 BPF 特性列表**][153] 在 bcc 仓库中可以找到。如果你想去知道运行一个给定的特性所要求的最小的内核版本,它是非常有用的。我贡献和添加了链接到提交中,它介绍了每个特性,因此,你也可以从那里很容易地去访问提交历史。 * [***一个每个内核版本的 BPF 特性列表***][153] 在 bcc 仓库中可以找到。如果你想去知道运行一个给定的特性所要求的最小的内核版本,它是非常有用的。我贡献和添加了链接到提交中,它介绍了每个特性,因此,你也可以从那里很容易地去访问提交历史。
### 关于 tc ### 关于 tc
@ -306,36 +321,36 @@ BPF是伯克利包过滤器**B**erkeley **P**acket **F**ilter的第
* 找到关于 **Linux 上 QoS** 的简单教程是很困难的。这里有两个链接,它们很长而且很难懂,但是,如果你可以抽时间去阅读它,你将学习到几乎关于 tc 的任何东西(虽然,关于 BPF 它什么也没有)。它们在这里:[_怎么去实现流量控制_  (Martin A. Brown, 2006)][105],和 [_怎么去实现 Linux 的高级路由 & 流量控制_  (“LARTC”) (Bert Hubert & al., 2002)][106]。 * 找到关于 **Linux 上 QoS** 的简单教程是很困难的。这里有两个链接,它们很长而且很难懂,但是,如果你可以抽时间去阅读它,你将学习到几乎关于 tc 的任何东西(虽然,关于 BPF 它什么也没有)。它们在这里:[_怎么去实现流量控制_  (Martin A. Brown, 2006)][105],和 [_怎么去实现 Linux 的高级路由 & 流量控制_  (“LARTC”) (Bert Hubert & al., 2002)][106]。
* 在你的系统上的 **tc 手册页面** 并不是最新日期的,因为它们中的几个最近已经增加了。如果你没有找到关于特定的队列规则、分类或者过滤器的文档,它可能在最新的 [tc 组件的手册页面][107] 中。 * 在你的系统上的 **tc 手册页面** 并不是最新日期的,因为它们中的几个最近已经增加了。如果你没有找到关于特定的队列规则、分类或者过滤器的文档,它可能在最新的 *[tc 组件的手册页面][107]* 中。
* 一些额外的材料可以在 iproute2 包自已的文件中找到:这个包中有 [一些文档][108],包括一些文件,它可以帮你去理解 [**tc 的 action** 的功能][109]。 * 一些额外的材料可以在 iproute2 包自已的文件中找到:这个包中有 [*一些文档*][108],包括一些文件,它可以帮你去理解 *[**tc 的 action** 的功能][109]*
**注意:** 这些文件在 2017 年 10 月 已经从 iproute2 中删除,然而,从 Git 历史中却一直可用。 **注意:** 这些文件在 2017 年 10 月 已经从 iproute2 中删除,然而,从 Git 历史中却一直可用。
* 非精确资料:这里是 [一个关于 tc 的几个特性的研讨会][110]包含过滤、BPF、tc offload、… 由 Jamal Hadi Salim 在 netdev 1.2 会议上组织的October 2016 * 非精确资料:这里是 [*一个关于 tc 的几个特性的研讨会*][110]包含过滤、BPF、tc offload、… 由 Jamal Hadi Salim 在 netdev 1.2 会议上组织的October 2016
* 额外信息 — 如果你使用 `tc` 较多,这里有一些好消息:我用这个工具 [写了一个 bash 完整的功能][111],并且它被包 iproute2 带到内核版本 4.6 和更高版中! * 额外信息 — 如果你使用 `tc` 较多,这里有一些好消息:我用这个工具 *[写了一个 bash 完整的功能][111]*,并且它被包 iproute2 带到内核版本 4.6 和更高版中!
### 关于 XDP ### 关于 XDP
* 对于 XDP 的一些 [进展中的文档(包括规范)][112] 已经由 Jesper Dangaard Brouer 启动并且意味着将成为一个合作的工作。正在推进2016 年 9 月你期望它去改变并且或许在一些节点上移动Jesper [称为贡献][113],如果你想去改善它)。 * 对于 XDP 的一些 *[进展中的文档(包括规范)][112]* 已经由 Jesper Dangaard Brouer 启动并且意味着将成为一个合作的工作。正在推进2016 年 9 月你期望它去改变并且或许在一些节点上移动Jesper *[称为贡献][113]*,如果你想去改善它)。
* 自来 Cilium 项目的 [BPF 和 XDP 参考指南][114] … 好吧,这个名字已经说明了一切。 * 自来 Cilium 项目的 *[BPF 和 XDP 参考指南][114]* … 好吧,这个名字已经说明了一切。
### 关于 P4 和 BPF ### 关于 P4 和 BPF
[P4][159] 是一个用于指定交换机行为的语言。它可以被编译为许多种目标硬件或软件。因此,你可能猜到了,这些目标中的一个就是 BPF … 仅部分支持的:一些 P4 特性并不能被转化到 BPF 中并且用类似的方法BPF 可以做的事情,而使用 P4 却不能表达出现。不过,**P4 与 BPF 使用** 的相关文档,[用于去隐藏在 bcc 仓库中][160]。这个改变在 P4_16 版本中p4c 引用的编辑器包含 [一个 eBPF 后端][161]。 *[P4][159]* 是一个用于指定交换机行为的语言。它可以被编译为许多种目标硬件或软件。因此,你可能猜到了,这些目标中的一个就是 BPF … 仅部分支持的:一些 P4 特性并不能被转化到 BPF 中并且用类似的方法BPF 可以做的事情,而使用 P4 却不能表达出现。不过,**P4 与 BPF 使用** 的相关文档,[*用于去隐藏在 bcc 仓库中*][160]。这个改变在 P4_16 版本中p4c 引用的编辑器包含 *[一个 eBPF 后端][161]*
![](https://qmonnet.github.io/whirl-offload/img/icons/flask.svg) ![](https://qmonnet.github.io/whirl-offload/img/icons/flask.svg)
### 教程 ### 教程
Brendan Gregg 为想去 **使用 bcc 工具** 跟踪和监视内核中的事件的人制作了一个非常好的 **教程**。[第一个教程是关于如何使用 bcc 工具][162],它总共有十一步,教你去理解怎么去使用已有的工具,而 [**针对 Python 开发者** 的一个目标][163] 是专注于开发新工具,它总共有十七节 “课程”。 Brendan Gregg 为想去 **使用 bcc 工具** 跟踪和监视内核中的事件的人制作了一个非常好的 **教程**。[*第一个教程是关于如何使用 bcc 工具*][162],它总共有十一步,教你去理解怎么去使用已有的工具,而 [***针对 Python 开发者** 的一个目标*][163] 是专注于开发新工具,它总共有十七节 “课程”。
Sasha Goldshtein 也有一些 [_**Linux 跟踪研究材料**_][164] 涉及到使用几个 BPF 去进行跟踪。 Sasha Goldshtein 也有一些 [_**Linux 跟踪研究材料**_][164] 涉及到使用几个 BPF 去进行跟踪。
作者为 Jean-Tiare Le Bigot 的文章为 ping 请求和回复,提供了一个详细的(和有指导意义的)[使用 perf 和 eBPF 去设置一个低级的跟踪器][165] 的示例。 作者为 Jean-Tiare Le Bigot 的文章为 ping 请求和回复,提供了一个详细的(和有指导意义的)[*使用 perf 和 eBPF 去设置一个低级的跟踪器*][165] 的示例。
对于网络相关的 eBPF 使用案例也有几个教程。那里有一些有趣的文档,包含一个 _eBPF Offload 入门指南_,由 Netronome 在 [Open NFP][166] 平台上操作的。其它的那些,来自 Jesper 的演讲,[_XDP 能为其它人做什么_][167],可能是 XDP 入门的最好的方法之一。 对于网络相关的 eBPF 使用案例也有几个教程。那里有一些有趣的文档,包含一个 _eBPF Offload 入门指南_,由 Netronome 在 *[Open NFP][166]* 平台上操作的。其它的那些,来自 Jesper 的演讲,[_XDP 能为其它人做什么_][167],可能是 XDP 入门的最好的方法之一。
![](https://qmonnet.github.io/whirl-offload/img/icons/gears.svg) ![](https://qmonnet.github.io/whirl-offload/img/icons/gears.svg)
@ -345,27 +360,33 @@ Sasha Goldshtein 也有一些 [_**Linux 跟踪研究材料**_][164] 涉及到使
### 来自内核的示例 ### 来自内核的示例
主要的程序类型都包含在内核的示例中:过滤器绑定到套接字或者到 tc 接口、事件跟踪/监视、甚至是 XDP。你可以在 [linux/samples/bpf/][168] 目录中找到这些示例。 主要的程序类型都包含在内核的示例中:过滤器绑定到套接字或者到 tc 接口、事件跟踪/监视、甚至是 XDP。你可以在 *[linux/samples/bpf/][168]* 目录中找到这些示例。
现在,更多的示例已经作为单元测试被添加到 *[linux/tools/testing/selftests/bpf][200]* 目录下,这里面包含对硬件 offload 的测试或者对于 libbpf 的测试。
Jesper 的 Dangaard Brouer 在他的 *[prototype-kernel][201]* 仓库中也维护了一套专门的示例。 这些示例与那些内核中提供的示例非常类似,但是它们可以以在内核基本文件 (Makefiles 和 headers) 之外编译。
也不要忘记去看一下 git 相关的提交历史,它们有一些指定的特性的介绍,它们也包含一些特性的详细的示例。 也不要忘记去看一下 git 相关的提交历史,它们有一些指定的特性的介绍,它们也包含一些特性的详细的示例。
### 来自包 iproute2 的示例 ### 来自包 iproute2 的示例
iproute2 包也提供了几个示例。它们都很明显地偏向网络编程,因此,这个程序是附加到 tc ingress 或者 egress 接口上。这些示例在 [iproute2/examples/bpf/][169] 目录中。 iproute2 包也提供了几个示例。它们都很明显地偏向网络编程,因此,这个程序是附加到 tc ingress 或者 egress 接口上。这些示例在 *[iproute2/examples/bpf/][169]* 目录中。
### 来自 bcc 工具集的示例 ### 来自 bcc 工具集的示例
许多示例都 [与 bcc 一起提供][170] 许多示例都 *[与 bcc 一起提供][170]*
* 一些网络编程的示例在关联的目录下面。它们包括套接字过滤器、tc 过滤器、和一个 XDP 程序。 * 一些网络编程的示例在关联的目录下面。它们包括套接字过滤器、tc 过滤器、和一个 XDP 程序。
* `tracing` 目录包含许多 **跟踪编程** 的示例。前面的教程中提到的都在那里。那些程序涉及了事件跟踪的很大的一个范围,并且,它们中的一些是面向生产系统的。注意,某些 Linux 分发版(至少是 Debian、Ubuntu、Fedora、Arch Linux、这些程序已经被 [打包了][115] 并且可以很 “容易地” 通过比如 `# apt install bcc-tools` 进行安装。但是在写这篇文章的时候(除了 Arch Linux第一个要求是去安装 IO Visor 的包仓库。 * `tracing` 目录包含许多 **跟踪编程** 的示例。前面的教程中提到的都在那里。那些程序涉及了事件跟踪的很大的一个范围,并且,它们中的一些是面向生产系统的。注意,某些 Linux 分发版(至少是 Debian、Ubuntu、Fedora、Arch Linux、这些程序已经被 *[打包了][115]* 并且可以很 “容易地” 通过比如 `# apt install bcc-tools` 进行安装。但是在写这篇文章的时候(除了 Arch Linux第一个要求是去安装 IO Visor 的包仓库。
* 那里也有 **使用 Lua** 作为一个不同的 BPF 后端(那是因为 BPF 程序是用 Lua 写的,它是 C 语言的一个子集,它允许为前端和后端使用相同的语言)的一些示例,它在第三个目录中。 * 那里也有 **使用 Lua** 作为一个不同的 BPF 后端(那是因为 BPF 程序是用 Lua 写的,它是 C 语言的一个子集,它允许为前端和后端使用相同的语言)的一些示例,它在第三个目录中。
* 当然,[*bcc 工具*][202] 自身就是 eBPF 程序使用案例的有趣示例。
### 手册页面 ### 手册页面
虽然 bcc 一般可以用很容易的方式在内核中去注入和运行一个 BPF 程序,通过 `tc` 工具去将程序附加到 tc 接口也可以被执行。因此,如果你打算将 **BPF 与 tc 一起使用**,你可以在 [`tc-bpf(8)` 手册页面][171] 中找到一些调用示例。 虽然 bcc 一般可以用很容易的方式在内核中去注入和运行一个 BPF 程序,通过 `tc` 工具去将程序附加到 tc 接口也可以被执行。因此,如果你打算将 **BPF 与 tc 一起使用**,你可以在 *[`tc-bpf(8)` 手册页面][171]* 中找到一些调用示例。
![](https://qmonnet.github.io/whirl-offload/img/icons/srcfile.svg) ![](https://qmonnet.github.io/whirl-offload/img/icons/srcfile.svg)
@ -375,37 +396,39 @@ iproute2 包也提供了几个示例。它们都很明显地偏向网络编程
### 在内核中的 BPF 代码 ### 在内核中的 BPF 代码
* 文件 [linux/include/linux/bpf.h][116] 和它的副本 [linux/include/uapi/bpf.h][117] 包含有关 eBPF 的 **定义**,它分别被内核中和用户空间程序的接口使用。 * 文件 *[linux/include/linux/bpf.h][116]* 和它的副本 *[linux/include/uapi/bpf.h][117]* 包含有关 eBPF 的 **定义**,它分别被内核中和用户空间程序的接口使用。
* 相同的方式,文件 [linux/include/linux/filter.h][118] 和 [linux/include/uapi/filter.h][119] 包含的信息被 **运行的 BPF 程序** 使用。 * 相同的方式,文件 *[linux/include/linux/filter.h][118]* 和 *[linux/include/uapi/filter.h][119]* 包含的信息被 **运行的 BPF 程序** 使用。
* BPF 相关的 **主要的代码片断** 在 [linux/kernel/bpf/][120] 目录下面。**被系统以不同的操作许可调用** 比如,程序加载或者映射管理是在文件 `syscall.c` 中实现,虽然 `core.c` 包含在 **解析器** 中。其它的文件有明显的命名:`verifier.c` 包含在 **校验器** 中(不是开玩笑的),`arraymap.c` 的代码用于与阵列类型的 **映射** 去互动,等等。 * BPF 相关的 **主要的代码片断** 在 *[linux/kernel/bpf/][120]* 目录下面。**被系统以不同的操作许可调用** 比如,程序加载或者映射管理是在文件 `syscall.c` 中实现,虽然 `core.c` 包含在 **解析器** 中。其它的文件有明显的命名:`verifier.c` 包含在 **校验器** 中(不是开玩笑的),`arraymap.c` 的代码用于与阵列类型的 **映射** 去互动,等等。
* **helpers**,以及几个网络(与 tc、XDP 一起)和用户可用的相关功能是实现在 [linux/net/core/filter.c][121] 中。它也包含代码去移植 cBPF 字节码到 eBPF 中(因为在运行之前,内核中的所有的 cBPF 程序被转换成 eBPF * **helpers**,以及几个网络(与 tc、XDP 一起)和用户可用的相关功能是实现在 [*linux/net/core/filter.c*][121] 中。它也包含代码去移植 cBPF 字节码到 eBPF 中(因为在运行之前,内核中的所有的 cBPF 程序被转换成 eBPF
* **JIT 编译器** 在它们各自的架构目录下面比如x86 架构的在 [linux/arch/x86/net/bpf_jit_comp.c][122] 中。 * 功能和 **helpers** 相关的 **事件跟踪** 都在 *[linux/kernel/trace/bpf_trace.c][203]* 中。
* 在 [linux/net/sched/][123] 目录下,你可以找到 **tc 的 BPF 组件** 相关的代码,尤其是在文件 `act_bpf.c` action `cls_bpf.c`filter中。 * **JIT 编译器** 在它们各自的架构目录下面比如x86 架构的在 *[linux/arch/x86/net/bpf_jit_comp.c][122]* 中。
* 我并没有在 BPF 上深入到 **事件跟踪** 中,因此,我并不真正了解这些程序的钩子。在 [linux/kernel/trace/bpf_trace.c][124] 那里有一些东西。如果你对它感 兴趣,并且想去了解更多,你可以在 Brendan Gregg 的演示或者博客文章上去深入挖掘 * 在 *[linux/net/sched/][123]* 目录下,你可以找到 **tc 的 BPF 组件** 相关的代码,尤其是在文件 `act_bpf.c` action `cls_bpf.c`filter
* 我也没有使用过 **seccomp-BPF**。但它的代码在 [linux/kernel/seccomp.c][125],并且可以在 [linux/tools/testing/selftests/seccomp/seccomp_bpf.c][126] 中找到一些它的使用示例。 * 我并没有在 BPF 上深入到 **事件跟踪** 中,因此,我并不真正了解这些程序的钩子。在 *[linux/kernel/trace/bpf_trace.c][124]* 那里有一些东西。如果你对它感 兴趣,并且想去了解更多,你可以在 Brendan Gregg 的演示或者博客文章上去深入挖掘。
* 我也没有使用过 **seccomp-BPF**。但它的代码在 *[linux/kernel/seccomp.c][125]*,并且可以在 [*linux/tools/testing/selftests/seccomp/seccomp_bpf.c*][126] 中找到一些它的使用示例。
### XDP 钩子代码 ### XDP 钩子代码
一旦将 BPF 虚拟机加载进内核,由一个 Netlink 命令将 **XDP** 程序从用户空间钩入到内核网络路径中。接收它的是在 [linux/net/core/dev.c][172] 文件中的被调用的 `dev_change_xdp_fd()` 函数,并且由它设置一个 XDP 钩子。比如,钩子位于在 NICs 支持的驱动中。例如,为一些 Mellanox 硬件使用的 mlx4 驱动的钩子实现在 [drivers/net/ethernet/mellanox/mlx4/][173] 目录下的文件中。文件 en_netdev.c 接收 Netlink 命令并调用 `mlx4_xdp_set()`,它再被在文件 en_rx.c 实现的实例 `mlx4_en_process_rx_cq()` 调用(对于 RX 侧)。 一旦将 BPF 虚拟机加载进内核,由一个 Netlink 命令将 **XDP** 程序从用户空间钩入到内核网络路径中。接收它的是在 *[linux/net/core/dev.c][172]* 文件中的被调用的 `dev_change_xdp_fd()` 函数,并且由它设置一个 XDP 钩子。比如,钩子位于在 NICs 支持的驱动中。例如,为一些 Mellanox 硬件使用的 mlx4 驱动的钩子实现在 *[drivers/net/ethernet/mellanox/mlx4/][173]* 目录下的文件中。文件 en_netdev.c 接收 Netlink 命令并调用 `mlx4_xdp_set()`,它再被在文件 en_rx.c 实现的实例 `mlx4_en_process_rx_cq()` 调用(对于 RX 侧)。
### 在 bcc 中的 BPF 逻辑 ### 在 bcc 中的 BPF 逻辑
[在 bcc 的 GitHub 仓库][174] 上找到的 **bcc** 工具集的其中一个代码。**Python 代码**,包含在 `BPF` 类中,最初它在文件 [bcc/src/python/bcc/__init__.py][175] 中。但是许多感兴趣的东西 — 我的意见是 — 比如,加载 BPF 程序到内核中,碰巧在 [libbcc **C 库**][176]中。 [*在 bcc 的 GitHub 仓库*][174] 上找到的 **bcc** 工具集的其中一个代码。**Python 代码**,包含在 `BPF` 类中,最初它在文件 *[bcc/src/python/bcc/__init__.py][175]* 中。但是许多感兴趣的东西 — 我的意见是 — 比如,加载 BPF 程序到内核中,碰巧在 *[libbcc 的 **C 库**][176]*中。
### 使用 tc 去管理 BPF 的代码 ### 使用 tc 去管理 BPF 的代码
**在 tc** 中与 iproute2 包中一起带来的与 BPF 相关的代码。其中的一些在 [iproute2/tc/][177] 目录中。文件 f_bpf.c 和 m_bpf.c和 e_bpf.c是各自用于处理 BPF 的过滤器和动作的和tc `exec` 命令,或许什么命令都可以)。文件 q_clsact.c 定义了 `clsact`qdisc 是为 BPF 特别创建的。但是,**大多数的 BPF 用户空间逻辑** 是在 [iproute2/lib/bpf.c][178] 库中实现的,因此,如果你想去使用 BPF 和 tc这里可能是会将你搞混乱的地方它是从文件 iproute2/tc/tc_bpf.c 中来的,你也可以在旧版本的包中找到代码相同的地方)。 **在 tc** 中与 iproute2 包中一起带来的与 BPF 相关的代码。其中的一些在 *[iproute2/tc/][177]* 目录中。文件 f_bpf.c 和 m_bpf.c和 e_bpf.c是各自用于处理 BPF 的过滤器和动作的和tc `exec` 命令,或许什么命令都可以)。文件 q_clsact.c 定义了 `clsact`qdisc 是为 BPF 特别创建的。但是,**大多数的 BPF 用户空间逻辑** 是在 *[iproute2/lib/bpf.c][178]* 库中实现的,因此,如果你想去使用 BPF 和 tc这里可能是会将你搞混乱的地方它是从文件 iproute2/tc/tc_bpf.c 中来的,你也可以在旧版本的包中找到代码相同的地方)。
### BPF 实用工具 ### BPF 实用工具
内核中也带有 BPF 相关的三个工具的源代码(`bpf_asm.c`, `bpf_dbg.c`, `bpf_jit_disasm.c`)、根据你的版本不同,在 [linux/tools/net/][179] 或者 [linux/tools/bpf/][180] 目录下面: 内核中也带有 BPF 相关的三个工具的源代码(`bpf_asm.c`, `bpf_dbg.c`, `bpf_jit_disasm.c`)、根据你的版本不同,在 *[linux/tools/net/][179]* 或者 *[linux/tools/bpf/][180]* 目录下面:
* `bpf_asm` 是一个极小的汇编程序。 * `bpf_asm` 是一个极小的汇编程序。
@ -417,25 +440,27 @@ iproute2 包也提供了几个示例。它们都很明显地偏向网络编程
阅读在源文件顶部的注释可以得到一个它们使用方法的概述。 阅读在源文件顶部的注释可以得到一个它们使用方法的概述。
与 eBPF 一起工作的其它必需的文件是来自内核树的两个**用户空间库**,它们可以用于管理 eBPF 程序或者映射来自外部的程序。这个函数可以通过 *[linux/tools/lib/bpf/][204]* 目录中的头文件 `bpf.h``libbpf.h`(更高级别) 来访问。比如,工具 `bpftool` 主要依赖这些库。
### 其它感兴趣的 chunks ### 其它感兴趣的 chunks
如果你对关于 BPF 的不常见的语言的使用感兴趣bcc 包含 [一个为 BPF 目标的 **P4 编译器**][181]以及 [一个 **Lua 前端**][182],它可以被使用,它以代替 C 的一个子集,并且(在 Lua 的案例中)可以用于 Python 工具。 如果你对关于 BPF 的不常见的语言的使用感兴趣bcc 包含 *[一个为 BPF 目标的 **P4 编译器***][181]以及 [***一个 Lua 前端***][182],它可以被使用,它以代替 C 的一个子集,并且(在 Lua 的案例中)可以用于 Python 工具。
### LLVM 后端 ### LLVM 后端
在 [这个提交][183] clang / LLVM 用于将 C 编译成 BPF 后端,将它添加到 LLVM 源(也可以在 [the GitHub mirror][184] 上访问)。 *[这个提交][183]* clang / LLVM 用于将 C 编译成 BPF 后端,将它添加到 LLVM 源(也可以在 [the GitHub mirror][184] 上访问)。
### 在用户空间中运行 ### 在用户空间中运行
到目前为止,我知道那里有至少两种 eBPF 用户空间实现。第一个是 [uBPF][185],它是用 C 写的。它包含一个解析器、一个 x86_64 架构的 JIT 编译器、一个汇编器和一个反汇编器。 到目前为止,我知道那里有至少两种 eBPF 用户空间实现。第一个是 *[uBPF][185]*,它是用 C 写的。它包含一个解析器、一个 x86_64 架构的 JIT 编译器、一个汇编器和一个反汇编器。
uBPF 的代码似乎被重用了,去产生了一个 [通用实现][186]claims 支持 FreeBSD 内核、FreeBSD 用户空间、Linux 内核、Linux 用户空间和 Mac OSX 用户空间。它被 [VALE 交换机的 BPF 扩展模块][187]使用。 uBPF 的代码似乎被重用了,去产生了一个 [*通用实现*][186]claims 支持 FreeBSD 内核、FreeBSD 用户空间、Linux 内核、Linux 用户空间和 Mac OSX 用户空间。它被 [*VALE 交换机的 BPF 扩展模块*][187]使用。
其它用户空间的实现是我做的:[rbpf][188],基于 uBPF但是用 Rust 写的。写了解析器和 JIT 编译器 Linux 下两个都有Mac OSX 和 Windows 下仅有解析器),以后可能会有更多。 其它用户空间的实现是我做的:[*rbpf*][188],基于 uBPF但是用 Rust 写的。写了解析器和 JIT 编译器 Linux 下两个都有Mac OSX 和 Windows 下仅有解析器),以后可能会有更多。
### 提交日志 ### 提交日志
正如前面所说的,如果你希望得到更多的关于它的信息,不要犹豫,去看一些提交日志,它介绍了一些特定的 BPF 特性。你可以在许多地方搜索日志,比如,在 [git.kernel.org][189]、[在 GitHub 上][190]、或者如果你克隆过它还有你的本地仓库中。如果你不熟悉 git你可以尝试像这些去做 `git blame <file>` 去看看介绍特定代码行的提交内容,然后,`git show <commit>` 去看详细情况(或者在 `git log` 的结果中按关键字搜索,但是这样做通常比较单调乏味)也可以看在 bcc 仓库中的 [按内核版本区分的 eBPF 特性列表][191],它链接到相关的提交上。 正如前面所说的,如果你希望得到更多的关于它的信息,不要犹豫,去看一些提交日志,它介绍了一些特定的 BPF 特性。你可以在许多地方搜索日志,比如,在 *[git.kernel.org][189]、[在 GitHub 上][190]*、或者如果你克隆过它还有你的本地仓库中。如果你不熟悉 git你可以尝试像这些去做 `git blame <file>` 去看看介绍特定代码行的提交内容,然后,`git show <commit>` 去看详细情况(或者在 `git log` 的结果中按关键字搜索,但是这样做通常比较单调乏味)也可以看在 bcc 仓库中的 *[按内核版本区分的 eBPF 特性列表][191]*,它链接到相关的提交上。
![](https://qmonnet.github.io/whirl-offload/img/icons/wand.svg) ![](https://qmonnet.github.io/whirl-offload/img/icons/wand.svg)
@ -445,7 +470,7 @@ uBPF 的代码似乎被重用了,去产生了一个 [通用实现][186]cla
### 编译时的错误 ### 编译时的错误
* 确保你有一个最新的 Linux 内核版本(也可以看 [这个文档][127])。 * 确保你有一个最新的 Linux 内核版本(也可以看 *[这个文档][127]*)。
* 如果你自己编译内核:确保你安装了所有正确的组件,包括内核镜像、头文件和 libc。 * 如果你自己编译内核:确保你安装了所有正确的组件,包括内核镜像、头文件和 libc。
@ -463,7 +488,7 @@ uBPF 的代码似乎被重用了,去产生了一个 [通用实现][186]cla
(seems fixed as of today). (seems fixed as of today).
* 对于使用 `bcc` 的其它问题,不要忘了去看一看这个工具集的 [答疑][128]。 * 对于使用 `bcc` 的其它问题,不要忘了去看一看这个工具集的 *[答疑][128]*
* 如果你从一个并不精确匹配你的内核版本的 iproute2 包中下载了示例,可能会通过在文件中包含的头文件触发一些错误。这些示例片断都假设安装在你的系统中内核的头文件与 iproute2 包是相同版本的。如果不是这种情况,下载正确的 iproute2 版本,或者编辑示例中包含的文件的路径,指向到 iproute2 中包含的头文件上(在运行时一些问题可能或者不可能发生,取决于你使用的特性)。 * 如果你从一个并不精确匹配你的内核版本的 iproute2 包中下载了示例,可能会通过在文件中包含的头文件触发一些错误。这些示例片断都假设安装在你的系统中内核的头文件与 iproute2 包是相同版本的。如果不是这种情况,下载正确的 iproute2 版本,或者编辑示例中包含的文件的路径,指向到 iproute2 中包含的头文件上(在运行时一些问题可能或者不可能发生,取决于你使用的特性)。
@ -477,32 +502,32 @@ uBPF 的代码似乎被重用了,去产生了一个 [通用实现][186]cla
* 静态使用 tc注意不使用过滤器动作不会直接附加到 qdiscs 或者接口。 * 静态使用 tc注意不使用过滤器动作不会直接附加到 qdiscs 或者接口。
* 通过内核校验器抛出错误到解析器可能很难。[内核文档][129]或许可以提供帮助,因此,可以 [参考指南][130] 或者,万不得一的情况下,可以去看源代码(祝你好运!)。记住,校验器 _不运行_ 程序,对于这种类型的错误,它也是非常重要的。如果你得到一个关于无效内存访问或者关于未初始化的数据的错误,它并不意味着那些问题真实发生了(或者有时候,它们完全有可能发生)。它意味着你的程序是以校验器预计可能发生错误的方式写的,并且因此而拒绝这个程序。 * 通过内核校验器抛出错误到解析器可能很难。[*内核文档*][129]或许可以提供帮助,因此,可以 *[参考指南][130]* 或者,万不得一的情况下,可以去看源代码(祝你好运!)。记住,校验器 _不运行_ 程序,对于这种类型的错误,它也是非常重要的。如果你得到一个关于无效内存访问或者关于未初始化的数据的错误,它并不意味着那些问题真实发生了(或者有时候,它们完全有可能发生)。它意味着你的程序是以校验器预计可能发生错误的方式写的,并且因此而拒绝这个程序。
* 注意 `tc` 工具有一个 `verbose` 模式,它与 BPF 一起工作的很好:在你的命令行尾部尝试追加一个 `verbose` * 注意 `tc` 工具有一个 `verbose` 模式,它与 BPF 一起工作的很好:在你的命令行尾部尝试追加一个 `verbose`
* bcc 也有一个 verbose 选项:`BPF` 类有一个 `debug` 参数,它可以带 `DEBUG_LLVM_IR`、`DEBUG_BPF` 和 `DEBUG_PREPROCESSOR` 三个标志中任何组合(详细情况在 [源文件][131]中)。 为调试代码,它甚至嵌入了 [一些条件去打印输出代码][132]。 * bcc 也有一个 verbose 选项:`BPF` 类有一个 `debug` 参数,它可以带 `DEBUG_LLVM_IR`、`DEBUG_BPF` 和 `DEBUG_PREPROCESSOR` 三个标志中任何组合(详细情况在 *[源文件][131]*中)。 为调试代码,它甚至嵌入了 [*一些条件去打印输出代码*][132]。
* LLVM v4.0+ 为 eBPF 程序 [嵌入一个反汇编器][133]。因此,如果你用 clang 编译你的程序,在编译时添加 `-g` 标志允许你通过内核校验器去以人类可读的格式去转储你的程序。处理转储文件,使用: * LLVM v4.0+ 为 eBPF 程序 *[嵌入一个反汇编器][133]*。因此,如果你用 clang 编译你的程序,在编译时添加 `-g` 标志允许你通过内核校验器去以人类可读的格式去转储你的程序。处理转储文件,使用:
``` ```
$ llvm-objdump -S -no-show-raw-insn bpf_program.o $ llvm-objdump -S -no-show-raw-insn bpf_program.o
``` ```
* 使用映射工作?你想去看 [bpf-map][134],一个为 Cilium 项目而用 Go 创建的非常有用的工具,它可以用于去转储内核中 eBPF 映射的内容。那里也有在 Rust 中的 [一个克隆][135]。 * 使用映射工作?你想去看 [*bpf-map*][134],一个为 Cilium 项目而用 Go 创建的非常有用的工具,它可以用于去转储内核中 eBPF 映射的内容。那里也有在 Rust 中的 [*一个克隆*][135]。
* 那里有一个旧的 [在 **StackOverflow** 上的 `bpf` 标签][136],但是,在这篇文章中它一直没有被使用过(并且那里几乎没有与新的 eBPF 相关的东西)。如果你是一位来自未来的阅读者,你可能想去看看在这方面是否有更多的活动。 * 那里有一个旧的 *[在 **StackOverflow** 上的 `bpf` 标签][136]*,但是,在这篇文章中它一直没有被使用过(并且那里几乎没有与新的 eBPF 相关的东西)。如果你是一位来自未来的阅读者,你可能想去看看在这方面是否有更多的活动。
![](https://qmonnet.github.io/whirl-offload/img/icons/zoomin.svg) ![](https://qmonnet.github.io/whirl-offload/img/icons/zoomin.svg)
### 更多! ### 更多!
* 如果你想很容易地去 **测试 XDP**,那是 [一个 Vagrant 设置][137] 可以使用。你也可以 **测试 bcc**[在一个 Docker 容器中][138]。 * 如果你想很容易地去 **测试 XDP**,那是 *[一个 Vagrant 设置][137]* 可以使用。你也可以 **测试 bcc** *[在一个 Docker 容器中][138]*
* 想知道围绕 BPF 的 **开发和活动** 在哪里吗?好吧,内核补丁总是结束于 [netdev 上的邮件列表][139](相关 Linux 内核的网络栈开发):以关键字 “BPF” 或者 “XDP” 来搜索。自 2017 年 4 月开始,那里也有 [一个专门用于 XDP 编程的邮件列表][140](是为了架构或者寻求帮助)。[在 IO Visor 的邮件列表上][141]也有许多的讨论和辨论,因为 BPF 是一个重要的项目。如果你只是想随时了解情况,那里也有一个 [@IOVisor Twitter 帐户][142]。 * 想知道围绕 BPF 的 **开发和活动** 在哪里吗?好吧,内核补丁总是结束于 *[netdev 上的邮件列表][139]*(相关 Linux 内核的网络栈开发):以关键字 “BPF” 或者 “XDP” 来搜索。自 2017 年 4 月开始,那里也有 *[一个专门用于 XDP 编程的邮件列表][140]*(是为了架构或者寻求帮助)。[*在 IO Visor 的邮件列表上*][141]也有许多的讨论和辨论,因为 BPF 是一个重要的项目。如果你只是想随时了解情况,那里也有一个 [*@IOVisor Twitter 帐户*][142]。
我经常会回到这篇博客中,来看一看 [关于 BPF][192] 有没有新的文章! 我经常会回到这篇博客中,来看一看 *[关于 BPF][192]* 有没有新的文章!
_特别感谢 Daniel Borkmann 指引我找到了许多的 [附加的文档][154]因此我才完成了这个合集。_ _特别感谢 Daniel Borkmann 指引我找到了许多的 [附加的文档][154]因此我才完成了这个合集。_
@ -561,7 +586,7 @@ via: https://qmonnet.github.io/whirl-offload/2016/09/01/dive-into-bpf/
[42]:http://jvns.ca/blog/2017/04/07/xdp-bpf-tutorial/ [42]:http://jvns.ca/blog/2017/04/07/xdp-bpf-tutorial/
[43]:http://www.slideshare.net/ThomasGraf5/clium-container-networking-with-bpf-xdp [43]:http://www.slideshare.net/ThomasGraf5/clium-container-networking-with-bpf-xdp
[44]:http://www.slideshare.net/Docker/cilium-bpf-xdp-for-containers-66969823 [44]:http://www.slideshare.net/Docker/cilium-bpf-xdp-for-containers-66969823
[45]:https://www.youtube.com/watch?v=TnJF7ht3ZYc&list=PLkA60AVN3hh8oPas3cq2VA9xB7WazcIgs [45]:https://www.youtube.com/watch?v=TnJF7ht3ZYc&amp;amp;amp;list=PLkA60AVN3hh8oPas3cq2VA9xB7WazcIgs
[46]:http://www.slideshare.net/ThomasGraf5/cilium-fast-ipv6-container-networking-with-bpf-and-xdp [46]:http://www.slideshare.net/ThomasGraf5/cilium-fast-ipv6-container-networking-with-bpf-and-xdp
[47]:https://fosdem.org/2017/schedule/event/cilium/ [47]:https://fosdem.org/2017/schedule/event/cilium/
[48]:http://openvswitch.org/support/ovscon2016/7/1120-tu.pdf [48]:http://openvswitch.org/support/ovscon2016/7/1120-tu.pdf
@ -629,7 +654,7 @@ via: https://qmonnet.github.io/whirl-offload/2016/09/01/dive-into-bpf/
[110]:http://netdevconf.org/1.2/session.html?jamal-tc-workshop [110]:http://netdevconf.org/1.2/session.html?jamal-tc-workshop
[111]:https://git.kernel.org/cgit/linux/kernel/git/shemminger/iproute2.git/commit/bash-completion/tc?id=27d44f3a8a4708bcc99995a4d9b6fe6f81e3e15b [111]:https://git.kernel.org/cgit/linux/kernel/git/shemminger/iproute2.git/commit/bash-completion/tc?id=27d44f3a8a4708bcc99995a4d9b6fe6f81e3e15b
[112]:https://prototype-kernel.readthedocs.io/en/latest/networking/XDP/index.html [112]:https://prototype-kernel.readthedocs.io/en/latest/networking/XDP/index.html
[113]:https://marc.info/?l=linux-netdev&m=147436253625672 [113]:https://marc.info/?l=linux-netdev&amp;amp;amp;m=147436253625672
[114]:http://docs.cilium.io/en/latest/bpf/ [114]:http://docs.cilium.io/en/latest/bpf/
[115]:https://github.com/iovisor/bcc/blob/master/INSTALL.md [115]:https://github.com/iovisor/bcc/blob/master/INSTALL.md
[116]:https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/bpf.h [116]:https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/bpf.h
@ -709,5 +734,15 @@ via: https://qmonnet.github.io/whirl-offload/2016/09/01/dive-into-bpf/
[190]:https://github.com/torvalds/linux [190]:https://github.com/torvalds/linux
[191]:https://github.com/iovisor/bcc/blob/master/docs/kernel-versions.md [191]:https://github.com/iovisor/bcc/blob/master/docs/kernel-versions.md
[192]:https://qmonnet.github.io/whirl-offload/categories/#BPF [192]:https://qmonnet.github.io/whirl-offload/categories/#BPF
[193]:https://lwn.net/Articles/740157/
[194]:https://www.netdevconf.org/2.2/session.html?viljoen-xdpoffload-talk
[195]:https://fosdem.org/2018/schedule/event/xdp/
[196]:http://blog.kubernetes.io/2017/12/using-ebpf-in-kubernetes.html
[197]:http://suricata.readthedocs.io/en/latest/capture-hardware/ebpf-xdp.html?highlight=XDP#ebpf-and-xdp
[198]:https://github.com/pevma/SEPTun-Mark-II
[199]:https://www.stamus-networks.com/2016/09/28/suricata-bypass-feature/
[200]:https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git/tree/tools/testing/selftests/bpf
[201]:https://github.com/netoptimizer/prototype-kernel/tree/master/kernel/samples/bpf
[202]:https://github.com/iovisor/bcc/tree/master/tools
[203]:https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/kernel/trace/bpf_trace.c
[204]:https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git/tree/tools/lib/bpf