关注了就能看到更多这么棒的文章哦~
January 14, 2020
This article was contributed by Marta Rybczyńska
原文来自:https://lwn.net/Articles/809333/
如今,纯粹用软件来支持高速场景下的网络协议,已经越来越困难了。目前已经有一些网络接口能达到25-100Gb/s的速度了,并且也开始出现一些能达到200-400Gb/s的。针对100Gb/s的速度要想及时完成network packet处理的话,每一笔需要在<200个cycle内处理掉,这样就没有留给操作系统多少时间了。幸运的是,许多操作可以由硬件来完成,包括校验和的验证,以及把一部分发送、接受packet的动作转移到硬件上(offload)去做。
现在的硬件功能更强大,有许多可能性了。5.3 kernel里面包含了Pablo Neira Ayuso的一个patch set,可以利用netfilter来把一些packet过滤的工作来offload到硬件上去做。这个patch set增加了offload功能的支持,同时也对网络通用代码和网卡驱动里面的现有的offload代码路径进行了重构。在后面的kernel发布版本里面还有更多的相关工作。因此现在是一个合适的时机来审视一下近期在network stack里面的offloading功能的演进。
Offloads in network cards
我们先回顾欻下网卡(network card,网络适配器)提供了什么功能。一个网络包(network packet)会先经过一些硬件处理之后才可能传递给kernel的网络协议栈。第一步它会被一个物理层(PHY, physical layer)处理器接收下来,PHY会处理好那些底层因素,包括传输介质(铜导线或者光纤以太网线),频率,调制方式(modulation)等等。接下来会把network packet传递给medium access control (MAC)单元,MAC把它复制到系统内存里面去,把packet的描述符写入接收队列,然后可能会触发一次中断。这样一来设备驱动程序就可以开始经过网络协议栈来处理数据包。
不过,MAC控制器通常还包含其他一些逻辑单元,包括特定的一个处理器或者FPGA,这样就可以不局限于仅仅做个DMA传输了。首先,可以用MAC来处理多个接收队列,这样可以把数据包的处理分发到系统里的不同CPU上去。它也可以把拥有相同的来源和目的地IP与端口号的packet排好序(这些可以成为数据流flow)。不同的数据流可以放到专门的接收队列里面去。这样可以提高性能,例如这样能刚好的利用cache。除此以外,MAC层还可以针对不同的数据流来做一些处理,例如把它们直接转发到别的网络接口上去(如果同一个MAC在支持多个网络接口的话),或者针对DoS(拒绝服务攻击)来把相关的网络包丢弃掉,等等等等。
要实现netfilter offload的话,硬件里需要两个重要功能模块:一个parser(解析器)和一个classifier(分类器)。parser会从网络数据包里实时地(at line speed)提取信息,它可以解析若干种网络协议,这样一来就可以从多个网络层的角度来对数据包进行处理。通常它会提取那些重要的数据(例如IP地址和端口号等)以及软件需要的一些信息。第二步里classifier会利用parser提供的这些信息来对这个网络数据包packet进行处理。
上述着两个模块在硬件实现的时候都需要利用到一个名为ternary content-addressable memory (TCAM)的结构,这是一种特殊的memory,不同于常见的使用两个值(0和1)的memory,它会使用3个值(0,1,X)。新增的这个X值,表示在做数据比对(compare)的时候,不用在乎这个值("don't care"),既能匹配0,也能匹配1。典型来说parser会提供若干个TCAM数据条目(entries),每个条目都跟另一块memory区域(存放了具体要做的action)关联起来。这样实现出来之后就可以利用正则表达式来对packet进行匹配,硬件会对每个packet都跟现有的TCAM条目逐项对比,命中后得到条目索引,也就能查到该对这个packet做什么具体的action了。
TCAM条目的数量是有限的,比如Marvell SoC里的Armada 70xx和80xx等控制器都有256个TCAM条目(这个信息来自Maxime Chevallier在2019 Embedded Linux Conference Europe会议上建议在网络驱动里面支持classification offload的演讲pdfhttps://static.sched.com/hosted_files/osseu19/3d/chevallier-network-classification-offload.pdf )。而相应地,netfilter的配置里面通常会有几千条规则。很明显,要配置这样的一个网络控制器,一大挑战就是如何限制TCAM里面添加的规则的数量。驱动程序需要负责配置此设备特有的action,以及可供使用的各种classifier。目前的硬件通常都很复杂,并且驱动程序通常只支持少数几个硬件。
MAC控制器里的的offload功能还有可能更加精致复杂,还有可以对完整的TCP stack进行offloading的,被称为TCP offload engines。目前Linux尚未支持这种,因为在许多年前有人提交这部分支持代码的时候收到了network stack maintainers的很多反对意见(https://lwn.net/Articles/148697/ )。因此,Linux kernel没有支持TCP offloading,而是提供了一些特定的无状态的offload功能的支持。
对offload开发历史感兴趣的读者可以读Jesse Brandeburg和Anjali Singhai Jain在2018 Linux Plubers Conference上的论文(http://vger.kernel.org/lpc_net2018_talks/Brandeburg_networking_hardware_offloads.pdf )。
Kernel subsystems with filtering offloads
networking subsystem核心代码里面支持了许多种offload到网络设备的功能,包括计算校验和,零散包归集(scatter/gather)处理,分包处理(segmentation)等等。读者们可以看一下他们PC上所支持的、已经激活的offload功能,用如下命令即可:
ethtool --show-offload
不同的网络接口都有不同的offload功能列表,这取决于硬件和对应的驱动支持哪些功能。ethtool也可以配置这些offload功能,在它的man page(http://man7.org/linux/man-pages/man8/ethtool.8.html )里面可以看到许多已有功能。
还有一个subsystem也利用了硬件offload功能,这就是traffic control(它的配置工具名字是tc)。tc的man page也介绍了现有功能的综述,特别是flower classifier,可以供系统管理员来配置网络包的调度。常见的使用tc的例子是针对各个服务(service)来限制带宽,或者对某些网络数据提升优先级。感兴趣的读者可以阅读2017年11月的NetDev 2.2会议上Simon Horman的文章(https://netdevconf.info/2.2/papers/horman-tcflower-talk.pdf )
到目前为止,无论tc还是ethtool都可以过滤offload功能。这两种功能在kernel里是分别实现的,因此某种意义上说是个重复工作,导致网卡驱动开发者需要做双份的工作,因为每种offload实现都需要使用不同的驱动callback函数。如果今后有第三个系统也来增加offload功能的话,开发者就会需要来统一一下实现了,这就需要对一些公用代码进行重构,以及对驱动程序实现的回调函数进行修改。
Summary
在高速网络接口上对网络包的处理不是那么容易的,所能利用的CPU cycle数实在太少了。幸运的是,硬件提供的offload功能可以被kernel利用来减少难度。在本文中,我们介绍了网卡是如何工作的,以及一些基本的offload只是。这是为了第二篇文章打好基础,在第二篇里面,我们会仔细介绍netfilter offloading功能带来的变动,包括公共代码的改动以及对驱动程序作者的影响,当然也会介绍如何使用offload。
全文完
LWN文章遵循CC BY-SA 4.0许可协议。
欢迎分享、转载及基于现有协议再创作~
长按下面二维码关注,关注LWN深度文章以及开源社区的各种新近言论~