架构¶
本文档描述了分布式交换架构 (DSA) 子系统的设计原则、限制、与其他子系统的交互,以及如何为此子系统开发驱动程序,以及为有兴趣加入此工作的开发人员提供的待办事项。
设计原则¶
分布式交换架构子系统最初设计用于支持使用 Linux 的 Marvell 以太网交换机(MV88E6xxx,也称为 Link Street 产品线),但此后已发展为支持其他供应商。
此设计背后的最初理念是能够使用未修改的 Linux 工具(例如 bridge、iproute2、ifconfig)来透明地工作,无论它们是配置/查询交换机端口网络设备还是常规网络设备。
以太网交换机通常包括多个前面板端口和一个或多个 CPU 或管理端口。DSA 子系统当前依赖于连接到以太网控制器的管理端口的存在,该控制器能够从交换机接收以太网帧。对于小型家庭和办公室产品(路由器、网关甚至机架顶部交换机)中发现的各种以太网交换机,这是一种非常常见的设置。此主机以太网控制器在 DSA 术语和代码中稍后将被称为“导管”和“cpu”。
DSA 中的 D 代表分布式,因为该子系统在设计时具有配置和管理彼此之上级联交换机的能力,方法是使用交换机之间的上游和下游以太网链路。这些特定端口在 DSA 术语和代码中称为“dsa”端口。彼此连接的多个交换机的集合称为“交换机树”。
对于每个前面板端口,DSA 创建专门的网络设备,这些设备用作 Linux 网络堆栈使用的控制和数据流端点。这些专门的网络接口在 DSA 术语和代码中称为“用户”网络接口。
使用 DSA 的理想情况是当以太网交换机支持“交换机标签”时,这是一种硬件功能,使交换机为它接收到的每个以太网帧插入特定标签,以帮助管理接口找出
此帧来自哪个端口
此帧被转发的原因
如何将 CPU 发起的流量发送到特定端口
该子系统确实支持无法插入/剥离标签的交换机,但在这种情况下,功能可能会受到一些限制(流量隔离依赖于基于端口的 VLAN ID)。
请注意,DSA 当前不为“cpu”和“dsa”端口创建网络接口,因为
“cpu”端口是管理控制器的以太网交换机侧,因此会产生功能重复,因为您将为同一导管获得两个接口:导管 netdev 和“cpu”netdev
“dsa”端口只是两个或多个交换机之间的导管,因此也不能真正用作合适的网络接口,只有下游或最上游的接口在这种模型下才有意义
注意:在过去的 15 年中,DSA 子系统一直在使用“主”(而不是“导管”)和“从”(而不是“用户”)这两个术语。这些术语已从 DSA 代码库中删除,并逐步淘汰出 uAPI。
交换机标记协议¶
DSA 支持多种特定于供应商的标记协议、一种软件定义的标记协议以及无标签模式 (DSA_TAG_PROTO_NONE
)。
标记协议的确切格式是特定于供应商的,但通常,它们都包含一些内容,这些内容
标识以太网帧来自/应发送到哪个端口
提供此帧被转发到管理接口的原因
所有标记协议都在 net/dsa/tag_*.c
文件中,并实现 struct dsa_device_ops
结构的方法,详细信息如下。
标记协议通常分为以下三类之一
特定于交换机的帧头位于以太网头之前,从 DSA 导管的帧解析器的角度来看,将 MAC DA、MAC SA、EtherType 和整个 L2 有效负载向右移动。
特定于交换机的帧头位于 EtherType 之前,从 DSA 导管的角度来看,保持 MAC DA 和 MAC SA 的位置,但将“真实”的 EtherType 和 L2 有效负载向右移动。
特定于交换机的帧头位于数据包的末尾,保持所有帧头的位置不变,并且不改变 DSA 导管的帧解析器对数据包的视图。
标记协议可以使用相同长度的交换机标签标记所有数据包,或者标签长度可能会有所不同(例如,带有 PTP 时间戳的数据包可能需要扩展的交换机标签,或者在 TX 上可能有一个标签长度,而在 RX 上则有一个不同的标签长度)。无论哪种方式,标记协议驱动程序都必须使用最长交换机帧头/尾部的八位字节长度填充 struct dsa_device_ops::needed_headroom
和/或 struct dsa_device_ops::needed_tailroom
。DSA 框架将自动调整导管接口的 MTU,以适应此额外大小,以便 DSA 用户端口支持 1500 八位字节的标准 MTU(L2 有效负载长度)。needed_headroom
和 needed_tailroom
属性还用于尽最大努力从网络堆栈请求分配具有足够额外空间的数据包,以便在传输数据包时推送交换机标签的行为不会因内存不足而导致其重新分配。
即使不希望应用程序解析特定于 DSA 的帧头,标记协议在线上的格式也表示内核向用户空间公开的应用程序二进制接口,用于 libpcap
等解码器。标记协议驱动程序必须使用唯一描述交换机硬件和数据路径驱动程序之间所需交互特征的值填充 struct dsa_device_ops
的 proto
成员:帧头内每个位字段的偏移量以及处理帧所需的任何有状态处理(如 PTP 时间戳可能需要)。
从网络堆栈的角度来看,同一 DSA 交换机树中的所有交换机都使用相同的标记协议。如果数据包在具有多个交换机的结构中传输,则特定于交换机的帧头由结构中接收到数据包的第一个交换机插入。此标头通常包含有关其类型的信息(它是必须捕获到 CPU 的控制帧,还是必须转发的数据帧)。控制帧应仅由软件数据路径解封装,而数据帧也可能从同一结构的其他交换机的其他用户端口自动转发,在这种情况下,最外层的交换机端口必须解封装数据包。
请注意,在某些情况下,叶交换机(未直接连接到 CPU)使用的标记格式可能与网络堆栈看到的格式不同。这可以在 Marvell 交换机树中看到,其中 CPU 端口可以配置为使用 DSA 或 Ethertype DSA (EDSA) 格式,但 DSA 链路配置为使用较短的(没有 Ethertype 的)DSA 帧头,以便减少自动数据包转发开销。仍然是这种情况,如果 DSA 交换机树配置为 EDSA 标记协议,则操作系统会看到来自使用较短的 DSA 标头标记它们的叶交换机的 EDSA 标记数据包。这是因为连接到 CPU 的 Marvell 交换机配置为在 DSA 和 EDSA 之间执行标签转换(这只是添加或删除 ETH_P_EDSA
EtherType 和一些填充八位字节的操作)。
即使 DSA 交换机的标记协议彼此不兼容,也可以构建 DSA 交换机的级联设置。在这种情况下,此结构中没有 DSA 链路,并且每个交换机构成一个不相交的 DSA 交换机树。DSA 链路被视为简单的一对 DSA 导管(上游 DSA 交换机的外向端口)和一个 CPU 端口(下游 DSA 交换机的内向端口)。
可以通过 DSA 导管的 dsa/tagging
sysfs 属性查看附加的 DSA 交换机树的标记协议
cat /sys/class/net/eth0/dsa/tagging
如果硬件和驱动程序能够做到,则可以在运行时更改 DSA 交换机树的标记协议。这是通过将新的标记协议名称写入与上述相同的 sysfs 设备属性来完成的(DSA 导管和所有附加的交换机端口在执行此操作时必须关闭)。
希望所有标记协议都可以使用 dsa_loop
模拟驱动程序进行测试,该驱动程序可以附加到任何网络接口。目标是任何网络接口都应该能够以相同的方式传输相同的数据包,并且无论用于交换机控制路径的驱动程序和用于 DSA 导管的驱动程序如何,标记器都应该以相同的方式解码相同的接收数据包。
数据包的传输会通过标记器的 xmit
函数。传递的 struct sk_buff *skb
的 skb->data
指向 skb_mac_header(skb)
,即目标 MAC 地址,并且传递的 struct net_device *dev
表示虚拟 DSA 用户网络接口,该接口的硬件对应部分必须将数据包引导至(即 swp0
)。此方法的作用是以一种交换机将理解数据包的目标出口端口(并且不会将其发送到其他端口)的方式准备 skb。如果正确填写了 needed_headroom
和 needed_tailroom
属性,则检查 skb 头或尾部空间中是否空间不足是不必要的,因为 DSA 会确保在调用此方法之前有足够的空间。
数据包的接收通过标记器的 rcv
函数进行。传递的 struct sk_buff *skb
的 skb->data
指向 skb_mac_header(skb) + ETH_ALEN
个字节,即指向以太网类型之后第一个字节的位置,如果此帧未被标记。此方法的作用是消耗帧头,调整 skb->data
以真正指向以太网类型之后的第一个字节,并将 skb->dev
更改为指向与接收数据包的物理前端交换机端口相对应的虚拟 DSA 用户网络接口。
由于第 1 类和第 2 类中的标记协议会破坏 DSA 管道上的软件(并且通常也会破坏硬件)数据包解剖,因此 DSA 管道上的诸如 RPS(接收数据包转向)之类的功能将会被破坏。DSA 框架通过挂钩流解剖器并移动 IP 报头在 DSA 管道所看到的标记帧中的偏移量来处理此问题。此行为是基于标记协议的 overhead
值自动进行的。如果并非所有数据包大小都相同,则标记器可以实现 struct dsa_device_ops
的 flow_dissect
方法,并通过指定每个单独的 RX 数据包产生的正确偏移量来覆盖此默认行为。尾部标记器不会给流解剖器造成问题。
当 DSA 管道驱动程序在 vlan_features 中声明 NETIF_F_HW_CSUM 并查看 csum_start 和 csum_offset 时,校验和卸载应与第 1 类和第 2 类标记器一起工作。对于这些情况,DSA 会将校验和的起始和偏移量移动标记大小。如果 DSA 管道驱动程序仍在 vlan_features 中使用传统的 NETIF_F_IP_CSUM 或 NETIF_F_IPV6_CSUM,则只有当卸载硬件已经期望使用该特定标记时(可能由于匹配的供应商)卸载才可能起作用。DSA 用户端口从管道继承这些标志,并且由驱动程序在 IP 报头不在硬件期望的位置时正确回退到软件校验和。如果该检查无效,则数据包可能会在没有正确校验和的情况下发送到网络(校验和字段将具有伪 IP 报头总和)。对于第 3 类,当卸载硬件尚未期望使用交换机标记时,必须在插入任何标记之前计算校验和(即在标记器内部)。否则,DSA 管道会将尾部标记包含在(软件或硬件)校验和计算中。然后,当标记在传输期间被交换机剥离时,它将在适当的位置留下不正确的 IP 校验和。
由于各种原因(最常见的是第 1 类标记器与不感知 DSA 的管道相关联,从而篡改了管道所认为的 MAC DA),标记协议可能需要 DSA 管道以混杂模式运行,以接收所有帧,而不管 MAC DA 的值如何。这可以通过设置 struct dsa_device_ops
的 promisc_on_conduit
属性来实现。请注意,这假设使用不感知 DSA 的管道驱动程序,这是常态。
管道网络设备¶
管道网络设备是用于 CPU/管理以太网接口的常规、未经修改的 Linux 网络设备驱动程序。这种驱动程序可能偶尔需要知道是否启用了 DSA(例如:启用/禁用特定的卸载功能),但 DSA 子系统已被证明可以与行业标准驱动程序一起工作:e1000e,
mv643xx_eth
等,而无需对这些驱动程序进行修改。此类网络设备也经常被称为管道网络设备,因为它们充当主机处理器和硬件以太网交换机之间的管道。
网络堆栈挂钩¶
当管道 netdev 与 DSA 一起使用时,会在网络堆栈中放置一个小的挂钩,以便让 DSA 子系统处理以太网交换机特定的标记协议。DSA 通过向网络堆栈注册特定的(和伪造的)以太网类型(稍后变为 skb->protocol
)来实现此目的,这也称为 ptype
或 packet_type
。典型的以太网帧接收序列如下所示
管道网络设备(例如:e1000e)
接收中断触发
调用接收函数
完成基本的数据包处理:获取长度、状态等。
通过调用
eth_type_trans
准备好数据包以供以太网层处理
net/ethernet/eth.c
eth_type_trans(skb, dev) if (dev->dsa_ptr != NULL) -> skb->protocol = ETH_P_XDSA
drivers/net/ethernet/*
netif_receive_skb(skb) -> iterate over registered packet_type -> invoke handler for ETH_P_XDSA, calls dsa_switch_rcv()
net/dsa/dsa.c
-> dsa_switch_rcv() -> invoke switch tag specific protocol handler in 'net/dsa/tag_*.c'
net/dsa/tag_*.c
检查并剥离交换机标记协议以确定始发端口
定位每个端口的网络设备
使用 DSA 用户网络设备调用
eth_type_trans()
调用
netif_receive_skb()
在此之后,DSA 用户网络设备将接收到可以由网络堆栈处理的常规以太网帧。
用户网络设备¶
由 DSA 创建的用户网络设备堆叠在其管道网络设备之上,这些网络接口中的每一个都将负责成为交换机每个前面板端口的控制和数据流端点。这些接口经过专门设计,以便
在将流量发送到特定交换机端口或从特定交换机端口发送流量时,插入/删除交换机标记协议(如果存在)
查询交换机以进行 ethtool 操作:统计信息、链路状态、局域网唤醒、寄存器转储...
管理外部/内部 PHY:链路、自动协商等。
这些用户网络设备具有自定义的 net_device_ops 和 ethtool_ops 函数指针,这允许 DSA 在网络堆栈/ethtool 和交换机驱动程序实现之间引入一个分层级别。
在从这些用户网络设备传输帧时,DSA 将查找当前向这些网络设备注册了哪个交换机标记协议,并调用特定的传输例程,该例程负责在以太网帧中添加相关的交换机标记。
然后,使用管道网络设备 ndo_start_xmit()
函数将这些帧排队以进行传输。由于它们包含适当的交换机标记,因此以太网交换机将能够处理来自管理接口的这些传入帧,并将它们传递到物理交换机端口。
当使用多个 CPU 端口时,可以在 DSA 用户设备和物理 DSA 管道之间堆叠 LAG(绑定/团队)设备。因此,LAG 设备也是一个 DSA 管道,但 LAG 从属设备也继续是 DSA 管道(只是没有分配给它们的用户端口;这在 LAG DSA 管道消失时进行恢复是必需的)。因此,LAG DSA 管道的数据路径是不对称使用的。在 RX 上,ETH_P_XDSA
处理程序(调用 dsa_switch_rcv()
)会提前(在物理 DSA 管道上;LAG 从属)调用。因此,不使用 LAG DSA 管道的 RX 数据路径。另一方面,TX 是线性进行的:dsa_user_xmit
调用 dsa_enqueue_skb
,后者调用 dev_queue_xmit
到 LAG DSA 管道。后者调用 dev_queue_xmit
到一个或另一个物理 DSA 管道,并且在这两种情况下,数据包都通过硬件路径向交换机退出系统。
图形表示¶
总而言之,这基本上是从网络设备的角度来看 DSA 的样子
Unaware application
opens and binds socket
| ^
| |
+-----------v--|--------------------+
|+------+ +------+ +------+ +------+|
|| swp0 | | swp1 | | swp2 | | swp3 ||
|+------+-+------+-+------+-+------+|
| DSA switch driver |
+-----------------------------------+
| ^
Tag added by | | Tag consumed by
switch driver | | switch driver
v |
+-----------------------------------+
| Unmodified host interface driver | Software
--------+-----------------------------------+------------
| Host interface (eth0) | Hardware
+-----------------------------------+
| ^
Tag consumed by | | Tag added by
switch hardware | | switch hardware
v |
+-----------------------------------+
| Switch |
|+------+ +------+ +------+ +------+|
|| swp0 | | swp1 | | swp2 | | swp3 ||
++------+-+------+-+------+-+------++
用户 MDIO 总线¶
为了能够读取/写入内置的交换机 PHY,DSA 创建了一个用户 MDIO 总线,该总线允许特定的交换机驱动程序将 MDIO 读取/写入转移和拦截到特定的 PHY 地址。在大多数 MDIO 连接的交换机中,这些功能将利用直接或间接 PHY 寻址模式从交换机内置 PHY 返回标准 MII 寄存器,从而允许 PHY 库和/或返回链路状态、链路伙伴页面、自动协商结果等。
对于具有外部和内部 MDIO 总线的以太网交换机,用户 MII 总线可用于多路复用/解多路复用 MDIO 读取和写入到此交换机可能连接的内部或外部 MDIO 设备:内部 PHY、外部 PHY 甚至外部交换机。
数据结构¶
DSA 数据结构在 include/net/dsa.h
以及 net/dsa/dsa_priv.h
中定义
dsa_chip_data
:给定交换机设备的平台数据配置,此结构描述了交换机设备的父设备、其地址以及其端口的各种属性:名称/标签,最后是路由表指示(在级联交换机时)dsa_platform_data
:平台设备配置数据,如果级联了多个交换机,则可以引用 dsa_chip_data 结构的集合,需要引用此交换机树所连接到的管道网络设备dsa_switch_tree
:在dsa_ptr
下分配给管道网络设备的结构,此结构引用了 dsa_platform_data 结构以及交换机树支持的标记协议,以及应调用哪些接收/传输函数挂钩,还提供了有关直接连接的交换机的信息:CPU 端口。最后,引用了一系列 dsa_switch 以寻址树中的各个交换机。dsa_switch
:描述树中交换机设备的结构,引用dsa_switch_tree
作为反向指针、用户网络设备、管道网络设备以及对支持``dsa_switch_ops`` 的引用dsa_switch_ops
:引用函数指针的结构,请参阅下文了解完整说明。
设计限制¶
缺少 CPU/DSA 网络设备¶
如前所述,DSA 目前不会为 CPU 或 DSA 端口创建用户网络设备。在以下情况下,这可能会成为问题:
无法使用 ethtool 获取交换机 CPU 端口的统计计数器,这会使得使用 xMII 接口连接的 MDIO 交换机的调试更加困难。
无法基于附加到 CPU 端口的以太网控制器功能配置 CPU 端口的链路参数:http://patchwork.ozlabs.org/patch/509806/
在使用级联设置时,无法配置交换机之间的特定 VLAN ID / 中继 VLAN。
使用 DSA 设置的常见陷阱¶
一旦将导管网络设备配置为使用 DSA(dev->dsa_ptr 变为非 NULL),并且其背后的交换机需要标记协议,则此网络接口只能专门用作导管接口。直接通过此接口发送数据包(例如:使用此接口打开套接字)不会使我们通过交换机标记协议的发送功能,因此另一端期望标记的以太网交换机通常会丢弃此帧。
与其他子系统的交互¶
DSA 当前利用以下子系统:
MDIO/PHY 库:
drivers/net/phy/phy.c
,mdio_bus.c
Switchdev:
net/switchdev/*
用于各种 of_* 函数的设备树
Devlink:
net/core/devlink.c
MDIO/PHY 库¶
DSA 公开的用户网络设备可能与也可能不与 PHY 设备(struct phy_device
,如 include/linux/phy.h
中定义)对接,但 DSA 子系统会处理所有可能的组合。
内置于以太网交换机硬件中的内部 PHY 设备
通过内部或外部 MDIO 总线连接的外部 PHY 设备
通过内部 MDIO 总线连接的内部 PHY 设备
特殊、非自动协商或非 MDIO 管理的 PHY 设备:SFP、MoCA;又称固定 PHY。
PHY 配置由 dsa_user_phy_setup()
函数完成,其逻辑基本如下:
如果使用设备树,则使用标准的 “phy-handle” 属性查找 PHY 设备。如果找到,则使用
of_phy_connect()
创建并注册此 PHY 设备。如果使用设备树且 PHY 设备是 “固定” 的,即符合
Documentation/devicetree/bindings/net/fixed-link.txt
中定义的非 MDIO 管理 PHY 的定义,则使用特殊的固定 MDIO 总线驱动程序透明地注册和连接 PHY。最后,如果 PHY 内置在交换机中,这在独立的交换机封装中很常见,则使用 DSA 创建的用户 MII 总线探测 PHY。
SWITCHDEV¶
当与桥接层接口时,DSA 直接利用 SWITCHDEV,更具体地说,当在每个端口的用户网络设备之上配置 VLAN 时,会利用其 VLAN 过滤部分。截至目前,DSA 唯一支持的 SWITCHDEV 对象是 FDB 和 VLAN 对象。
Devlink¶
DSA 在结构中为每个物理交换机注册一个 devlink 设备。对于每个 devlink 设备,每个物理端口(即用户端口、CPU 端口、DSA 链路或未使用的端口)都公开为 devlink 端口。
DSA 驱动程序可以使用以下 devlink 功能:
区域:调试功能,允许用户空间以低级二进制格式转储驱动程序定义的硬件信息区域。支持全局区域和每个端口的区域。即使对于以某种方式向标准 iproute2 用户空间程序(ip-link、bridge)公开的数据片段,也可以导出 devlink 区域,例如地址表和 VLAN 表。例如,如果表格包含 iproute2 抽象不可见的额外的硬件特定详细信息,或者在非用户端口上检查这些表格也可能很有用,因为没有为这些端口注册网络接口,因此 iproute2 不可见。
参数:一项功能,使用户能够配置与设备相关的某些低级可调旋钮。驱动程序可以实现适用的通用 devlink 参数,也可以添加新的特定于设备的 devlink 参数。
资源:一项监控功能,使用户能够查看设备中某些硬件表(例如 FDB、VLAN 等)的利用率。
共享缓冲区:一种 QoS 功能,用于调整和分配每个端口和每个流量类别的内存和帧保留,在入口和出口方向上,以便低优先级的大容量流量不会妨碍高优先级关键流量的处理。
有关更多详细信息,请参阅 Documentation/networking/devlink/
。
设备树¶
DSA 具有一个标准化的绑定,该绑定在 Documentation/devicetree/bindings/net/dsa/dsa.txt
中进行了文档记录。PHY/MDIO 库辅助函数(例如 of_get_phy_mode()
, of_phy_connect()
)也用于查询每个端口的 PHY 特定详细信息:接口连接、MDIO 总线位置等。
驱动程序开发¶
DSA 交换机驱动程序需要实现一个 dsa_switch_ops
结构,其中包含下面描述的各种成员。
探测、注册和设备生命周期¶
DSA 交换机是总线(无论是平台、SPI、I2C、MDIO 还是其他总线)上的常规 device
结构。DSA 框架不参与它们与设备核心的探测。
从驱动程序的角度来看,交换机注册意味着将有效的 struct dsa_switch
指针传递给 dsa_register_switch()
,通常从交换机驱动程序的探测函数传递。提供的结构中以下成员必须有效:
ds->dev
:将用于解析交换机的 OF 节点或平台数据。ds->num_ports
:将用于为此交换机创建端口列表,并验证 OF 节点中提供的端口索引。ds->ops
:指向保存 DSA 方法实现的dsa_switch_ops
结构的指针。ds->priv
:指向驱动程序私有数据结构的反向指针,该结构可以在所有后续的 DSA 方法回调中检索。
此外,可以选择在 dsa_switch
结构中配置以下标志,以从 DSA 核心获得特定于驱动程序的行为。设置时的行为通过 include/net/dsa.h
中的注释进行记录。
ds->vlan_filtering_is_global
ds->needs_standalone_vlan_filtering
ds->configure_vlan_while_not_filtering
ds->untag_bridge_pvid
ds->assisted_learning_on_cpu_port
ds->mtu_enforcement_ingress
ds->fdb_isolation
在内部,DSA 保留一个全局于内核的交换机树数组(交换机组),并在注册时将 dsa_switch
结构附加到树。交换机附加到的树 ID 由交换机 OF 节点的 dsa,member
属性的第一个 u32 数字确定(如果缺少则为 0)。树中的交换机 ID 由同一 OF 属性的第二个 u32 数字确定(如果缺少则为 0)。注册具有相同交换机 ID 和树 ID 的多个交换机是非法的,会导致错误。使用平台数据,只允许单个交换机和单个交换机树。
在具有多个交换机的树的情况下,探测是非对称进行的。dsa_register_switch()
的前 N-1 个调用者仅将其端口添加到树的端口列表(dst->ports
),每个端口都有一个指向其关联交换机(dp->ds
)的反向指针。然后,这些交换机提前退出其 dsa_register_switch()
调用,因为 dsa_tree_setup_routing_table()
已确定该树尚未完成(并非 DSA 链路引用的所有端口都存在于树的端口列表中)。当最后一个交换机调用 dsa_register_switch()
时,树才会完成,这会触发所有初始化(包括对 ds->ops->setup()
的调用)的有效继续,所有这些都作为最后一个交换机探测函数的调用上下文的一部分。
当调用 dsa_unregister_switch()
时,会发生与注册相反的操作,这将从树的端口列表中删除交换机的端口。当第一个交换机注销时,整个树会被拆除。
DSA 交换机驱动程序必须实现各自总线的 shutdown()
回调函数,并从中调用 dsa_switch_shutdown()
(这是 dsa_unregister_switch()
执行的完整拆卸操作的最小版本)。原因是 DSA 保留了对导管网络设备的引用,如果导管设备的驱动程序决定在关机时解除绑定,则 DSA 的引用将阻止该操作完成。
必须调用 dsa_switch_shutdown()
或 dsa_unregister_switch()
,但不能同时调用两者。即使已经调用了 shutdown()
,设备驱动程序模型也允许调用总线的 remove()
方法。因此,驱动程序应该通过在运行任一函数后将其 drvdata 设置为 NULL,并在采取任何操作之前检查 drvdata 是否为 NULL,来实现 remove()
和 shutdown()
之间的互斥方法。
在调用 dsa_switch_shutdown()
或 dsa_unregister_switch()
之后,不得再通过提供的 dsa_switch_ops
进行任何进一步的回调,并且驱动程序可以释放与 dsa_switch
关联的数据结构。
交换机配置¶
get_tag_protocol
: 此函数用于指示支持哪种标记协议,应为dsa_tag_protocol
枚举中的有效值。返回的信息不必是静态的;驱动程序会收到 CPU 端口号,以及可能堆叠的上游交换机的标记协议,以防在支持的标记格式方面存在硬件限制。change_tag_protocol
: 当默认标记协议与导管存在兼容性问题或其他问题时,驱动程序可能支持在运行时通过设备树属性或通过 sysfs 更改它。在这种情况下,进一步调用get_tag_protocol
应报告当前正在使用的协议。setup
: 交换机的设置函数,此函数负责使用所有需要的设置dsa_switch_ops
私有结构:寄存器映射、中断、互斥锁、锁等。此函数还应正确配置交换机以将所有网络接口彼此隔离,也就是说,它们应由交换机硬件本身隔离,通常是为每个端口创建基于端口的 VLAN ID,并仅允许 CPU 端口和特定端口位于转发向量中。平台未使用的端口应禁用。完成此函数后,交换机应完全配置好并准备好服务任何类型的请求。建议在此设置函数期间对交换机执行软件重置,以避免依赖于先前软件代理(例如引导加载程序/固件)可能先前配置的内容。负责撤消此处完成的任何适用分配或操作的方法是teardown
。port_setup
和port_teardown
: 用于初始化和销毁每个端口数据结构的方法。某些操作(例如注册和注销 devlink 端口区域)必须从这些方法中完成,否则它们是可选的。仅当端口之前已设置时,才会拆除该端口。可以在探测期间设置端口,然后立即将其拆除,例如,如果找不到其 PHY。在这种情况下,DSA 交换机的探测将继续,而不会探测该特定端口。port_change_conduit
: 可以通过此方法更改用户端口和 CPU 端口之间的关联(用于流量终止目的)。默认情况下,树中的所有用户端口都分配给对它们有意义的第一个可用 CPU 端口(大多数情况下,这意味着树的用户端口都分配给同一个 CPU 端口,但 H 拓扑结构除外,如 commit 2c0b03258b8b 中所述)。port
参数表示用户端口的索引,conduit
参数表示新的 DSA 导管net_device
。可以通过查看struct dsa_port *cpu_dp = conduit->dsa_ptr
来检索与新导管关联的 CPU 端口。此外,导管还可以是 LAG 设备,其中所有从设备都是物理 DSA 导管。LAG DSA 还具有有效的conduit->dsa_ptr
指针,但这并不是唯一的,而是第一个物理 DSA 导管(LAG 从设备)的dsa_ptr
的副本。对于 LAG DSA 导管,将为与物理 DSA 导管关联的物理 CPU 端口单独发出对port_lag_join
的进一步调用,请求它们创建与 LAG 接口关联的硬件 LAG。
PHY 设备和链路管理¶
get_phy_flags
: 某些交换机与各种以太网 PHY 连接,如果 PHY 库 PHY 驱动程序需要知道它无法自行获取的信息(例如:来自交换机内存映射寄存器),则此函数应返回 32 位 “标志” 位掩码,该掩码在交换机驱动程序和drivers/net/phy/*
中的以太网 PHY 驱动程序之间是私有的。phy_read
: 当尝试读取交换机端口 MDIO 寄存器时,由 DSA 用户 MDIO 总线调用的函数。如果不可用,则每次读取都返回 0xffff。对于内置交换机以太网 PHY,此函数应允许读取链路状态、自动协商结果、链路伙伴页面等。phy_write
: 当尝试写入交换机端口 MDIO 寄存器时,由 DSA 用户 MDIO 总线调用的函数。如果不可用,则返回负错误代码。adjust_link
: 当用户网络设备连接到 PHY 设备时,由 PHY 库调用的函数。此函数负责根据phy_device
提供的内容适当配置交换机端口链路参数:速度、双工、暂停。fixed_link_update
: 由 PHY 库调用,特别是当固定 PHY 驱动程序要求交换机驱动程序提供无法自动协商或通过 MDIO 读取 PHY 寄存器获得的链路参数时调用。这对于特定类型的硬件(例如 QSGMII、MoCA 或其他类型的非 MDIO 管理的 PHY)特别有用,在这些硬件中,链路外信息可以获取。
Ethtool 操作¶
get_strings
: 用于查询驱动程序字符串的 ethtool 函数,通常会返回统计字符串、私有标志字符串等。get_ethtool_stats
: 用于查询每个端口的统计信息并返回其值的 ethtool 函数。DSA 将用户网络设备的常规统计信息(来自网络设备的 RX/TX 计数器)与每个端口的交换机驱动程序特定统计信息叠加在一起。get_sset_count
: 用于查询统计信息项数量的 ethtool 函数get_wol
: 用于获取每个端口的 Wake-on-LAN 设置的 ethtool 函数。对于某些实现,如果此接口需要参与 Wake-on-LAN,此函数还可以查询导管网络设备的 Wake-on-LAN 设置set_wol
: 用于配置每个端口的 Wake-on-LAN 设置的 ethtool 函数,与 set_wol 的直接对应,具有类似的限制set_eee
: 用于配置交换机端口 EEE(绿色以太网)设置的 ethtool 函数,可以选择调用 PHY 库以在相关时在 PHY 级别启用 EEE。此函数应在交换机端口 MAC 控制器和数据处理逻辑中启用 EEEget_eee
: 用于查询交换机端口 EEE 设置的 ethtool 函数,此函数应返回交换机端口 MAC 控制器和数据处理逻辑的 EEE 状态,并查询 PHY 以获取其当前配置的 EEE 设置get_eeprom_len
: ethtool 函数,返回给定交换机的 EEPROM 长度/大小(以字节为单位)get_eeprom
: ethtool 函数,返回给定交换机的 EEPROM 内容set_eeprom
: ethtool 函数,将指定的数据写入给定交换机的 EEPROMget_regs_len
: ethtool 函数,返回给定交换机的寄存器长度get_regs
:ethtool 函数,返回以太网交换机内部寄存器内容。此函数可能需要在 ethtool 中使用用户态代码来美化打印寄存器值和寄存器。
电源管理¶
suspend
:当系统进入挂起状态时,由 DSA 平台设备调用的函数,应停止所有以太网交换机活动,但保持参与网络唤醒(Wake-on-LAN)的端口以及其他支持的唤醒逻辑处于活动状态。resume
:当系统恢复时,由 DSA 平台设备调用的函数,应恢复所有以太网交换机活动,并将交换机重新配置为完全活动状态。port_enable
:当端口以管理方式启动时,由 DSA 用户网络设备 ndo_open 函数调用的函数,此函数应完全启用给定的交换机端口。如果端口是网桥成员,DSA 负责将端口标记为BR_STATE_BLOCKING
;如果不是,则标记为BR_STATE_FORWARDING
,并将这些更改传播到硬件。port_disable
:当端口以管理方式关闭时,由 DSA 用户网络设备 ndo_close 函数调用的函数,此函数应完全禁用给定的交换机端口。如果该端口在作为网桥成员时被禁用,DSA 负责将端口标记为BR_STATE_DISABLED
并将更改传播到硬件。
地址数据库¶
交换硬件应具有 FDB 条目的表,但并非所有条目都同时处于活动状态。地址数据库是 FDB 条目的子集(分区),根据端口的状态,该子集处于活动状态(可以通过 RX 上的地址学习或 TX 上的 FDB 查找来匹配)。在本文档中,地址数据库有时可能被称为“FID”(过滤 ID),尽管底层实现可以选择硬件可用的任何内容。
例如,属于 VLAN 感知桥(当前为 VLAN 感知)的所有端口都应在驱动程序与该桥关联的数据库中学习源地址(而不是与其他 VLAN 感知桥关联的数据库)。在转发和 FDB 查找期间,在 VLAN 感知桥端口上接收的数据包应该能够找到与数据包具有相同 MAC DA 的 VLAN 感知 FDB 条目,该条目存在于同一桥的另一个端口成员上。同时,如果该条目指向属于不同 VLAN 感知桥(因此与不同的地址数据库关联)的端口,则 FDB 查找过程必须能够找不到与数据包具有相同 MAC DA 的 FDB 条目。
类似地,每个卸载的 VLAN 感知桥的每个 VLAN 都应具有关联的地址数据库,该数据库由作为该 VLAN 成员的所有端口共享,但不被属于同一 VID 的不同桥的端口共享。
在这种情况下,VLAN 感知数据库意味着所有数据包都应在不考虑 VLAN ID 的情况下进行匹配(仅限 MAC 地址查找),而 VLAN 感知数据库意味着数据包应根据分类的 802.1Q 标头中的 VLAN ID(如果未标记则为 pvid)进行匹配。
在桥接层,VLAN 感知 FDB 条目的特殊 VID 值为 0,而 VLAN 感知 FDB 条目的 VID 值不为零。请注意,VLAN 感知桥可能具有 VLAN 感知(非零 VID)FDB 条目,而 VLAN 感知桥可能具有 VLAN 感知 FDB 条目。与硬件一样,软件桥接器保留单独的地址数据库,并通过 switchdev 将属于这些数据库的 FDB 条目卸载到硬件,相对于数据库变为活动或不活动的时间异步进行。
当用户端口以独立模式运行时,其驱动程序应将其配置为使用称为端口私有数据库的单独数据库。这与上述数据库不同,应尽可能减少独立端口的操作(数据包进入、数据包输出到 CPU 端口)。例如,在入口处,它不应尝试学习入口流量的 MAC SA,因为学习是桥接层服务,而这是一个独立端口,因此会消耗无用的空间。在没有地址学习的情况下,端口私有数据库在简单的实现中应为空,在这种情况下,所有接收的数据包都应简单地洪泛到 CPU 端口。
DSA(级联)和 CPU 端口也称为“共享”端口,因为它们为多个地址数据库提供服务,并且数据包应关联到的数据库通常嵌入在 DSA 标记中。这意味着 CPU 端口可能会同时传输来自独立端口(由硬件分类到一个地址数据库中)和来自网桥端口(被分类到另一个地址数据库中)的数据包。
满足某些条件的交换机驱动程序可以通过从交换机的洪泛域中删除 CPU 端口来优化简单的配置,并且仅使用指向 CPU 端口的 FDB 条目对硬件进行编程,软件已知这些 CPU 端口对这些 MAC 地址感兴趣。不匹配已知 FDB 条目的数据包将不会传递到 CPU,这将节省创建 skb 并将其丢弃所需的 CPU 周期。
DSA 能够为以下类型的地址执行主机地址过滤
端口的主要单播 MAC 地址 (
dev->dev_addr
)。这些地址与各自用户端口的端口私有数据库相关联,并通过port_fdb_add
通知驱动程序将其安装到 CPU 端口。端口的辅助单播和多播 MAC 地址(通过
dev_uc_add()
和dev_mc_add()
添加的地址)。这些地址也与各自用户端口的端口私有数据库相关联。本地/永久桥 FDB 条目 (
BR_FDB_LOCAL
)。这些是网桥端口的 MAC 地址,对于这些地址,数据包必须在本地终止,而不会转发。它们与该桥的地址数据库相关联。向与某些 DSA 交换机端口存在于同一网桥中的外部(非 DSA)接口安装的静态桥 FDB 条目。这些条目也与该桥的地址数据库相关联。
如果驱动程序将
ds->assisted_learning_on_cpu_port
设置为 true,则在与某些 DSA 交换机端口存在于同一网桥中的外部接口上动态学习的 FDB 条目。这些条目与该桥的地址数据库相关联。
对于下面详述的各种操作,DSA 提供了一个 dsa_db
结构,该结构可以是以下类型之一
DSA_DB_PORT
:要安装或删除的 FDB(或 MDB)条目属于用户端口db->dp
的端口私有数据库。DSA_DB_BRIDGE
:该条目属于桥db->bridge
的一个地址数据库。此桥的 VLAN 感知数据库和每个 VID 的数据库之间的分离预计由驱动程序完成。DSA_DB_LAG
:该条目属于 LAGdb->lag
的地址数据库。注意:DSA_DB_LAG
当前未使用,将来可能会被删除。
对 port_fdb_add
、port_mdb_add
等中的 dsa_db
参数起作用的驱动程序应将 ds->fdb_isolation
声明为 true。
为了对共享端口上的地址进行引用计数,DSA 将每个卸载的网桥和每个卸载的 LAG 与一个从 1 开始的 ID (struct dsa_bridge :: num
、struct dsa_lag :: id
) 相关联。驱动程序可以使用 DSA 的编号方案(ID 可以通过 db->bridge.num
和 db->lag.id
读取),或者可以实现自己的编号方案。
只有声明支持 FDB 隔离的驱动程序才会收到 CPU 端口上属于 DSA_DB_PORT
数据库的 FDB 条目的通知。出于兼容性/遗留原因,即使驱动程序不支持 FDB 隔离,也会将 DSA_DB_BRIDGE
地址通知给驱动程序。但是,在这种情况下,db->bridge.num
和 db->lag.id
始终设置为 0(表示缺少隔离,用于引用计数)。
请注意,对于交换机驱动程序来说,为每个独立的独立用户端口实现物理上独立的地址数据库不是强制性的。由于端口私有数据库中的 FDB 条目将始终指向 CPU 端口,因此不存在不正确的转发决策的风险。在这种情况下,所有独立端口可以共享同一个数据库,但是主机过滤地址的引用计数(如果端口的 MAC 地址仍在被另一个端口使用,则不删除该地址的 FDB 条目)将由驱动程序负责,因为 DSA 不知道端口数据库实际上是共享的。可以通过调用 dsa_fdb_present_in_other_db()
和 dsa_mdb_present_in_other_db()
来实现此目的。缺点是,每个用户端口的 RX 过滤列表实际上是共享的,这意味着用户端口 A 可能会接收到它不应该接收的具有 MAC DA 的数据包,仅仅是因为该 MAC 地址在用户端口 B 的 RX 过滤列表中。但是,这些数据包仍然会在软件中被丢弃。
桥接层¶
卸载桥接转发平面是可选的,并通过以下方法处理。它们可能不存在,返回 -EOPNOTSUPP,或者 ds->max_num_bridges
可能为非零值并且已超出,在这种情况下,仍然可以加入网桥端口,但是数据包转发将在软件中进行,并且软件网桥下的端口必须保持与独立操作相同的方式配置,即禁用所有桥接服务功能(地址学习等),并且仅将所有接收的数据包发送到 CPU 端口。
具体来说,当端口成功返回 port_bridge_join
方法时,该端口就开始卸载网桥的转发平面,并在调用 port_bridge_leave
后停止卸载。卸载网桥意味着根据软件网桥端口的状态自主学习 FDB 条目,并自主转发(或泛洪)接收到的数据包,而无需 CPU 干预。即使在卸载网桥端口时,这也是可选的。标签协议驱动程序应为已经在入口交换机端口的转发域中自主转发的数据包调用 dsa_default_offload_fwd_mark(skb)
。DSA 通过 dsa_port_devlink_setup()
,将所有属于同一树 ID 的交换机端口视为同一网桥转发域的一部分(能够彼此自主转发)。
卸载网桥的 TX 转发过程与简单地卸载其转发平面是一个不同的概念,它指的是某些驱动程序和标签协议组合将来自网桥设备的传输函数的单个 skb 传输到多个出口端口(从而避免在软件中克隆它)的能力。
网桥请求此行为的数据包称为数据平面数据包,并在标签协议驱动程序的 xmit
函数中将 skb->offload_fwd_mark
设置为 true。数据平面数据包需要进行 FDB 查找、CPU 端口上的硬件学习,并且不会覆盖端口 STP 状态。此外,数据平面数据包的复制(组播、泛洪)在硬件中处理,网桥驱动程序将为每个可能需要复制的数据包传输一个 skb。
当启用 TX 转发卸载时,标签协议驱动程序负责将数据包注入到硬件的数据平面,使其到达端口所属的正确桥接域(FID)。该端口可能是不感知 VLAN 的,在这种情况下,FID 必须等于驱动程序用于与其网桥关联的不感知 VLAN 地址数据库的 FID。或者,网桥可能是感知 VLAN 的,在这种情况下,可以保证数据包也使用网桥处理该数据包时所使用的 VLAN ID 进行 VLAN 标记。硬件负责在出口未标记端口上取消 VID 标记,或在出口标记端口上保留标记。
port_bridge_join
:当给定的交换机端口添加到网桥时调用的网桥层函数,此函数应在交换机级别执行必要的操作,以允许加入的端口添加到相关的逻辑域,以便与网桥的其他成员一起接收/发送流量。通过将tx_fwd_offload
参数设置为 true,还可以卸载此网桥的 TX 转发过程。port_bridge_leave
:当从网桥中删除给定的交换机端口时调用的网桥层函数,此函数应在交换机级别执行必要的操作,以拒绝离开的端口接收/发送来自剩余网桥成员的流量。port_stp_state_set
:当网桥层计算出给定的交换机端口 STP 状态时调用的网桥层函数,应将其传播到交换机硬件以转发/阻止/学习流量。port_bridge_flags
:当端口必须配置其设置(例如,未知流量的泛洪或源地址学习)时调用的网桥层函数。交换机驱动程序负责使用禁用地址学习和所有类型流量的出口泛洪来初始设置独立端口,然后当端口加入和离开网桥时,DSA 核心会通知网桥端口标志的任何更改。DSA 当前不管理 CPU 端口的网桥端口标志。假设应该在 CPU 端口上静态启用地址学习(如果硬件支持),并且由于 DSA 核心中缺少显式地址过滤机制,还应启用向 CPU 端口的泛洪。port_fast_age
:当需要刷新端口上动态学习的 FDB 条目时调用的网桥层函数。当从应进行学习的 STP 状态转换到不应进行学习的 STP 状态,或者当离开网桥时,或者通过port_bridge_flags
关闭地址学习时,会调用此函数。
网桥 VLAN 过滤¶
port_vlan_filtering
:当配置网桥以打开或关闭 VLAN 过滤时调用的网桥层函数。如果不需要在硬件级别执行任何特定操作,则不需要实现此回调。当打开 VLAN 过滤时,必须对硬件进行编程,以拒绝 VLAN ID 在编程允许的 VLAN ID 映射/规则之外的 802.1Q 帧。如果未在交换机端口中编程 PVID,则还必须拒绝未标记的帧。关闭时,交换机必须接受任何 802.1Q 帧,而不管其 VLAN ID 如何,并且允许未标记的帧。port_vlan_add
:当为给定的交换机端口配置 VLAN(标记或未标记)时调用的网桥层函数。只有当外部网桥端口也是 VLAN 的成员(并且需要在软件中进行转发)时,或者为了终止目的,将 VLAN 安装到网桥设备本身的 VLAN 组时,CPU 端口才会成为 VLAN 的成员(bridge vlan add dev br0 vid 100 self
)。共享端口上的 VLAN 将进行引用计数,并在没有用户剩余时删除。驱动程序不需要手动在 CPU 端口上安装 VLAN。port_vlan_del
:当从给定的交换机端口中删除 VLAN 时调用的网桥层函数port_fdb_add
:当网桥想要安装转发数据库条目时调用的网桥层函数,应在与此 VLAN ID 关联的转发数据库中,使用指定的地址在指定的 VLAN ID 中对交换机硬件进行编程。port_fdb_del
:当网桥想要删除转发数据库条目时调用的网桥层函数,应将交换机硬件编程为从指定的 VLAN ID 中删除指定的 MAC 地址(如果该地址已映射到此端口转发数据库中)port_fdb_dump
:在物理 DSA 端口接口上由ndo_fdb_dump
调用的网桥旁路函数。由于 DSA 不尝试将其硬件 FDB 条目与软件网桥保持同步,因此实现此方法是为了查看硬件数据库中用户端口上可见的条目。此函数报告的条目在bridge fdb show
命令的输出中具有self
标志。port_mdb_add
:当网桥想要安装组播数据库条目时调用的网桥层函数。应在与此 VLAN ID 关联的转发数据库中,使用指定的地址在指定的 VLAN ID 中对交换机硬件进行编程。port_mdb_del
:当网桥想要删除组播数据库条目时调用的网桥层函数,应将交换机硬件编程为从指定的 VLAN ID 中删除指定的 MAC 地址(如果该地址已映射到此端口转发数据库中)。
链路聚合¶
链路聚合在 Linux 网络堆栈中由绑定和团队驱动程序实现,它们被建模为虚拟的、可堆叠的网络接口。DSA 能够将链路聚合组 (LAG) 卸载到支持此功能的硬件,并支持物理端口和 LAG 之间以及 LAG 之间的桥接。拥有多个物理端口的绑定/团队接口构成一个逻辑端口,尽管 DSA 目前没有逻辑端口的明确概念。因此,LAG 加入/离开网桥的事件被视为该 LAG 的所有成员的单个物理端口加入/离开网桥。卸载到作为网桥端口的 LAG 的 Switchdev 端口属性(VLAN 过滤、STP 状态等)和对象(VLAN、MDB 条目)的处理方式类似:DSA 在 LAG 的所有成员上卸载相同的 switchdev 对象/端口属性。由于 DSA 驱动程序 API 没有逻辑端口 ID 的概念,因此尚不支持 LAG 上的静态网桥 FDB 条目。
port_lag_join
:当给定的交换机端口添加到 LAG 时调用的函数。驱动程序可能返回-EOPNOTSUPP
,在这种情况下,DSA 将回退到软件实现,其中来自此端口的所有流量都将发送到 CPU。port_lag_leave
:当给定的交换机端口离开 LAG 并返回作为独立端口运行时调用的函数。port_lag_change
:当 LAG 的任何成员的链路状态发生更改时调用的函数,并且需要重新平衡哈希函数以仅使用已启动的物理 LAG 成员端口的子集。
可以从与每个卸载的 LAG 关联的 ID 中受益的驱动程序可以选择从 dsa_switch_ops::setup
方法中填充 ds->num_lag_ids
。然后,DSA 交换机驱动程序可以使用 dsa_lag_id
函数检索与绑定/团队接口关联的 LAG ID。
IEC 62439-2 (MRP)¶
媒体冗余协议是一种为环形网络优化以实现快速故障恢复时间的拓扑管理协议,它的一些组件是作为网桥驱动程序的功能实现的。MRP 使用管理 PDU(测试、拓扑、链路断开/启动、选项),这些 PDU 以 01:15:4e:00:00:0x 的组播目标 MAC 地址范围和 0x88e3 的以太网类型发送。根据节点在环形网络中的角色(MRM:媒体冗余管理器、MRC:媒体冗余客户端、MRA:媒体冗余自动管理器),某些 MRP PDU 可能需要在本地终止,而其他 PDU 可能需要转发。MRM 还可以从将某些 MRP PDU(测试)的创建和传输卸载到硬件中受益。
通常,MRP实例可以在任何网络接口之上创建。但是,对于具有卸载数据路径的设备(例如DSA),即使硬件本身不感知MRP,也必须能够从结构中提取MRP PDU,然后驱动程序才能继续进行软件实现。目前,DSA没有感知MRP的驱动程序,因此它只监听软件辅助正常工作所需的最低限度的switchdev对象。具体操作如下详述。
port_mrp_add
和port_mrp_del
:当创建/删除具有特定环ID、优先级、主端口和辅助端口的MRP实例时,通知驱动程序。port_mrp_add_ring_role
和port_mrp_del_ring_role
:当MRP实例在MRM或MRC之间更改环角色时调用的函数。这会影响哪些MRP PDU应捕获到软件,哪些应自主转发。
IEC 62439-3 (HSR/PRP)¶
并行冗余协议 (PRP) 是一种网络冗余协议,其工作原理是通过两个独立的 L2 网络(不感知数据包中携带的 PRP 尾部标签)复制和序列编号数据包,并在接收器端消除重复项。高可用性无缝冗余 (HSR) 协议在概念上类似,只是所有携带冗余流量的节点都知道它是 HSR 标记的(因为 HSR 使用 EtherType 为 0x892f 的报头),并且以环形拓扑物理连接。HSR 和 PRP 都使用监视帧来监视网络健康状况和发现其他节点。
在 Linux 中,HSR 和 PRP 都在 hsr 驱动程序中实现,该驱动程序实例化一个具有两个成员端口的虚拟、可堆叠的网络接口。该驱动程序仅实现 DANH(实现 HSR 的双附着节点)和 DANP(实现 PRP 的双附着节点)的基本角色;RedBox 和 QuadBox 的角色未实现(因此,将 hsr 网络接口与物理交换机端口桥接不会产生预期的结果)。
能够卸载 DANP 或 DANH 的某些功能的驱动程序应声明相应的 netdev 功能,如 Documentation/networking/netdev-features.rst
中的文档所示。此外,必须实现以下方法
port_hsr_join
:当给定交换机端口添加到 DANP/DANH 时调用的函数。驱动程序可能会返回-EOPNOTSUPP
,在这种情况下,DSA 将回退到软件实现,其中来自此端口的所有流量都将发送到 CPU。port_hsr_leave
:当给定交换机端口离开 DANP/DANH 并恢复为独立端口的正常操作时调用的函数。
TODO¶
使 SWITCHDEV 和 DSA 向统一的代码库收敛¶
SWITCHDEV 适当地抽象了具有卸载功能的硬件的网络堆栈,但并未强制执行严格的交换机设备驱动程序模型。另一方面,DSA 强制执行相当严格的设备驱动程序模型,并处理大多数特定于交换机的内容。在某个时候,我们应该设想这两个子系统之间的合并,并获得两者的最佳特性。