多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 之間轉換會破壞該功能。因此,我們暫時停用此組合。