mirror of
https://github.com/LCTT/TranslateProject.git
synced 2024-12-23 21:20:42 +08:00
Translated by qhwdw
This commit is contained in:
parent
1b907b07c6
commit
ff92e7ea70
@ -63,23 +63,23 @@
|
||||
|
||||
# 什么是 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 程序可以附加到 tc(Linux 流量控制工具) ingress 或者 egress 接口,并且用一种高效的方式去执行各种包处理任务。它在这个领域打开了一个新的思路。
|
||||
另外一个应用领域是网络编程。除了套接字过滤器外,eBPF 程序还可以附加到 tc(Linux 流量控制工具)的入站或者出站接口上,以一种很高效的方式去执行各种包处理任务。这种使用方式在这个领域开创了一个新的天地。
|
||||
|
||||
并且 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] 或者开始去接近(approach)BPF。其它的一些,如 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*][193](Matt Flemming,on LWN.net,December 2017):
|
||||
一篇写的很好的,并且易于理解的,介绍 eBPF 子系统组件的概述文章。
|
||||
|
||||
* [_利用 BPF 和 XDP 实现可编程的内核网络数据路径_][53] (Daniel Borkmann, OSSNA17, Los Angeles, September 2017):
|
||||
快速理解所有的关于 eBPF 和 XDP 的基础概念的许多文章中的一篇(大多数是关于网络处理的)
|
||||
|
||||
* [BSD 包过滤器][54] (Suchakra Sharma, June 2017):
|
||||
* [*BSD 包过滤器*][54] (Suchakra Sharma, June 2017):
|
||||
一篇非常好的介绍文章,大多数是关于跟踪方面的。
|
||||
|
||||
* [_BPF:跟踪及更多_][55] (Brendan Gregg, January 2017):
|
||||
@ -119,7 +122,7 @@ BPF,是伯克利包过滤器(**B**erkeley **P**acket **F**ilter)的第
|
||||
|
||||
**BPF 内部结构**:
|
||||
|
||||
* Daniel Borkmann 正在做的一项令人称奇的工作,它用于去展现 eBPF 的 **内部结构**,特别是通过几次关于 **eBPF 用于 tc ** 的演讲和论文。
|
||||
* Daniel Borkmann 正在做的一项令人称奇的工作,它用于去展现 eBPF 的 **内部结构**,尤其是,它的关于 **eBPF 用于 tc ** 的几次演讲和论文。
|
||||
* [_使用 tc 的 cls_bpf 的高级可编程和它的最新更新_][30] (netdev 1.2, Tokyo, October 2016):
|
||||
Daniel 介绍了 eBPF 的细节,它使用了隧道和封装、直接包访问、和其它特性。
|
||||
|
||||
@ -134,7 +137,7 @@ BPF,是伯克利包过滤器(**B**erkeley **P**acket **F**ilter)的第
|
||||
|
||||
这些介绍可能是理解 eBPF 内部机制设计与实现的最佳文档资源之一。
|
||||
|
||||
[**IO Visor 博客**][157] 有一些关于 BPF 感兴趣的技术文章。它们中的一些包含了许多营销讨论。
|
||||
[***IO Visor 博客***][157] 有一些关于 BPF 感兴趣的技术文章。它们中的一些包含了许多营销讨论。
|
||||
|
||||
**内核跟踪**:总结了所有的已有的方法,包括 BPF:
|
||||
|
||||
@ -144,7 +147,7 @@ BPF,是伯克利包过滤器(**B**erkeley **P**acket **F**ilter)的第
|
||||
* [_Linux 内核跟踪_][63] (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 和火焰图相关的博客文章。其中的大多数都可以 [从这篇文章中][158] 访问,或者浏览他的博客。
|
||||
关于 **事件跟踪和监视**,Brendan Gregg 使用 eBPF 的一些心得,它使用 eBPFR 的一些案例,他做的非常出色。如果你正在做一些内核跟踪方面的工作,你应该去看一下他的关于 eBPF 和火焰图相关的博客文章。其中的大多数都可以 *[从这篇文章中][158]* 访问,或者浏览他的博客。
|
||||
|
||||
介绍 BPF,也介绍 **Linux 网络的一般概念**:
|
||||
|
||||
@ -154,24 +157,30 @@ BPF,是伯克利包过滤器(**B**erkeley **P**acket **F**ilter)的第
|
||||
|
||||
**硬件 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 Viljoen,netdev 2.2 ,Seoul,November 2017)
|
||||
|
||||
* 我现在有一个简短的,但是在 2018 年的 FOSDEM 上有一个更新版:
|
||||
[*XDP 硬件 Offload 的挑战*][195](Quentin Monnet,FOSDEM 2018,Brussels,February 2018)
|
||||
|
||||
关于 **cBPF**:
|
||||
|
||||
* [_BSD 包过滤器:一个用户级包捕获的新架构_][66] (Steven McCanne 和 Van Jacobson, 1992):
|
||||
它是关于(classic)BPF 的最早的论文。
|
||||
|
||||
* [关于 BPF 的 FreeBSD 手册][67] 是理解 cBPF 程序的可用资源。
|
||||
* *[关于 BPF 的 FreeBSD 手册][67]* 是理解 cBPF 程序的可用资源。
|
||||
|
||||
* 关于 cBPF,Daniel Borkmann 实现的至少两个演示,[一是,在 2013 年 mmap 中,BPF 和 Netsniff-NG][68],以及 [在 2014 中关于 tc 和 cls_bpf 的的一个非常完整的演示][69]。
|
||||
* 关于 cBPF,Daniel 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
|
||||
|
||||
* 在 IO Visor 网站上的 [XDP 概述][72]。
|
||||
* 在 IO Visor 网站上的 *[XDP 概述][72]*。
|
||||
|
||||
* [_eXpress Data Path (XDP)_][73] (Tom Herbert, Alexei Starovoitov, March 2016):
|
||||
这是第一个关于 XDP 的演示。
|
||||
@ -214,7 +223,7 @@ BPF,是伯克利包过滤器(**B**erkeley **P**acket **F**ilter)的第
|
||||
|
||||
### 关于 基于 eBPF 或者 eBPF 相关的其它组件
|
||||
|
||||
* [_在边缘上的 P4_][77] (John Fastabend, May 2016):
|
||||
* [_在边界上的 P4_][77] (John Fastabend, May 2016):
|
||||
提出了使用 **P4**,一个包处理的描述语言,使用 BPF 去创建一个高性能的可编程交换机。
|
||||
|
||||
* 如果你喜欢音频的介绍,这里有一个相关的 [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]。
|
||||
|
||||
* 这里也有一个关于 **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,它已经实现了几个概念验证原型:
|
||||
|
||||
* [使用 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 的主分支中),但是,看它带来了什么将是非常有趣的事情。
|
||||
|
||||
* 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]* 的文章,它解释了现有的产品 (Cilium,Weave Scope) 如何支持 eBPF 与 Kubernetes 一起工作,并且进一步描述了,在容器部署环境中,eBPF 感兴趣的交互内容是什么。
|
||||
|
||||
* [_CETH for XDP_][85] (Yan Chan 和 Yunsong Lu、Linux Meetup、Santa Clara、July 2016):
|
||||
**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)
|
||||
[_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 解决方案可以获得更好的性能。
|
||||
|
||||
* [_**gobpf** - 从 Go 中利用 eBPF_][92] (Michael Schubert, fosdem17, Brussels, Belgium, February 2017):
|
||||
“一个从 Go 中的库,可以去创建、加载和使用 eBPF 程序”
|
||||
|
||||
* [**ply**][93] 是为 Linux 实现的一个小的但是非常灵活的开源动态 **跟踪器**,它的一些特性非常类似于 bcc 工具,是受 awk 和 dtrace 启发,但使用一个更简单的语言。它是由 Tobias Waldekranz 写的。
|
||||
* [***ply***][93] 是为 Linux 实现的一个小的但是非常灵活的开源动态 **跟踪器**,它的一些特性非常类似于 bcc 工具,是受 awk 和 dtrace 启发,但使用一个更简单的语言。它是由 Tobias Waldekranz 写的。
|
||||
|
||||
* 如果你读过我以前的文章,你可能对我在这篇文章中的讨论感兴趣,[使用 eBPF 实现 OpenState 接口][151],关于包状态处理,在 fosdem17 中。
|
||||
|
||||
@ -272,33 +287,33 @@ BPF,是伯克利包过滤器(**B**erkeley **P**acket **F**ilter)的第
|
||||
|
||||
### 关于 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
|
||||
|
||||
@ -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]。
|
||||
|
||||
* 在你的系统上的 **tc 手册页面** 并不是最新日期的,因为它们中的几个最近已经增加了。如果你没有找到关于特定的队列规则、分类或者过滤器的文档,它可能在最新的 [tc 组件的手册页面][107] 中。
|
||||
* 在你的系统上的 **tc 手册页面** 并不是最新日期的,因为它们中的几个最近已经增加了。如果你没有找到关于特定的队列规则、分类或者过滤器的文档,它可能在最新的 *[tc 组件的手册页面][107]* 中。
|
||||
|
||||
* 一些额外的材料可以在 iproute2 包自已的文件中找到:这个包中有 [一些文档][108],包括一些文件,它可以帮你去理解 [**tc 的 action** 的功能][109]。
|
||||
* 一些额外的材料可以在 iproute2 包自已的文件中找到:这个包中有 [*一些文档*][108],包括一些文件,它可以帮你去理解 *[**tc 的 action** 的功能][109]*。
|
||||
**注意:** 这些文件在 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 的一些 [进展中的文档(包括规范)][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][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)
|
||||
|
||||
### 教程
|
||||
|
||||
Brendan Gregg 为想去 **使用 bcc 工具** 跟踪和监视内核中的事件的人制作了一个非常好的 **教程**。[第一个教程是关于如何使用 bcc 工具][162],它总共有十一步,教你去理解怎么去使用已有的工具,而 [**针对 Python 开发者** 的一个目标][163] 是专注于开发新工具,它总共有十七节 “课程”。
|
||||
Brendan Gregg 为想去 **使用 bcc 工具** 跟踪和监视内核中的事件的人制作了一个非常好的 **教程**。[*第一个教程是关于如何使用 bcc 工具*][162],它总共有十一步,教你去理解怎么去使用已有的工具,而 [***针对 Python 开发者** 的一个目标*][163] 是专注于开发新工具,它总共有十七节 “课程”。
|
||||
|
||||
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)
|
||||
|
||||
@ -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 相关的提交历史,它们有一些指定的特性的介绍,它们也包含一些特性的详细的示例。
|
||||
|
||||
### 来自包 iproute2 的示例
|
||||
|
||||
iproute2 包也提供了几个示例。它们都很明显地偏向网络编程,因此,这个程序是附加到 tc ingress 或者 egress 接口上。这些示例在 [iproute2/examples/bpf/][169] 目录中。
|
||||
iproute2 包也提供了几个示例。它们都很明显地偏向网络编程,因此,这个程序是附加到 tc ingress 或者 egress 接口上。这些示例在 *[iproute2/examples/bpf/][169]* 目录中。
|
||||
|
||||
### 来自 bcc 工具集的示例
|
||||
|
||||
许多示例都 [与 bcc 一起提供][170]:
|
||||
许多示例都 *[与 bcc 一起提供][170]*:
|
||||
|
||||
* 一些网络编程的示例在关联的目录下面。它们包括套接字过滤器、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 语言的一个子集,它允许为前端和后端使用相同的语言)的一些示例,它在第三个目录中。
|
||||
|
||||
* 当然,[*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)
|
||||
|
||||
@ -375,37 +396,39 @@ iproute2 包也提供了几个示例。它们都很明显地偏向网络编程
|
||||
|
||||
### 在内核中的 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 钩子代码
|
||||
|
||||
一旦将 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 的 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** 中与 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_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` 是一个极小的汇编程序。
|
||||
|
||||
@ -417,25 +440,27 @@ iproute2 包也提供了几个示例。它们都很明显地偏向网络编程
|
||||
|
||||
阅读在源文件顶部的注释可以得到一个它们使用方法的概述。
|
||||
|
||||
与 eBPF 一起工作的其它必需的文件是来自内核树的两个**用户空间库**,它们可以用于管理 eBPF 程序或者映射来自外部的程序。这个函数可以通过 *[linux/tools/lib/bpf/][204]* 目录中的头文件 `bpf.h` 和 `libbpf.h`(更高级别) 来访问。比如,工具 `bpftool` 主要依赖这些库。
|
||||
|
||||
### 其它感兴趣的 chunks
|
||||
|
||||
如果你对关于 BPF 的不常见的语言的使用感兴趣,bcc 包含 [一个为 BPF 目标的 **P4 编译器**][181]以及 [一个 **Lua 前端**][182],它可以被使用,它以代替 C 的一个子集,并且(在 Lua 的案例中)可以用于 Python 工具。
|
||||
如果你对关于 BPF 的不常见的语言的使用感兴趣,bcc 包含 *[一个为 BPF 目标的 **P4 编译器***][181]以及 [***一个 Lua 前端***][182],它可以被使用,它以代替 C 的一个子集,并且(在 Lua 的案例中)可以用于 Python 工具。
|
||||
|
||||
### 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)
|
||||
|
||||
@ -445,7 +470,7 @@ uBPF 的代码似乎被重用了,去产生了一个 [通用实现][186],cla
|
||||
|
||||
### 编译时的错误
|
||||
|
||||
* 确保你有一个最新的 Linux 内核版本(也可以看 [这个文档][127])。
|
||||
* 确保你有一个最新的 Linux 内核版本(也可以看 *[这个文档][127]*)。
|
||||
|
||||
* 如果你自己编译内核:确保你安装了所有正确的组件,包括内核镜像、头文件和 libc。
|
||||
|
||||
@ -463,7 +488,7 @@ uBPF 的代码似乎被重用了,去产生了一个 [通用实现][186],cla
|
||||
|
||||
(seems fixed as of today).
|
||||
|
||||
* 对于使用 `bcc` 的其它问题,不要忘了去看一看这个工具集的 [答疑][128]。
|
||||
* 对于使用 `bcc` 的其它问题,不要忘了去看一看这个工具集的 *[答疑][128]*。
|
||||
|
||||
* 如果你从一个并不精确匹配你的内核版本的 iproute2 包中下载了示例,可能会通过在文件中包含的头文件触发一些错误。这些示例片断都假设安装在你的系统中内核的头文件与 iproute2 包是相同版本的。如果不是这种情况,下载正确的 iproute2 版本,或者编辑示例中包含的文件的路径,指向到 iproute2 中包含的头文件上(在运行时一些问题可能或者不可能发生,取决于你使用的特性)。
|
||||
|
||||
@ -477,32 +502,32 @@ uBPF 的代码似乎被重用了,去产生了一个 [通用实现][186],cla
|
||||
|
||||
* 静态使用 tc,注意不使用过滤器,动作不会直接附加到 qdiscs 或者接口。
|
||||
|
||||
* 通过内核校验器抛出错误到解析器可能很难。[内核文档][129]或许可以提供帮助,因此,可以 [参考指南][130] 或者,万不得一的情况下,可以去看源代码(祝你好运!)。记住,校验器 _不运行_ 程序,对于这种类型的错误,它也是非常重要的。如果你得到一个关于无效内存访问或者关于未初始化的数据的错误,它并不意味着那些问题真实发生了(或者有时候,它们完全有可能发生)。它意味着你的程序是以校验器预计可能发生错误的方式写的,并且因此而拒绝这个程序。
|
||||
* 通过内核校验器抛出错误到解析器可能很难。[*内核文档*][129]或许可以提供帮助,因此,可以 *[参考指南][130]* 或者,万不得一的情况下,可以去看源代码(祝你好运!)。记住,校验器 _不运行_ 程序,对于这种类型的错误,它也是非常重要的。如果你得到一个关于无效内存访问或者关于未初始化的数据的错误,它并不意味着那些问题真实发生了(或者有时候,它们完全有可能发生)。它意味着你的程序是以校验器预计可能发生错误的方式写的,并且因此而拒绝这个程序。
|
||||
|
||||
* 注意 `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
|
||||
|
||||
```
|
||||
|
||||
* 使用映射工作?你想去看 [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)
|
||||
|
||||
### 更多!
|
||||
|
||||
* 如果你想很容易地去 **测试 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],因此我才完成了这个合集。_
|
||||
|
||||
@ -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/
|
||||
[43]:http://www.slideshare.net/ThomasGraf5/clium-container-networking-with-bpf-xdp
|
||||
[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;list=PLkA60AVN3hh8oPas3cq2VA9xB7WazcIgs
|
||||
[46]:http://www.slideshare.net/ThomasGraf5/cilium-fast-ipv6-container-networking-with-bpf-and-xdp
|
||||
[47]:https://fosdem.org/2017/schedule/event/cilium/
|
||||
[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
|
||||
[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
|
||||
[113]:https://marc.info/?l=linux-netdev&m=147436253625672
|
||||
[113]:https://marc.info/?l=linux-netdev&amp;amp;m=147436253625672
|
||||
[114]:http://docs.cilium.io/en/latest/bpf/
|
||||
[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
|
||||
@ -709,5 +734,15 @@ via: https://qmonnet.github.io/whirl-offload/2016/09/01/dive-into-bpf/
|
||||
[190]:https://github.com/torvalds/linux
|
||||
[191]:https://github.com/iovisor/bcc/blob/master/docs/kernel-versions.md
|
||||
[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
|
Loading…
Reference in New Issue
Block a user