在 Linux 内核 4.0 前,Linux 内核并没有对硬件交换模块的支持,尽管在 bridge
实现了一个软网桥,所有的交换都是通过 CPU 实现的,但是并没有实现对于真正硬件交换机的支持,通用接口层面一直没有合理的解决方案。Linux 4.0 引入了 switchdev
框架,全称是 Ethernet switch device driver model
,它代表一类具有「交换」能力芯片的多网口设备的抽象,使得内核可以将「交换」功能 offload 到硬件上。
技术背景
在 switchdev
模型之前,开发者如果想要将交换功能从内核 offload 到自己硬件交换模块上,在内核并没有一个统一的模型,需要自己去实现复杂的驱动代码。
记得去年的时候,我曾经拿到过一块交换板,可以直接插在主板的PCI-E上,当时必须使用厂商特定的驱动程序以及配合VLAN技术才能将其用起来。其实很多的交换机可能都采用了Linux作为管理平面和控制平面,然后配置自己的定制硬件和定制驱动来使用。
我曾经想过一种办法用Netfilter技术实现对硬件交换模块的支持,但是,CPU还是要被中断的,整个流程是CPU将数据包拉到bridge或者IP层,然后再交回硬件…正确的方式是根本不用中断CPU,完全通过硬件来转发数据包,只有数据和本地协议栈相关的时候,才中断CPU。而这个思路,意味着你必须重写驱动。
总之,没有一个统一的接口,这就意味着如果你自己想设计一块交换板,没有比较好的标准可循,即便有,可能你也要自己编写或者复制粘贴大量的驱动代码,这将严重影响研发效率。
switchdev 框架如下图所示,硬件交换模块是一个具有「交换」能力的多网口设备抽象。其中每个网口就是一个 port
,在 switchdev
框架中被注册成 net_device
。除此之外,内核中自带了一个rocker driver,演示了一个实际的设备驱动的实现:
框架模型
下图展示了 switchdev
模型,硬件是专门用于交换的 ASIC
芯片,硬件每个交换的 port 都对应在 switch driver
里面实现的网口设备。在 switch driver
初始化过程中,驱动会遍历每个硬件交换机端口,同时申请和创建一个 net_device
,一般被称作 port netdev
。
port netdev
是硬件交换机端口的软件抽象,也是构建更高层级 bridges
、bonds
、VLANs
、tunnels
和 L3 routers 的基础。使用标准的 netdev
工具,比如 iproute2
、ethtool
等,port netdev 也可以给用户提供关于 swich port 的 PHY link state 和 I/O statistics 相关数据。
There is (currently) no higher-level kernel object for the switch beyond the
port netdevs. All of the switchdev driver ops are netdev ops or switchdev ops.A switch management port is outside the scope of the switchdev driver model.
Typically, the management port is not participating in offloaded data plane and
is loaded with a different driver, such as a NIC driver, on the management port
device.
注意,理想化的实现中,OpenFlow 控制器可以直接将流表注入到设备中,从而指导设备直接进行数据包交换。流表的内容超级复杂,不是本文的目标,但是相信在后一个内核版本中会出现相关的Document。采用了硬件交换模块的Linux BOX和原来的截然不同了,它更像是一个高端的专业网络设备,类似Cisco那样的。它看起来就是下面的样子: