架构¶
本文档介绍了分布式交换机架构 (DSA) 子系统的设计原则、局限性、与其他子系统的交互,以及如何为此子系统开发驱动程序,以及有兴趣参与此项工作的开发人员的 TODO。
设计原则¶
分布式交换机架构子系统最初设计用于支持 Marvell 以太网交换机(MV88E6xxx,也称为 Link Street 产品线),使用 Linux,但后来发展为支持其他供应商。
此设计背后的最初理念是能够使用未修改的 Linux 工具(例如 bridge、iproute2、ifconfig)来透明地工作,无论它们是配置/查询交换机端口网络设备还是常规网络设备。
以太网交换机通常包含多个前面板端口以及一个或多个 CPU 或管理端口。DSA 子系统当前依赖于连接到以太网控制器的管理端口的存在,该控制器能够从交换机接收以太网帧。这是在小型家庭和办公室产品(路由器、网关,甚至是架顶式交换机)中发现的各种以太网交换机的一种非常常见的设置。此主机以太网控制器将在 DSA 术语和代码中稍后被称为“导管 (conduit)”和“cpu”。
DSA 中的 D 代表分布式,因为该子系统被设计为能够使用交换机之间的上游和下游以太网链路来配置和管理彼此之上的级联交换机。这些特定端口在 DSA 术语和代码中被称为“dsa”端口。连接在一起的多个交换机的集合称为“交换机树”。
对于每个前面板端口,DSA 创建专门的网络设备,这些设备用作 Linux 网络堆栈使用的控制和数据流端点。这些专门的网络接口在 DSA 术语和代码中被称为“用户 (user)”网络接口。
使用 DSA 的理想情况是当以太网交换机支持“交换机标签 (switch tag)”时,这是一种硬件功能,使交换机为它接收的每个以太网帧插入一个特定的标签,以帮助管理接口确定
此帧来自哪个端口
此帧被转发的原因是什么
如何将 CPU 发起的流量发送到特定端口
该子系统确实支持无法插入/剥离标签的交换机,但在这种情况下,功能可能会受到一些限制(流量分离依赖于基于端口的 VLAN ID)。
请注意,DSA 当前不为“cpu”和“dsa”端口创建网络接口,因为
“cpu”端口是管理控制器的以太网交换机侧,因此会创建功能重复,因为您会获得两个接口用于同一导管:导管 netdev 和“cpu” netdev
“dsa”端口只是两个或多个交换机之间的导管,因此也不能真正用作适当的网络接口,只有下游或最顶端的上游接口才符合该模型
注意:在过去的 15 年里,DSA 子系统一直在使用术语“主 (master)”(而不是“导管 (conduit)”)和“从 (slave)”(而不是“用户 (user)”)。这些术语已从 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
八位字节,即,如果没有标记此帧,则指向 EtherType 之后的第一个八位字节的位置。此方法的作用是消耗帧头,调整 skb->data
以真正指向 EtherType 之后的第一个八位字节,并将 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 操作:统计信息、链路状态、Wake-on-LAN、寄存器转储...
管理外部/内部 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
,后者调用指向 LAG DSA 导管的 dev_queue_xmit
。后者调用指向一个或另一个物理 DSA 导管的 dev_queue_xmit
,在这两种情况下,数据包都通过通向交换机的硬件路径退出系统。
图形表示¶
总而言之,这基本上就是从网络设备角度来看 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 总线,该总线允许特定的交换机驱动程序分流和拦截对特定 PHY 地址的 MDIO 读取/写入。在大多数 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 端口链路参数: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)的数据片段(例如地址表和 VLAN 表),也可以导出 devlink 区域。例如,如果这些表包含其他硬件特定的详细信息,这些详细信息无法通过 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 交换机是总线上的常规 device
结构(平台总线、SPI 总线、I2C 总线、MDIO 总线或其他总线)。DSA 框架不参与设备核心的探测。
从驱动程序的角度来看,交换机注册意味着将有效的 struct dsa_switch
指针传递给 dsa_register_switch()
,通常从交换机驱动程序的探测函数中进行。提供的结构中必须包含以下有效成员:
ds->dev
:将用于解析交换机的 OF 节点或平台数据。ds->num_ports
:将用于创建此交换机的端口列表,并验证 OF 节点中提供的端口索引。ds->ops
:指向dsa_switch_ops
结构的指针,其中包含 DSA 方法的实现。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 的多个交换机是非法的,会导致错误。使用平台数据时,允许单个交换机和单个交换机树。
在具有多个交换机的树中,探测以不对称方式进行。前 N-1 个 dsa_register_switch()
调用者仅将其端口添加到树的端口列表 (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 保留了对 conduit 网络设备的引用,如果 conduit 设备的驱动程序决定在关闭时解除绑定,则 DSA 的引用将阻止该操作完成。
必须调用 dsa_switch_shutdown()
或 dsa_unregister_switch()
,但不能同时调用,并且即使已经调用了 shutdown()
,设备驱动程序模型也允许调用总线的 remove()
方法。因此,驱动程序需要实现 remove()
和 shutdown()
之间的互斥方法,方法是在任何一个运行后将其 drvdata 设置为 NULL,并在继续执行任何操作之前检查 drvdata 是否为 NULL。
在调用 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 端口,除了 commit 2c0b03258b8b 中描述的 H 拓扑)。port
参数表示用户端口的索引,conduit
参数表示新的 DSA 导线net_device
。与新导线关联的 CPU 端口可以通过查看struct dsa_port *cpu_dp = conduit->dsa_ptr
来检索。此外,导线也可以是 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
:当 DSA 用户 MDIO 总线尝试读取交换机端口 MDIO 寄存器时调用的函数。如果不可用,则每次读取返回 0xffff。对于内置的交换机以太网 PHY,此函数应允许读取链路状态、自动协商结果、链路合作伙伴页面等。phy_write
:当 DSA 用户 MDIO 总线尝试写入交换机端口 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
:ethtool 函数,用于获取每个端口的 Wake-on-LAN 设置,对于某些实现,如果此接口需要参与 Wake-on-LAN,则此函数还可以查询导线网络设备的 Wake-on-LAN 设置。set_wol
:ethtool 函数,用于配置每个端口的 Wake-on-LAN 设置,与 set_wol 直接对应,具有类似的限制。set_eee
:ethtool 函数,用于配置交换机端口 EEE(绿色以太网)设置,可以选择调用 PHY 库以在 PHY 级别启用 EEE(如果相关)。此函数应在交换机端口 MAC 控制器和数据处理逻辑中启用 EEE。get_eee
:ethtool 函数,用于查询交换机端口 EEE 设置,此函数应返回交换机端口 MAC 控制器和数据处理逻辑的 EEE 状态,并查询 PHY 以获取其当前配置的 EEE 设置。get_eeprom_len
:ethtool 函数,返回给定交换机的 EEPROM 长度/大小(以字节为单位)。get_eeprom
:ethtool 函数,返回给定交换机的 EEPROM 内容。set_eeprom
:ethtool 函数,将指定的数据写入给定的交换机 EEPROM。get_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 标头(或未标记时的 pvid)中的 VLAN ID 进行匹配。
在桥层,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 条目对硬件进行编程,已知软件对这些 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 条目。这些地址也与该桥的地址数据库关联。
在与某些 DSA 交换机端口位于同一桥中的外部接口上动态学习的 FDB 条目,前提是驱动程序将
ds->assisted_learning_on_cpu_port
设置为 true。这些地址与该桥的地址数据库关联。
对于下面详述的各种操作,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 与一个从一开始的 ID 关联(struct dsa_bridge :: num
、struct dsa_lag :: id
),以便在共享端口上对地址进行引用计数。驱动程序可以在 DSA 的编号方案(可以通过 db->bridge.num
和 db->lag.id
读取 ID)上搭载,也可以实现自己的编号方案。
只有声明支持 FDB 隔离的驱动程序才会收到属于 DSA_DB_PORT
数据库的 CPU 端口上的 FDB 条目的通知。出于兼容性/遗留原因,即使驱动程序不支持 FDB 隔离,也会将 DSA_DB_BRIDGE
地址通知给驱动程序。但是,在这种情况下,db->bridge.num
和 db->lag.id
始终设置为 0(表示缺少隔离,用于引用计数目的)。
请注意,交换机驱动程序不一定需要为每个独立的User Port实现物理上分离的地址数据库。由于端口私有数据库中的FDB条目始终指向CPU端口,因此不存在错误转发决策的风险。在这种情况下,所有独立的端口可以共享同一个数据库,但是主机过滤地址的引用计数(如果端口的MAC地址仍在被其他端口使用,则不删除该端口的FDB条目)将成为驱动程序的责任,因为DSA并不知道端口数据库实际上是共享的。这可以通过调用dsa_fdb_present_in_other_db()
和 dsa_mdb_present_in_other_db()
来实现。缺点是每个User Port的RX过滤列表实际上是共享的,这意味着User Port A可能会接收到本不应该接收的MAC DA数据包,仅仅是因为该MAC地址在User Port B的RX过滤列表中。但是,这些数据包仍然会在软件中被丢弃。
桥接层¶
卸载桥接转发平面是可选的,由以下方法处理。它们可能不存在,返回-EOPNOTSUPP,或者ds->max_num_bridges
可能非零且超出限制,在这种情况下,仍然可以加入桥接端口,但数据包转发将在软件中进行,并且软件桥接下的端口必须保持与独立操作相同的方式配置,即禁用所有桥接服务功能(地址学习等),并且仅将所有接收到的数据包发送到CPU端口。
具体来说,当端口成功返回port_bridge_join
方法时,该端口开始卸载桥接的转发平面,并在调用port_bridge_leave
后停止卸载。卸载桥接意味着根据软件桥接端口的状态自主学习FDB条目,以及自主转发(或广播)接收到的数据包,而无需CPU干预。即使卸载桥接端口,这也是可选的。期望Tagging协议驱动程序为已经在入口交换机端口的转发域中自主转发的数据包调用dsa_default_offload_fwd_mark(skb)
。DSA通过dsa_port_devlink_setup()
,将属于同一树ID的所有交换机端口视为同一桥接转发域的一部分(能够相互自主转发)。
卸载桥接的TX转发过程与简单地卸载其转发平面是一个不同的概念,指的是某些驱动程序和Tagging协议组合能够将来自桥接设备传输功能的单个skb传输到潜在的多个出口端口(从而避免在软件中克隆它)。
桥接请求此行为的数据包称为数据平面数据包,并且在Tagging协议驱动程序的xmit
函数中将skb->offload_fwd_mark
设置为true。数据平面数据包受FDB查找、CPU端口上的硬件学习的影响,并且不覆盖端口的STP状态。此外,数据平面数据包的复制(多播、广播)在硬件中处理,并且桥接驱动程序将为每个可能需要或不需要复制的数据包传输单个skb。
启用TX转发卸载后,Tagging协议驱动程序负责将数据包注入到硬件的数据平面中,并使其指向端口所属的正确的桥接域 (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 网络堆栈中由 bonding 和 team 驱动程序实现,这些驱动程序被建模为虚拟的、可堆叠的网络接口。DSA 能够将链路聚合组 (LAG) 卸载到支持该功能的硬件,并支持物理端口和 LAG 之间以及 LAG 之间的桥接。容纳多个物理端口的 bonding/team 接口构成一个逻辑端口,尽管 DSA 目前没有逻辑端口的明确概念。因此,LAG 加入/离开桥接的事件被视为该 LAG 的所有单个物理端口加入/离开桥接。作为桥接端口卸载到 LAG 的 Switchdev 端口属性(VLAN 过滤、STP 状态等)和对象(VLAN、MDB 条目)的处理方式类似:DSA 在 LAG 的所有成员上卸载相同的 switchdev 对象/端口属性。尚不支持 LAG 上的静态桥接 FDB 条目,因为 DSA 驱动程序 API 没有逻辑端口 ID 的概念。
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
函数检索与 bonding/team 接口关联的 LAG ID。
IEC 62439-2 (MRP)¶
媒体冗余协议是一种拓扑管理协议,针对环形网络的快速故障恢复时间进行了优化,它的一些组件实现为桥接驱动程序的功能。MRP 使用管理 PDU(测试、拓扑、链路关闭/开启、选项),以 01:15:4e:00:00:0x 的多播目标 MAC 地址范围和 0x88e3 的 EtherType 发送。根据节点在环中的角色(MRM:媒体冗余管理器,MRC:媒体冗余客户端,MRA:媒体冗余自动管理器),某些 MRP 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 的某些功能,则应按照 Documentation/networking/netdev-features.rst
的文档指示声明相应的 netdev 功能。此外,必须实现以下方法
port_hsr_join
:当给定的交换机端口添加到 DANP/DANH 时调用的函数。驱动程序可能返回-EOPNOTSUPP
,在这种情况下,DSA 将回退到软件实现,其中来自此端口的所有流量都将发送到 CPU。port_hsr_leave
:当给定的交换机端口离开 DANP/DANH 并返回作为独立端口的正常运行时调用的函数。
TODO¶
使 SWITCHDEV 和 DSA 收敛到统一的代码库¶
SWITCHDEV 正确地处理了抽象具有卸载功能的硬件的网络堆栈,但不强制执行严格的交换机设备驱动程序模型。另一方面,DSA 强制执行相当严格的设备驱动程序模型,并处理大多数交换机特定的问题。在某些时候,我们应该设想这两个子系统之间的合并,并获得两全其美的好处。