哪些是BPF?
BPF,及伯克利包过滤器BerkeleyPacketFilter,最初设想提出于1992年,其目的是为了提供一种过滤包的方式,而且要防止从内核空间到用户空间的无用的数据包复制行为。它最初是由从用户空间注入到内核的一个简单的字节码构成,它在哪个位置借助一个校准器进行检测——以防止内核崩溃或则安全问题——并附着到一个套接字上,接着在每位接收到的包上运行。几年后它被移植到Linux上,但是应用于一小部份应用程序上(比如,tcpdump)。其简化的语言以及存在于内核中的即时编译器(JIT),使BPF成为一个性能卓越的工具。
之后,在2013年,AlexeiStarovoitov对BPF进行彻底地改建,并降低了新的功能,改善了它的性能。这个新版本被命名为eBPF(意思是“extendedBPF”),与此同时,将原先的BPF弄成cBPF(意思是“classic”BPF)。新版本出现了如映射和尾调用tailcall这样的新特点,但是JIT编译器也被重画了。新的语言比cBPF更接近于原生机器语言。而且,在内核中创建了新的附着点。
谢谢这些新的钩子,eBPF程序才可以被设计用于各类各样的情形下,其分为两个应用领域。其中一个应用领域是内核跟踪和风波监控。BPF程序可以被附着到探针(kprobe),但是它与其它跟踪模式相比,有好多的优点(有时也有一些缺点)。
另外一个应用领域是网路编程。不仅套接字过滤器外,eBPF程序还可以附加到tc(Linux流量控制工具)的入站或则出站插口上,以一种很高效的方法去执行各类包处理任务。这些使用方法在这个领域开创了一个新的天地。
但是eBPF通过使用为IOVisor项目开发的技术,使它的性能进一步得到提高:也为XDP(“eXpressDataPath”)添加了新的钩子,XDP是不久前添加到内核中的一种旧式快速路径。XDP与Linux栈组合,之后使用BPF,使包处理的速率更快。
甚至一些项目,如P4、OpenvSwitch,考虑或则开始去商讨使用BPF。其它的一些,如CETH、Cilium,则是完全基于它的。BPF是这么流行,因而,我们可以预计,不久以后,将围绕它有更多工具和项目出现…
深入理解字节码
如同我一样:我的一些工作(包括BEBA)是十分依赖eBPF的,但是在这个网站上之后的几篇文章将关注于这个主题。按理说,在深入到细节之前,我应当以某种方法去介绍BPF——我的意思是,真正的介绍,在第一节所提供的简略介绍上更多地介绍在BPF上开发的新功能:哪些是BPF映射?尾调用?内部结构是哪些样子?等等。并且,在这个网站上早已有好多这个主题的介绍了,但是,我也不希望去写另一篇“BPF介绍”的重复文章。
其实,我耗费了好多的时间去阅读和学习关于BPF的知识,因而,在这儿我们即将做哪些呢,我搜集了十分多的关于BPF的阅读材料:介绍、文档,也有教程或则示例。这儿有好多的材料可以去阅读红旗linux5.0,并且,为了去阅读它,首先要去找到它。为此,为了就能帮助更多想去学习和使用BPF的人,如今的这篇文章给出了一个资源清单。这儿有各类阅读材料,它可以帮你深入理解内核字节码的机制。
资源简介
这篇文章中下边的链接提供了BPF的基本概述,或则,一些与它密切相关的一些主题。假如你对BPF十分陌生,你可以在这种介绍文章中选购出一篇你喜欢的文章去阅读。假如你已然理解了BPF,你可以针对特定的主题去阅读,下边是阅读清单。
关于BPF
关于eBPF的常规介绍:
BPF内部结构:
IOVisor博客有一些关于BPF的值得关注技术文章。它们中的一些包含了一点营销讨论。
内核跟踪:总结了所有的已有的方式,包括BPF:
关于风波跟踪和监视,BrendanGregg大量使用了eBPF,但是就其使用eBPFR的一些案例写了极好的文档。假如你正在做一些内核跟踪方面的工作suse linux 下载,你应当去看一下他的关于eBPF和火焰图相关的博客文章。其中的大多数都可以从这篇文章中访问,或则浏览他的博客。
介绍BPF,也介绍Linux网路的通常概念:
硬件卸载offload(LCTT评注:“卸载”是指原先由软件来处理的一些操作交由硬件来完成,以提高吞吐量,减少CPU负荷。):
关于cBPF:
关于XDP
(测试是用mlx4驱动程序执行的)。
JesperDangaardBrouer有几个特别好的幻kt板,它可以从本质起来理解XDP的内部结构。
(Jesper也创建了而且尝试去扩充了有关eBPF和XDP的一些文档,查看。)
关于基于eBPF或则eBPF相关的其它组件
在上述不同的讲演中重复了大量的内容;嫌麻烦就选近来的一个。DanielBorkmann作为Google开源博客的特邀作者,也写了Cilium简介。
这儿也有一个关于Cilium的播客节目:一个是OvSOrbitepisode(#4),它是BenPfaff采访ThomasGraf(2016年5月),和另外一个IvanPepelnjak的播客,一直是ThomasGraf关于eBPF、P4、XDP和Cilium方面的(2016年10月)。OpenvSwitch(OvS),它是OpenVirtualNetwork(OVN,一个开源的网路虚拟化解决方案)相关的项目,正在考虑在不同的层次上使用eBPF,它早已实现了几个概念验证原型:
据我所知,这种eBPF的使用案例看起来仅处于提议阶段(并没有合并到OvS的主分支中),然而,看它带来了哪些将是十分值得关注的事情。
XDP的设计对分布式拒绝访问(DDoS)功击是十分有用的。越来越多的讲演都关注于它。比如,在2017年4月英国格拉斯哥举行的netdev2.1大会上,来自Cloudflare的人们的讲话(XDP实践:将XDP集成到我们的DDoS减轻管线)或则来自Facebook的(Droplet:由BPF+XDP驱动的DDoS对策)都存在这样的好多使用案例。Kubernetes可以用好多种方法与eBPF交互。这儿有一篇关于在Kubernetes中使用eBPF的文章,它解释了现有的产品(Cilium、WeaveScope)怎样支持eBPF与Kubernetes一起工作,但是进一步描述了,在容器布署环境中,eBPF感兴趣的交互内容是哪些。CETHforXDP(YanChan和YunsongLu、LinuxMeetup、SantaClara、July2016):
CETH,是由Mellanox发起的,为实现更快的网路I/O而主张的通用以太网驱动程序构架。
VALE交换机,另一个虚拟交换机,它可以与netmap框架结合,有一个BPF扩充模块。Suricata,一个开源的入侵测量系统,它的旁路捕获旁特点依赖于XDP。有一些关于它的资源:
当使用原生驱动的XDP时,这个项目要求实现特别高的性能。
InKeV:对于DCN的内核中分布式网路虚拟化(Z.Ahmed,M.H.Alizai和A.A.Syed,SIGCOMM,August2016):
InKeV是一个基于eBPF的虚拟网路、目标数据中心网路的数据路径构架。它最初由PLUMgrid提出,而且宣称相比基于OvS的OpenStack解决方案可以获得更好的性能。
gobpf-在Go中使用eBPF(MichaelSchubert,fosdem17,Brussels,Belgium,February2017):
“一个来自Go库,可以去创建、加载和使用eBPF程序”
ply是为Linux实现的一个小而灵活的开源动态跟踪器,它的一些特点十分类似于bcc工具,是受awk和dtrace启发,但使用一个更简单的语言。它是由TobiasWaldekranz写的。假如你读过我先前的文章,你可能对我在这篇文章中的讨论感兴趣,使用eBPF实现OpenState插口,关于包状态处理,在fosdem17中。文档
一旦你对BPF是做哪些的有一个大体的理解。你可以抛掉通常的讲演而深入到文档中了。下边是BPF的规范和功能的最全面的文档,按你的须要挑一个开始阅读吧!
关于BPF
最后一个可能是目前来说关于校准器的最佳的总结。
FerrisEllis发布的一个关于eBPF的系列博客文章。作为我写的这个短文,第一篇文章是关于eBPF的历史背景和未来期望。接出来的文章将更多的是技术方面,和前景展望。每位内核版本的BPF特点列表在bcc库房中可以找到。假如你想去晓得运行一个给定的特点所要求的最小的内核版本,它是十分有用的。我贡献和添加了链接到递交中,它介绍了每位特点,为此,你也可以从哪里很容易地去访问递交历史。关于tc
当为了网路目的结合使用BPF与tc(Linux流量控制trafficcontrol工具)时,它可用于搜集tc的常规功能的信息。这儿有几个关于它的资源。
关于XDP关于P4和BPF
P4是一个用于指定交换机行为的语言。它可以为多种目标硬件或软件编译。为此,你可能猜到了,这种目标中的一个就是BPF…仅部份支持的:一些P4特点并不能被转化到BPF中,但是,用类似的方式,BPF可以做的事情,而使用P4却不能抒发出现。不过,P4与BPF使用的相关文档,被隐藏在bcc库房中。这个改变在P4_16版本中,p4c引用的编辑器包含一个eBPF前端。
教程
BrendanGregg为想要使用bcc工具跟踪和监视内核中的风波的人制做了一个特别好的教程。第一个教程是关于怎么使用bcc工具,它有许多章节,可以教你去理解如何去使用已有的工具,而针对Python开发者的一篇专注于开发新工具,它总共有十七节“课程”。
SashaGoldshtein也有一些Linux跟踪研究材料涉及到使用几个BPF工具进行跟踪。
Jean-TiareLeBigot的另一篇文章提供了一个详尽的(和有指导意义的)使用perf和eBPF去设置一个低级的跟踪器的示例。
对于网路相关的eBPF使用案例也有几个教程。有一些值得关注的文档,包括一篇eBPF卸载入门手册,是关于在OpenNFP平台上用Netronome操作的。其它的这些,来自Jesper的讲演,XDP能为其它人做哪些(及其第二版),可能是XDP入门的最好的方式之一。
示例
有示例是特别好的。瞧瞧它们是怎样工作的。并且BPF程序示例是分散在几个项目中的,为此,我列举了我所晓得的所有的示例。示例并不是总是使用相同的helper(比如,tc和bcc都有一套它们自己的helper,使它可以很容易地去用C语言写BPF程序)
来自内核的示例
内核中包含了大多数类型的程序:过滤器绑定到套接字或则tc插口、事件跟踪/监视、甚至是XDP。你可以在linux/samples/bpf/目录中找到这种示例。
如今,更多的示例早已作为单元测试被添加到linux/tools/testing/selftests/bpf目录下,这儿面包含对硬件卸载的测试或则对于libbpf的测试。
Jesper的DangaardBrouer在他的prototype-kernel库房中也维护了一套专门的示例。这种示例与这些内核中提供的示例十分类似,并且它们可以脱离内核构架(Makefile和头文件)编译。
也不要忘掉去看一下git相关的递交历史,它们介绍了一些特定的特点,似乎包含了一些特点的详尽示例。
来自包iproute2的示例
iproute2包也提供了几个示例。它们都很显著地偏向网路编程,为此,这个程序是附着到tc入站或则出站插口上。这种示例在iproute2/examples/bpf/目录中。
来自bcc工具集的示例
许多示例都是与bcc一起提供的:
指南页面
尽管bcc通常很容易在内核中去注入和运行一个BPF程序,将程序附着到tc插口也能通过tc工具自己完成。为此,假如你准备将BPF与tc一起使用,你可以在tc-bpf(8)指南页面中找到一些调用示例。
代码
有时侯,BPF文档或则示例并不够,但是你只想在你喜欢的文本编辑器(它其实应当是Vim)中去显示代码并去阅读它。或则,你可能想深入到代码中去做一个补丁程序或则为机器降低一些新特点。为此,这儿对有关的文件的几个建议,找到你想要的函数只取决于你自己!
在内核中的BPF代码XDP钩子代码
一旦装载进内核的BPF虚拟机,由一个Netlink命令将XDP程序从用户空间钩入到内核网路路径中。接收它的是在linux/net/core/dev.c文件中的dev_change_xdp_fd()函数,它被调用并设置一个XDP钩子。钩子被置于支持的网卡的驱动程序中。诸如linux 钩子程序,用于Netronome硬件钩子的ntp驱动程序实现置于drivers/net/ethernet/netronome/nfp/中。文件nfp_net_common.c接受Netlink命令,并调用nfp_net_xdp_setup()linux 钩子程序,它会转而调用nfp_net_xdp_setup_drv()实例来安装该程序。
在bcc中的BPF逻辑
在bcc的GitHub库房能找到的bcc工具集的代码。其Python代码,包含在BPF类中,最初它在文件bcc/src/python/bcc/__init__.py中。并且许多我认为有意思的东西,例如,加载BPF程序到内核中,出现在libbcc的C库中。
使用tc去管理BPF的代码
其实,这种代码与iproute2包中的tc中的BPF相关。其中的一些在iproute2/tc/目录中。文件f_bpf.c和m_bpf.c(和e_bpf.c)各自用于处理BPF的过滤器和动作的(和tcexec命令,等等)。文件q_clsact.c定义了为BPF非常创建的clsactqdisc。并且,大多数的BPF用户空间逻辑是在iproute2/lib/bpf.c库中实现的,因而,假如你想去使用BPF和tc,这儿可能是会将你搞混乱的地方(它是从文件iproute2/tc/tc_bpf.c中联通而至的,你也可以在旧版本的包中找到相同的代码)。
BPF实用工具
内核中也带有BPF相关的三个工具的源代码(bpf_asm.c、bpf_dbg.c、bpf_jit_disasm.c),按照你的版本不同,在linux/tools/net/(直至Linux4.14)或则linux/tools/bpf/目录下边:
阅读在源文件底部的注释可以得到一个它们使用方式的概述。
与eBPF一起工作的其它必需的文件是来自内核树的两个用户空间库,它们可以用于管理eBPF程序或则映射来自外部的程序。这个函数可以通过linux/tools/lib/bpf/目录中的头文件bpf.h和libbpf.h(更高层面封装)来访问。例如,工具bpftool主要依赖这种库。