多 PF 网络设备

目录

背景

多 PF NIC 技术使多路服务器中的多个 CPU 能够通过各自专用的 PCIe 接口直接连接到网络。通过连接线束将 PCIe 通道在两个卡之间拆分,或者通过为单个卡分叉 PCIe 插槽来实现。这消除了网络流量在插槽之间的内部总线上遍历,除了减少 CPU 利用率和增加网络吞吐量之外,还显著降低了开销和延迟。

概述

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

mlx5 实现

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

netdev 网络通道在所有设备之间分配,正确的配置将在处理特定应用程序/CPU 时利用正确的本地 NUMA 节点。

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

目前,我们将支持限制为仅支持 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” 下使用相同的实例。

可观察性

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

$ ./tools/net/ynl/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/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。仍然维护一个能够指向不同 PF 的接收队列的单个默认 RSS 表。

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

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

XPS 默认配置示例

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

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

  • /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

互斥功能

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