多PF Netdev

目录

背景

多PF NIC 技术使多路服务器中的多个 CPU 能够通过其自己的专用 PCIe 接口直接连接到网络。可以通过分割两个卡之间的 PCIe 通道的连接线束,或者通过分叉单个卡的 PCIe 插槽来实现。这样可以消除网络流量在插槽之间的内部总线上穿梭,从而显著降低开销和延迟,此外还可以减少 CPU 利用率并提高网络吞吐量。

概述

该特性增加了对在 Multi-PF 环境中将同一端口的多个 PF 组合在一个 netdev 实例下的支持。它在 netdev 层实现。较低层实例(如 pci func、sysfs 条目和 devlink)保持分离。通过属于不同 NUMA 插槽的不同设备传递流量可以节省跨 NUMA 流量,并允许从不同 NUMA 运行在同一 netdev 上的应用程序仍然感受到与设备的邻近性,从而提高性能。

mlx5 实现

mlx5 中的 Multi-PF 或 Socket-direct 通过将属于同一 NIC 且启用了 socket-direct 属性的 PF 分组在一起来实现,一旦所有 PF 都被探测到,我们就会创建一个单一的 netdev 来代表所有这些 PF,对称地,每当任何 PF 被移除时,我们都会销毁 netdev。

netdev 网络通道在所有设备之间分配,正确的配置会在处理某个应用/CPU 时利用正确的近 NUMA 节点。

我们选择一个 PF 作为主 PF(领导者),它承担着特殊的角色。其他设备(辅助设备)在芯片级别与网络断开连接(设置为静默模式)。在静默模式下,没有南 <-> 北的流量直接流经辅助 PF。它需要领导者 PF 的帮助(东 <-> 西的流量)才能正常工作。所有 Rx/Tx 流量都通过主 PF 路由到/从辅助设备。

目前,我们将支持限制为仅 PF,最多支持两个 PF(插槽)。

通道分配

我们在不同的 PF 之间分配通道,以在多个 NUMA 节点上实现本地 NUMA 节点性能。

每个组合通道都针对一个特定的 PF 工作,针对它创建所有其数据路径队列。我们以轮询策略将通道分配给 PF。

Example for 2 PFs and 5 channels:
+--------+--------+
| ch idx | PF idx |
+--------+--------+
|    0   |    0   |
|    1   |    1   |
|    2   |    0   |
|    3   |    1   |
|    4   |    0   |
+--------+--------+

我们更喜欢轮询的原因是,它受通道数量变化的影响较小。无论用户配置多少通道,通道索引和 PF 之间的映射都是固定的。由于通道统计信息在通道关闭后仍然存在,因此每次更改映射都会使累积统计信息更少地代表通道的历史记录。

这是通过在每个通道中使用正确的核心设备实例 (mdev) 来实现的,而不是它们都使用 “priv->mdev” 下的同一个实例。

可观察性

PF、irq、napi 和队列之间的关系可以通过 netlink spec 观察到

$ ./tools/net/ynl/pyynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump queue-get --json='{"ifindex": 13}'
[{'id': 0, 'ifindex': 13, 'napi-id': 539, 'type': 'rx'},
 {'id': 1, 'ifindex': 13, 'napi-id': 540, 'type': 'rx'},
 {'id': 2, 'ifindex': 13, 'napi-id': 541, 'type': 'rx'},
 {'id': 3, 'ifindex': 13, 'napi-id': 542, 'type': 'rx'},
 {'id': 4, 'ifindex': 13, 'napi-id': 543, 'type': 'rx'},
 {'id': 0, 'ifindex': 13, 'napi-id': 539, 'type': 'tx'},
 {'id': 1, 'ifindex': 13, 'napi-id': 540, 'type': 'tx'},
 {'id': 2, 'ifindex': 13, 'napi-id': 541, 'type': 'tx'},
 {'id': 3, 'ifindex': 13, 'napi-id': 542, 'type': 'tx'},
 {'id': 4, 'ifindex': 13, 'napi-id': 543, 'type': 'tx'}]

$ ./tools/net/ynl/pyynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump napi-get --json='{"ifindex": 13}'
[{'id': 543, 'ifindex': 13, 'irq': 42},
 {'id': 542, 'ifindex': 13, 'irq': 41},
 {'id': 541, 'ifindex': 13, 'irq': 40},
 {'id': 540, 'ifindex': 13, 'irq': 39},
 {'id': 539, 'ifindex': 13, 'irq': 36}]

在这里您可以清楚地观察到我们的通道分配策略

$ ls /proc/irq/{36,39,40,41,42}/mlx5* -d -1
/proc/irq/36/mlx5_comp0@pci:0000:08:00.0
/proc/irq/39/mlx5_comp0@pci:0000:09:00.0
/proc/irq/40/mlx5_comp1@pci:0000:08:00.0
/proc/irq/41/mlx5_comp1@pci:0000:09:00.0
/proc/irq/42/mlx5_comp2@pci:0000:08:00.0

控制

辅助 PF 设置为“静默”模式,这意味着它们与网络断开连接。

在 Rx 中,控制表仅属于主 PF,并且它的作用是通过交叉 vhca 控制功能将传入流量分配给其他 PF。仍然保持一个默认的 RSS 表,该表能够指向不同 PF 的接收队列。

在 Tx 中,主 PF 创建一个新的 Tx 流表,该表被辅助设备别名,以便它们可以通过它连接到网络。

此外,我们设置了默认的 XPS 配置,该配置基于 CPU 选择与 CPU 位于同一节点上的 PF 的 SQ。

XPS 默认配置示例

NUMA 节点:2 NUMA 节点 0 CPU:0-11 NUMA 节点 1 CPU:12-23

节点 0 上的 PF0,节点 1 上的 PF1。

  • /sys/class/net/eth2/queues/tx-0/xps_cpus:000001

  • /sys/class/net/eth2/queues/tx-1/xps_cpus:001000

  • /sys/class/net/eth2/queues/tx-2/xps_cpus:000002

  • /sys/class/net/eth2/queues/tx-3/xps_cpus:002000

  • /sys/class/net/eth2/queues/tx-4/xps_cpus:000004

  • /sys/class/net/eth2/queues/tx-5/xps_cpus:004000

  • /sys/class/net/eth2/queues/tx-6/xps_cpus:000008

  • /sys/class/net/eth2/queues/tx-7/xps_cpus:008000

  • /sys/class/net/eth2/queues/tx-8/xps_cpus:000010

  • /sys/class/net/eth2/queues/tx-9/xps_cpus:010000

  • /sys/class/net/eth2/queues/tx-10/xps_cpus:000020

  • /sys/class/net/eth2/queues/tx-11/xps_cpus:020000

  • /sys/class/net/eth2/queues/tx-12/xps_cpus:000040

  • /sys/class/net/eth2/queues/tx-13/xps_cpus:040000

  • /sys/class/net/eth2/queues/tx-14/xps_cpus:000080

  • /sys/class/net/eth2/queues/tx-15/xps_cpus:080000

  • /sys/class/net/eth2/queues/tx-16/xps_cpus:000100

  • /sys/class/net/eth2/queues/tx-17/xps_cpus:100000

  • /sys/class/net/eth2/queues/tx-18/xps_cpus:000200

  • /sys/class/net/eth2/queues/tx-19/xps_cpus:200000

  • /sys/class/net/eth2/queues/tx-20/xps_cpus:000400

  • /sys/class/net/eth2/queues/tx-21/xps_cpus:400000

  • /sys/class/net/eth2/queues/tx-22/xps_cpus:000800

  • /sys/class/net/eth2/queues/tx-23/xps_cpus:800000

互斥特性

Multi-PF 的本质是不同的通道与不同的 PF 一起工作,这与在其中一个 PF 中维护状态的有状态特性相冲突。例如,在 TLS 设备卸载功能中,每个连接都会创建特殊的上下文对象并在 PF 中维护。在不同的 RQ/SQ 之间转换会破坏该功能。因此,我们暂时禁用此组合。