从 57 Gbit/s 到 PCIe Gen3 x8:ConnectX-6 SR-IOV RDMA 性能排查
最近在一台 GPU 服务器上测试 ConnectX-6 SR-IOV VF 直通虚拟机。物理 IB 端口协商为 200G,虚拟机里的 RDMA 端口也处于 ACTIVE,但 ib_write_bw 单向吞吐始终只有 57~60 Gbit/s。
排查从虚拟化侧一路检查到测试工具和固件。最终的 PF 对 PF 测试仍然只有约 60G,而其中一张 ConnectX-6 的 PCIe 链路是 Gen3 x8。这个链路的理论单向有效带宽约为 63 Gbit/s,足以解释实测结果。
本文记录配置路径、测试对照和定位过程。重点是如何把问题从虚拟机、VF 和测试工具逐层缩小到物理 PCIe 链路。
先理解 IB 与 RDMA
IB 是什么
IB 是 InfiniBand 的简称,是一种面向高带宽、低延迟通信的网络互连技术。网卡在 IB 语境中通常称为 HCA(Host Channel Adapter),HCA 通过 PCIe 连接主机内存,再通过 IB 链路连接交换机和另一端 HCA。
因此,网卡标注的 200G 首先描述的是 HCA 与 IB Fabric 之间的端口链路能力。它不直接等于主机内存到另一台主机内存的端到端吞吐,这个吞吐还会受到主机侧 PCIe 链路和 NUMA 布局影响,驱动与测试参数也会改变结果。
RDMA 是什么
RDMA(Remote Direct Memory Access)描述的是一种数据传输方式:通信双方建立资源并注册内存后,网卡可以按照队列中的请求直接读写远端内存,数据面通常不需要远端 CPU 参与,也避免了传统 TCP/IP 路径中的多次内存拷贝。
RDMA 的控制面仍然需要驱动和内核参与,例如创建 QP(Queue Pair)、注册内存和建立连接。应用数据面常通过 verbs 接口提交 Work Request,再从 CQ(Completion Queue)获取完成事件。ib_write_bw 使用的就是这条 verbs 路径。
IB 与 RDMA 的关系
两者有直接关系,但不是同一个概念。IB(InfiniBand)是一整套网络互连与传输架构,定义了链路、交换、路由和传输服务;RDMA 是其中的一种通信语义,允许应用通过网卡执行远端内存读写。也就是说,IB 负责提供通信承载和传输机制,RDMA 负责说明数据如何以「远端内存访问」的方式被提交和完成。
在 InfiniBand 上,一次 RDMA Write 的路径可以简化为:
| |
本文测试的 ib_write_bw 就处在这条路径上:它通过 verbs 创建 QP,并使用 InfiniBand 的 RC(Reliable Connection)传输服务执行 RDMA Write。Transport type: IB 说明承载是 InfiniBand,RDMA Write 说明传输操作是远端内存写入;两者是同一次测试中的不同层次。
RDMA 并不只依赖 InfiniBand,也可以使用 RoCE 等其他承载。反过来,IPoIB 是把 IB 作为网络接口来承载普通 IP 包,不等于 RDMA verbs;它们可以共享同一个 HCA 和 IB Fabric,但使用的上层数据路径不同。
IPoIB 与 RDMA 的关系
IPoIB(IP over InfiniBand)把 IB 设备表现为 Linux 网络接口,用来承载普通 IP 数据包。它和 verbs RDMA 是两条不同的数据路径:
| |
所以,/sys/class/net/ib*/mode 显示 datagram,只能说明 IPoIB netdev 的工作模式,不能据此判断 RDMA 是否启用。后文会用 ib_write_bw 测试 IB 承载的 RDMA verbs 路径,再用 iperf3 测试 IPoIB 上的 TCP/IP 路径。
环境与拓扑
宿主机环境:
| |
服务器为双路 NUMA。两台虚拟机分别绑定到不同 NUMA Node,避免 CPU 和内存跨 NUMA 访问。
两张 IB 网卡的状态如下:
| |
测试流量经过一台 IB 交换机:
| |
下面的配置和测试会解绑驱动、删除并重新创建 VF,还会把 PF 网卡移动到 network namespace。只能在测试主机上执行;如果主机上有其他业务,先停止相关虚拟机并记录原始配置。
配置 SR-IOV VF 直通
创建 VF
先确认 PF 与 Linux 设备名:
| |
假设两张 PF 对应:
| |
每张 PF 创建一个 VF:
| |
确认 VF 已出现:
| |
例如:
| |
配置 VF GUID
InfiniBand VF 需要有效的 Node GUID、Port GUID,并且 policy 允许它跟随 PF。GUID 仍然为全 0,或 policy 不正确时,VF 可能无法进入 ACTIVE。
| |
检查配置:
| |
实际环境中必须为每个 VF 分配唯一 GUID,不能直接复制示例值。
绑定 vfio-pci
先把 VF 从 mlx5_core 解绑:
| |
让 vfio-pci 接管对应设备:
| |
检查绑定结果:
| |
应该看到:
| |
写入 new_id 后,内核可能已经自动完成绑定。如果再次手动执行:
| |
并得到:
| |
先用 lspci -nnk 检查当前驱动。只要已经显示 vfio-pci,这个提示不一定代表绑定失败。
配置 libvirt 直通
在虚拟机 XML 中加入 PCI Host Device:
| |
第二台虚拟机使用另一个 VF 的 PCI 地址。GPU 和 PCIe 设备直通环境建议使用 Q35 芯片组与 OVMF/UEFI。
在虚拟机内配置 RDMA
虚拟机使用 Ubuntu 24.04,安装 RDMA 和测试工具:
| |
加载 mlx5_ib:
| |
检查设备:
| |
正常情况下可以看到类似信息:
| |
配置 IPoIB 地址
使用独立测试网段。VM1 的 netplan 配置:
| |
VM2 的配置:
| |
应用配置并先验证连通性:
| |
datagram 不代表没有 RDMA
查看 IPoIB netdev 模式:
| |
输出可能是:
| |
datagram 描述的是 IPoIB netdev 的工作模式,不等于 RDMA 没有启用。ib_write_bw 使用 verbs/RC QP,不经过普通 TCP/IP 数据面。
例如测试输出中的以下字段已经说明测试路径是 RDMA:
| |
ib_write_bw -R 中的 -R 也不是「打开 RDMA」。ib_write_bw 本身就是 RDMA 测试,-R 只表示使用 rdma_cm 建立连接和 QP。
VM 内的多组测试都停在约 60G
基准测试
VM1 作为 server:
| |
VM2 作为 client:
| |
结果稳定在:
| |
改用 rdma_cm
server:
| |
client:
| |
结果约为 59.1 Gbit/s,与基准测试基本一致,因此问题不像是 rdma_cm 建连路径造成的。
测试双向吞吐
| |
结果为:
| |
-b 报告的是双向 aggregate,不能直接与单向 200G 比较。按两个方向近似拆分:
| |
用 iperf3 对照
再用普通 TCP/IPoIB 测试,确认是否只有 perftest 或 verbs 路径受影响。
server:
| |
client:
| |
结果约为 58.7 Gbit/s,同时 TCP 已经出现不少 retransmission。
不同测试方法的结果如下:
| 测试 | 数据路径 | 结果 |
|---|---|---|
ib_write_bw | RDMA verbs | ~57.1 Gbit/s |
ib_write_bw -R | RDMA + rdma_cm | ~59.1 Gbit/s |
ib_write_bw -b | 双向 RDMA aggregate | ~111.7 Gbit/s |
iperf3 -P 8 | TCP/IPoIB | ~58.7 Gbit/s |
RDMA、rdma_cm 和 TCP/IPoIB 的单向测试都撞在接近 60G 的位置,继续调整 ib_write_bw 参数的收益已经很低。下一步应该隔离 KVM、VFIO 和虚拟机驱动。
用 PF 对 PF 测试隔离虚拟化层
关键问题是:这约 60G 的上限来自虚拟化,还是宿主机物理链路本身?
先避免本机路由短路
如果在同一台主机给两个接口配置地址,再直接访问另一个本机 IP:
| |
可能得到:
| |
此时 Linux 会执行 local delivery,流量不会真正经过 HCA 和 IB 交换机,测试结果没有意义。
因此,需要把两个 IB netdev 放到不同的 network namespace,强制流量走真实的 IB 路径。
删除 VF 并移动 PF
先关闭使用 VF 的虚拟机,再删除 VF:
| |
确认 RDMA namespace 配置:
| |
本次输出为:
| |
创建两个 namespace 并移动 PF:
| |
分别配置接口地址:
| |
确认路由没有落到 lo:
| |
应该类似:
| |
先测试连通性:
| |
PF 对 PF 跑 RDMA
server:
| |
client:
| |
结果为:
| |
这次测试绕过了:
- KVM/QEMU
- VFIO
- SR-IOV VF
- Guest Kernel
- Guest
mlx5驱动
PF 对 PF 仍然只有约 60G,所以问题已经可以从虚拟化层移开。
检查 PCIe 链路
查看两张 ConnectX-6 的链路能力和当前状态:
| |
第一张网卡:
| |
即当前为 PCIe Gen4 x16。
第二张网卡:
| |
即当前为 PCIe Gen3 x8。ConnectX-6 本身支持更高 PCIe 规格,并不代表它在当前服务器上一定能协商到对应速率和宽度;最终要看 LnkSta 的实际状态。
Gen3 x8 的带宽上限
PCIe 3.0 每 lane 为 8 GT/s,使用 128b/130b 编码。x8 链路的理论有效带宽约为:
| |
实测结果为:
| |
这已经非常接近 Gen3 x8 的有效上限。
因此,ibstat 或其他工具显示 IB 链路为 200G,并不意味着主机内存到另一端主机内存的端到端吞吐也一定是 200G。完整数据路径是:
| |
HCA 到 IB Fabric 的链路速率和 HCA 到主机内存的 PCIe 带宽是两段不同的约束,端到端吞吐会受较慢的一段限制。
常见 PCIe 配置对 200G IB 的影响
| PCIe | 理论单向带宽 | 对 200G IB 的影响 |
|---|---|---|
| Gen3 x8 | ~63 Gbit/s | 明显不够 |
| Gen3 x16 | ~126 Gbit/s | 仍不足以跑满 200G |
| Gen4 x8 | ~126 Gbit/s | 仍不足以跑满 200G |
| Gen4 x16 | ~252 Gbit/s | 可以承载 200G |
如果目标是让 200G ConnectX-6 接近线速,PCIe Gen4 x16 是比较合理的配置。实际 RDMA 跑到 180~195 Gbit/s,已经属于接近 200G line rate 的状态。
固件与其他变量
测试时网卡固件为:
| |
当时还有 20.43.x 版本可用。固件升级可能带来 bug fix、兼容性或性能变化,但在本次问题中,PCIe Gen3 x8 已经足以解释 57~60G,没有必要先把固件升级当成唯一变量。
在这个场景里,PCIe link speed 和 width 应该是首个检查项,NUMA locality 随后确认。虚拟化和测试工具相关配置留到这两项之后再看,firmware 则适合作为独立的 A/B 变量。
测试完成后恢复 VF
清理 network namespace
先把接口地址和状态清掉,再将 PF 移回 root namespace:
| |
重新创建并绑定 VF
| |
重新配置 VF GUID 和 policy:
| |
重新解绑并让 vfio-pci 接管:
| |
最后确认:
| |
确保输出包含:
| |
结论
这次排查中,以下现象最容易造成误判:
ibstat显示Rate: 200,只说明 IB Fabric 链路能力,不代表应用端到端吞吐一定是200G。/sys/class/net/ib*/mode显示datagram,描述的是 IPoIB netdev 模式,不代表 RDMA 没有启用。ib_write_bw -R不是「开启 RDMA」;ib_write_bw本身就是 RDMA verbs 测试,-R只改变连接建立方式。- 双向
-b的 aggregate 不能与单向带宽直接比较。 - VM 中只有
57G时,不能直接归因于 SR-IOV 或 VFIO;PF 对 PF 测试可以先把虚拟化层排除。 - 同一台宿主机用两个本地 IP 互测,可能被
local route短路;使用 network namespace 才能强制经过 HCA 和 IB 交换机。 - 对 200G HCA,PCIe link speed 和 width 必须一起看;
Gen3 x8本身只能提供约63 Gbit/s的理论单向有效带宽。
决定性的对照数据是:
| |
三组数字基本对上后,问题就从「RDMA 为什么这么慢」收敛成了一个明确的 PCIe 带宽问题。