网络功能表示器¶
本文档描述了表示器网络设备(netdevices)的语义和用法,用于控制智能网卡上的内部交换。对于物理(多端口)交换机上密切相关的端口表示器,请参阅Documentation/networking/switchdev.rst。
动机¶
自 2010 年代中期以来,网卡开始提供比传统的 SR-IOV 方法(及其简单的基于 MAC/VLAN 的交换模型)所能支持的更复杂的虚拟化功能。这导致人们希望将软件定义网络(例如 OpenVSwitch)卸载到这些网卡,以指定每个功能的网络连接。由此产生的设计被称为智能网卡或 DPU。
网络功能表示器将标准的 Linux 网络堆栈带到虚拟交换机和 IOV 设备。正如 Linux 控制的交换机的每个物理端口都有一个单独的网络设备一样,虚拟交换机的每个虚拟端口也是如此。当系统启动时,在配置任何卸载之前,来自虚拟功能的所有数据包都通过表示器出现在 PF 的网络堆栈中。因此,PF 始终可以与虚拟功能自由通信。PF 可以在表示器、上行链路或任何其他网络设备之间配置标准的 Linux 转发(路由、桥接、TC 分类器)。
因此,表示器既是控制平面对象(在管理命令中表示功能),又是数据平面对象(虚拟管道的一端)。作为虚拟链路端点,表示器可以像任何其他网络设备一样配置;在某些情况下(例如链路状态),被表示者将遵循表示器的配置,而在其他情况下,则有单独的 API 来配置被表示者。
定义¶
本文档使用术语“switchdev 功能”来指代对设备上的虚拟交换机具有管理控制权的 PCIe 功能。通常,这将是一个 PF,但可以想象的是,网卡可以配置为将这些管理权限授予 VF 或 SF(子功能)。根据网卡设计,多端口网卡可能对整个设备只有一个 switchdev 功能,或者可能为每个物理网络端口都有一个单独的虚拟交换机,因此也有一个单独的 switchdev 功能。如果网卡支持嵌套交换,则每个嵌套交换机可能都有单独的 switchdev 功能,在这种情况下,每个 switchdev 功能应该只为其直接管理的(子)交换机上的端口创建表示器。
“被表示者”是表示器表示的对象。因此,例如,在 VF 表示器的情况下,被表示者是相应的 VF。
表示器做什么?¶
表示器有三个主要作用。
它用于配置被表示者看到的网络连接,例如链路启动/关闭、MTU 等。例如,以管理方式启动表示器应导致被表示者看到链路启动/载波开启事件。
它为虚拟交换机中未命中任何卸载快速路径规则的流量提供慢速路径。在表示器网络设备上发送的数据包应被传递给被表示者;被表示者发送的未匹配任何交换规则的数据包应在表示器网络设备上接收。(也就是说,存在一个连接表示器和被表示者的虚拟管道,其概念类似于 veth 对。)这允许软件交换机实现(例如 OpenVSwitch 或 Linux 网桥)在被表示者和网络的其余部分之间转发数据包。
它充当切换规则(例如 TC 过滤器)可以引用被表示者的句柄,从而允许将这些规则卸载。
2) 和 3) 的结合意味着行为(除了性能)应该相同,无论是否卸载 TC 过滤器。例如,VF 表示器上的 TC 规则在软件中应用于在该表示器网络设备上接收的数据包,而在硬件卸载中,它将应用于被表示者 VF 发送的数据包。相反,对 VF 表示器的镜像出口重定向在硬件中对应于直接传递到被表示者 VF。
哪些功能应该有表示器?¶
本质上,对于设备内部交换机上的每个虚拟端口,都应该有一个表示器。一些供应商选择省略上行链路和物理网络端口的表示器,这可以简化使用(上行链路网络设备实际上成为物理端口的表示器),但不适用于具有多个端口或上行链路的设备。
因此,以下所有内容都应该有表示器
属于 switchdev 功能的 VF。
本地 PCIe 控制器上的其他 PF 以及属于它们的任何 VF。
设备上外部 PCIe 控制器上的 PF 和 VF(例如,对于智能网卡中的任何嵌入式片上系统)。
具有其他特性的 PF 和 VF,包括网络块设备(例如由远程/分布式存储支持的 vDPA virtio-blk PF),如果(且仅当)它们的网络访问是通过虚拟交换机端口实现的。 [1] 请注意,即使被表示者没有网络设备,此类功能也可能需要表示器。
如果子功能在交换机上有自己的端口(而不是使用其父 PF 的端口),则属于上述任何 PF 或 VF 的子功能 (SF)。
设备上任何通过虚拟交换机端口连接到网络的加速器或插件,即使它们没有相应的 PCIe PF 或 VF。
这允许通过表示器 TC 规则控制网卡的整个交换行为。
一个常见的误解是将虚拟端口与 PCIe 虚拟功能或其网络设备混淆。虽然在简单的情况下,VF 网络设备和 VF 表示器之间将存在 1:1 的对应关系,但更高级的设备配置可能不遵循此规律。通过内部交换机(甚至不是通过功能提供的任何服务的硬件实现间接)不具有网络访问权限的 PCIe 功能不应具有表示器(即使它具有网络设备)。此类功能没有用于表示器配置的交换机虚拟端口,也不是虚拟管道的另一端。表示器表示虚拟端口,而不是 PCIe 功能或“最终用户”网络设备。
如何创建表示器?¶
附加到 switchdev 功能的驱动程序实例应该为交换机上的每个虚拟端口创建一个纯软件网络设备,该网络设备具有某种形式的内核引用,指向 switchdev 功能自身的网络设备或驱动程序私有数据(netdev_priv()
)。这可以通过在探测时枚举端口、在运行时动态响应端口的创建和销毁,或两者结合来实现。
表示器网络设备的操作通常涉及通过 switchdev 功能进行操作。例如,ndo_start_xmit()
可能会通过连接到 switchdev 功能的硬件 TX 队列发送数据包,其中数据包元数据或队列配置将其标记为传递给被表示者。
如何标识表示器?¶
表示器网络设备不应直接引用 PCIe 设备(例如,通过 net_dev->dev.parent
/ SET_NETDEV_DEV()
),无论是被表示者还是 switchdev 功能。相反,驱动程序应使用 SET_NETDEV_DEVLINK_PORT
宏在注册网络设备之前将 devlink 端口实例分配给该网络设备;内核使用 devlink 端口来提供 phys_switch_id
和 phys_port_name
sysfs 节点。(一些旧版驱动程序直接实现 ndo_get_port_parent_id()
和 ndo_get_phys_port_name()
,但这已弃用。)有关此 API 的详细信息,请参阅 Documentation/networking/devlink/devlink-port.rst。
预期用户空间将使用此信息(例如,通过 udev 规则)为网络设备构造一个适当的信息性名称或别名。例如,如果 switchdev 功能是 eth4
,则 phys_port_name
为 p0pf1vf2
的表示器可能会重命名为 eth4pf1vf2rep
。
对于不对应于 PCIe 功能(例如,加速器和插件)的表示器的命名,目前尚未建立约定。
表示器如何与 TC 规则交互?¶
表示器上的任何 TC 规则都(在软件 TC 中)应用于该表示器网络设备接收的数据包。因此,如果规则的传递部分对应于虚拟交换机上的另一个端口,则驱动程序可以选择将其卸载到硬件,并将其应用于被表示者发送的数据包。
类似地,由于针对表示器的 TC 镜像出口操作(在软件中)会将数据包通过表示器发送(从而间接将其传递给被表示者),因此硬件卸载应将其解释为传递给被表示者。
作为一个简单的示例,如果 PORT_DEV
是物理端口的代表,而 REP_DEV
是 VF 的代表,则以下规则
tc filter add dev $REP_DEV parent ffff: protocol ipv4 flower \
action mirred egress redirect dev $PORT_DEV
tc filter add dev $PORT_DEV parent ffff: protocol ipv4 flower skip_sw \
action mirred egress mirror dev $REP_DEV
意味着来自 VF 的所有 IPv4 数据包都会发送到物理端口,并且物理端口上接收到的所有 IPv4 数据包都会传递给 VF,同时也会传递给 PORT_DEV
。(请注意,如果第二条规则没有 skip_sw
,则 VF 会收到两份副本,因为在 PORT_DEV
上接收数据包会再次触发 TC 规则并将数据包镜像到 REP_DEV
。)
在没有单独的端口和上行链路代表设备的设备上,PORT_DEV
将是 switchdev 功能自身的上行链路网络设备。
当然,这些规则(如果 NIC 支持)可以包括数据包修改操作(例如,VLAN 推送/弹出),这些操作应由虚拟交换机执行。
隧道封装和解封装则更为复杂,因为它们涉及到第三个网络设备(以元数据模式运行的隧道网络设备,例如使用 ip link add vxlan0 type vxlan external
创建的 VxLAN 设备),并且需要将 IP 地址绑定到底层设备(例如,switchdev 功能上行链路网络设备或端口代表)。TC 规则例如
tc filter add dev $REP_DEV parent ffff: flower \
action tunnel_key set id $VNI src_ip $LOCAL_IP dst_ip $REMOTE_IP \
dst_port 4789 \
action mirred egress redirect dev vxlan0
tc filter add dev vxlan0 parent ffff: flower enc_src_ip $REMOTE_IP \
enc_dst_ip $LOCAL_IP enc_key_id $VNI enc_dst_port 4789 \
action tunnel_key unset action mirred egress redirect dev $REP_DEV
其中 LOCAL_IP
是绑定到 PORT_DEV
的 IP 地址,而 REMOTE_IP
是同一子网上的另一个 IP 地址,这意味着 VF 发送的数据包应进行 VxLAN 封装并发送到物理端口(驱动程序必须通过查找路由来推断这一点,该路由的 LOCAL_IP
指向 PORT_DEV
,并执行 ARP/邻居表查找以查找外部以太网帧中使用的 MAC 地址),而物理端口上接收到的 UDP 端口为 4789 的 UDP 数据包应解析为 VxLAN,如果其 VSID 与 $VNI
匹配,则应解封装并转发到 VF。
如果这一切看起来很复杂,请记住 TC 卸载的“黄金法则”:硬件应确保与数据包通过慢速路径处理、遍历软件 TC(忽略任何 skip_hw
规则并应用任何 skip_sw
规则)并通过代表网络设备发送或接收的最终结果相同。
配置被代表者的 MAC¶
被代表者的链路状态通过代表者控制。将代表者设置为管理性 UP 或 DOWN 应导致被代表者上的载波 ON 或 OFF。
在代表者上设置 MTU 应导致向被代表者报告相同的 MTU。(在允许配置单独且不同的 MTU 和 MRU 值的硬件上,代表者 MTU 应对应于被代表者的 MRU,反之亦然。)
目前,没有办法使用代表者设置被代表者的永久 MAC 地址;可用于执行此操作的其他方法包括
传统的 SR-IOV (
ip link set DEVICE vf NUM mac LLADDR
)devlink 端口功能(请参阅 devlink-port(8) 和 Documentation/networking/devlink/devlink-port.rst)