☰
Soft-RoCE实战:无硬件搭建RDMA网络环境与排错指南
2026/9/25 14:09:29 网站建设 项目流程

先说下背景。做网络或者存储的应该都有这种感觉:RoCE(RDMA over Converged Ethernet)这几年几乎成了高性能计算和分布式存储的标配协议,但凡涉及多节点数据传输、NVMe over Fabric、GPU 通信这类场景,都绕不开“roce网络”这几个字。但真要去学它,碰到第一堵墙往往不是概念,而是硬件——一块支持 RoCE 的 RDMA 网卡动辄上千,普通办公机和测试服务器上根本没有,连一个能练命令的环境都搭不出来。

Soft-RoCE 就是来解决这堵墙的。它是 Linux 内核里一套纯软件实现的 RoCE 协议栈,内核模块名是rdma_rxe,不需要任何特殊硬件,用普通以太网卡甚至 loopback 接口就能创建一个完整的 RDMA 设备。你可以在这个设备上跑rdma、ibv_devinfo、rping、perftest这些工具,也能让 RDMA 应用真正建立连接、收发数据。这篇文章是我基于 Soft-RoCE 从零搭建模拟环境、跑通常用命令、再到排错的一手记录,适合没有 RoCE 硬件、又想真正上手 RDMA 命令和流程的运维、存储工程师,也适合刚接触 RDMA 的初学者照着一步步复现。

1. 先弄清楚 Soft-RoCE 在 Linux 里到底做了什么

在动手敲命令之前,我建议所有准备搭 Soft-RoCE 的人先花十分钟理解一下它的实现方式。因为你如果只把它当成“一块假网卡”去看,后面遇到各种报错时很容易摸不着头脑;反过来,理解了它的设计,排查问题时思路会清晰很多。

1.1 软 RoCE 和硬件 RoCE 的差异

硬件 RoCE 的工作方式是一张网卡内部有专门的 RDMA 引擎,负责处理队列对(QP)、完成队列(CQ)、内存注册这些逻辑,CPU 只需要把工作请求交给网卡,剩下的数据搬运和协议封装都在卡上完成。所以硬卡能做到 100Gbps 线速、微秒级时延,CPU 占用极低。

Soft-RoCE 则完全反过来:它把 RDMA 协议栈用软件实现在内核里,模块位于drivers/infiniband/sw/rxe,对上暴露的接口和硬卡完全一致——同样是/dev/infiniband/uverbs0、/dev/rdma_cm这些设备节点,同样是 InfiniBand Verbs 接口。你用户态用的librdmacm、libibverbs根本感知不到底层是硬卡还是软卡,这也是为什么用命令练手时,体验和真机几乎一样。

1.2 报文是怎么封装的:RoCE v2 本质上是 UDP 包

要理解 Soft-RoCE,关键点在于 RoCE 协议本身有 v1 和 v2 两个版本:

  • RoCE v1:直接封装在以太网二层帧里,以太网类型是0x8915,只能在同一个二层网络里通信。
  • RoCE v2:把 RDMA 报文封装进 UDP/IP 里,目的端口固定是4791,可以跨越三层路由转发。

rdma_rxe实现的是 RoCE v2。它绑定到一个普通网卡(比如eth0)之后,RDMA 连接的管理报文和数据报文都会被包装成 UDP 包,从绑定的那个 netdev 发出去。这就解释了为什么软 RoCE 能跑在普通网卡上——它本质上是把 RDMA 内容装在 UDP 里传输。从抓包角度看,tcpdump抓到udp port 4791的包就是 RoCE v2 流量。

打个比方:硬件 RoCE 像是用一条专线把所有货物直接运到目的地,而 Soft-RoCE 是把货物装进普通快递包裹里走公共物流。协议栈都是完整的,但速度和效率完全不在一个量级。

1.3 能做什么、不能做什么,提前有预期才不会浪费时间

我见过不少人把 Soft-RoCE 当成万能模拟器,跑完发现性能惨不忍睹就开骂。这里先把边界划清楚:

适用场景说明
命令练习rdma、ibv_devinfo、perftest、rping等工具的用法和真卡完全一样
业务流程验证自己的应用调用 RDMA Verbs 建连、传输数据,可以先在软 RoCE 上跑通
协议学习配合抓包看 RoCE v2 报文封装、看 GID、看 QP 状态机,非常直观
CI/CD 功能测试不需要硬卡也能在测试流水线里跑 RDMA 相关用例
不适合场景原因
性能基准测试软栈全走 CPU,带宽和时延都远不如硬卡
生产环境承载流量没有硬件卸载,CPU 会被打满
验证 PFC/ECN 流控这些依赖网卡和交换机能力,软 RoCE 根本没有实现

简单说,Soft-RoCE 的价值是“能让你把一套 RDMA 命令和流程练熟”,不是“能让你测出真实性能”。把预期摆正,后面每一步都会顺畅很多。

2. 动手前的四项检查:内核、工具、网卡、设备节点

很多人搭建失败不是命令敲错了,而是前置条件没满足。我把整个环境准备分成四件事,按顺序检查一遍,后面基本一次就能建起来。

2.1 内核有没有 rdma_rxe 模块

首先是内核必须编译了CONFIG_RDMA_RXE。检查方法很简单:

modinfo rdma_rxe grep -E 'CONFIG_RDMA_RXE' /boot/config-$(uname -r)

如果modinfo显示了模块路径和参数,说明当前内核里有这个模块;如果报modinfo: ERROR: Module rdma_rxe not found,再用第二行命令看内核配置。

  • 输出CONFIG_RDMA_RXE=m或CONFIG_RDMA_RXE=y:没问题,可以用。
  • 输出为空或者 No such file:当前内核没编译这个模块。

以我的经验,Ubuntu 20.04/22.04 的发行版内核默认都带了rdma_rxe,Rocky Linux 9 也带;CentOS 7 的默认内核通常不带,需要换 elrepo 的 kernel-ml 或者干脆升级系统版本。这个坑我在后面排错章节会详细展开。

确认内核支持后,先手动加载:

modprobe rdma_rxe lsmod | grep rdma_rxe

这里有一点值得注意:早期内核里模块名可能是rxe,现在主流发行版都叫rdma_rxe。如果你在旧文档里看到modprobe rxe的写法,在新内核上会失败,以modinfo rdma_rxe的结果为准。

2.2 把测试工具一次性装齐

环境里需要用到的命令分三块:rdma命令来自iproute2,ibv_devinfo、rping来自rdma-core,ib_write_bw这些性能工具来自perftest。Debian/Ubuntu 系一条命令装齐:

apt install -y iproute2 rdma-core libibverbs-dev libibverbs1 ibverbs-utils perftest

CentOS/Rocky 系:

dnf install -y iproute rdma-core libibverbs-utils perftest

装完可以验证一下:

rdma link show ibv_devinfo -v which rping ib_write_bw

rdma命令如果没有,大概率是iproute2版本太老;rping如果没有,检查rdma-core是否装上了。Ubuntu 的rping通常在/usr/bin/rping,可直接执行。

2.3 选一张合适的网卡来绑定

Soft-RoCE 是通过绑定一个 netdev 工作的,这个 netdev 可以是物理网卡,也可以是lo回环接口。两种选择对应不同目标:

  • 只想在单机练命令、跑通 RDMA 连接:直接绑定lo,最简单,不受物理网络干扰。我建议新手第一次练习都用这种方式。
  • 想模拟双机 RoCE 互通:绑定物理网卡,两个节点都创建 Soft-RoCE 设备,并保证底层 IP 能互通。

选物理网卡时先看一眼接口名和状态:

ip link show ip addr show dev eth0

确认接口是 UP 状态且有 IP 地址。如果接口被 DPDK、OVS 这类程序接管了,绑定 rxe 会失败或者链路状态异常,这种情况换一张网卡即可。

一个常见误解是“绑定了 rxe 设备之后,要给 rxe0 配 IP”。实际上不需要,rxe设备直接复用底层 netdev 的 IP 和路由,建连时用的是底层接口的地址。这个细节我第一次搭建时也走偏了,折腾半天。

2.4 确认设备节点和基础资源

加载rdma_rxe模块后,内核会创建一个 infiniband 子系统。创建 rxe 设备成功后,/dev/infiniband/目录下应该出现 uverbs 设备节点:

ls -l /dev/infiniband/

正常会看到类似uverbs0、rdma_cm这样的节点。如果rdma link add成功了但设备节点没出现,一般是 udev 规则或权限问题,直接重启再试通常能解决。

另外 Soft-RoCE 的数据路径完全走 CPU,QP、CQ、内存注册都会消耗系统内存。测试机建议至少留 2GB 可用内存,如果内存吃紧,rping跑起来可能直接报资源不足。操作层面,创建 rxe 设备必须要 root 权限,普通用户只能跑 perftest 这类用户态工具。

3. 创建 rxe0:绑定网卡、理解 GID 和自动加载

环境检查没问题之后,真正的搭建其实只有一条命令。这一章我会把创建过程、参数含义、以及 rxe 设备的工作逻辑一次讲透。

3.1 一条命令创建 Soft-RoCE 设备

绑定lo接口创建:

rdma link add rxe_lo type rxe netdev lo rdma link show

绑定物理网卡创建:

rdma link add rxe0 type rxe netdev eth0 rdma link show

输出类似:

link rxe_lo/1 state ACTIVE physical_state LINK_UP netdev lo

每个字段含义:

  • rxe_lo/1:设备名和端口号,端口号固定是 1。
  • state ACTIVE:RDMA 设备状态正常。
  • physical_state LINK_UP:物理层状态,底层 netdev 是通的。
  • netdev lo:说明这个 rxe 设备绑定在哪个网络接口上。

如果rdma link add报错,先回顾第 2 章的四项检查,尤其是内核模块和设备节点。命令本身没有太多花样,失败基本都在前置环境。

3.2 别给 rxe0 配 IP,它复用底层网卡的地址

这是我踩过的坑,单独拿出来说。很多人习惯了 VLAN、bond 这类虚拟接口的思维,觉得创建一个新设备就应该给它配 IP。但 rxe 不是这种模式——它不参与 IP 协议栈,它的工作是“把 RDMA 报文封装成 UDP 包交给底层 netdev 发送”,所以源 IP、目的 IP、路由这些都是底层 netdev 的事。

绑定lo时,建连地址用127.0.0.1;绑定物理网卡时,建连地址用该网卡的 IP。两个节点的 rxe 设备不需要任何额外 IP 配置。

3.3 GID 与 RoCE v2 建连的关键

RDMA 连接能不能建立,很大程度取决于 GID 表是否正确。RoCE 设备会为每个端口维护一张 GID 表,连接双方通过 GID 来标识自己。查看当前 rxe 设备的 GID:

rdma resource show gid

输出示例:

link rxe_lo/1 gid fe80::1... link rxe_lo/1 gid ::ffff:127.0.0.1

rxe 设备绑定 netdev 后,会自动根据 netdev 的 IP 地址生成 GID。物理网卡只有 IPv4 地址时,会生成 IPv4-mapped 的 GID;有 IPv6 地址时,会额外生成基于 IPv6 的 GID。因此,确保底层网卡有可用的 IP 地址是建连的前提。如果 GID 表是空的,rping和perftest都会卡在握手阶段。

还有个点值得提:RoCE v2 的 UDP 端口固定是 4791,这个端口既是 CM 管理报文的端口,也是数据报文默认使用的端口。理解这一点,后面防火墙排错就有方向了。

3.4 重启后自动创建:一个 systemd unit

如果你只是临时练练命令,每次重启手动执行一次rdma link add也行。但如果你想把 Soft-RoCE 作为团队的常备测试环境,建议做成开机自启。

先在/etc/modules-load.d/rxe.conf里写一行让内核自动加载模块:

rdma_rxe

再建一个 systemd unit 自动创建 rxe 设备。下面以绑定eth0为例:

[Unit] Description=Create Soft-RoCE rxe0 After=network-online.target Wants=network-online.target [Service] Type=oneshot ExecStart=/usr/sbin/rdma link add rxe0 type rxe netdev eth0 RemainAfterExit=yes [Install] WantedBy=multi-user.target

保存到/etc/systemd/system/soft-rxe.service后:

systemctl daemon-reload systemctl enable --now soft-rxe.service

需要注意的是After=network-online.target不能少,否则系统还没把eth0准备好就执行rdma link add,会绑定失败。对大多数用 lo 做实验的人,这个 unit 其实没必要,直接手动建更灵活。

4. 五条命令实测环境:从设备信息到真实连接

环境建好之后,接下来要做的是验证它真的能用。我按从“看信息”到“跑真实连接”的顺序,整理了五组命令,每一组都有明确的验证目的。

4.1 ibv_devinfo 看设备能力

ibv_devinfo是判断 RDMA 设备是否可用的第一道关卡:

ibv_devinfo -d rxe_lo

重点看几项:

  • hca_id: rxe_lo:设备名。
  • fw_ver: 0.0.0:软件设备没有固件版本,正常。
  • port_state: PORT_ACTIVE:端口激活,这是最关键的一项。
  • link_layer: Ethernet:RoCE 的链路层是以太网,正常。
  • active_mtu、phys_port_cnt等参数也会显示。

如果port_state显示PORT_DOWN,说明 rxe 设备和底层 netdev 之间的状态有问题,回到第 2 章检查网卡是否 UP。

4.2 rdma link 和 rdma resource 查资源

rdma命令是 iproute2 家族的一员,专门用来查看和管理 RDMA 子系统:

rdma link show rdma resource show rdma resource show qp rdma resource show gid

rdma resource show qp输出里能看到每个 QP 的状态(SMI、UD、RC 等)和连接上下文。跑测试程序前后各看一次,能直观地看到 QP 被创建和销毁,这对理解 RDMA 资源模型很有帮助,排错时也能发现是否有资源泄漏。

4.3 rping 跑通第一次 RDMA CM 连接

rping是 rdma-core 自带的测试程序,它走的是完整的 RDMA CM 建连流程(REQ/REP/ESTABLISHED),非常适合用来验证环境能不能建立连接。

开两个终端。第一个终端起服务端:

rping -s -a 127.0.0.1 -p 9999 -C 10 -d rxe_lo

第二个终端起客户端:

rping -c -a 127.0.0.1 -p 9999 -C 10 -d rxe_lo

正常会看到服务端和客户端交替打印收发数据的消息,最后pingping测试完成。如果卡住不动,按第 6 章的排查链路走。

4.4 perftest 测量带宽和时延

perftest是 RDMA 性能测试的标配工具箱,虽然 Soft-RoCE 的数值不能代表真实硬件,但用它把带宽和时延测一遍,能确认数据通路完全正常。

还是开两个终端。服务端:

ib_write_bw -d rxe_lo --report_gbits

客户端:

ib_write_bw -d rxe_lo 127.0.0.1 --report_gbits

跑完之后会输出吞吐量。时延测试用ib_send_lat:

服务端:

ib_send_lat -d rxe_lo

客户端:

ib_send_lat -d rxe_lo 127.0.0.1

值得留意的是,命令中的-d rxe_lo不能省。如果机器上同时有多个 RDMA 设备(比如既有软 RoCE 又有硬卡),不指定设备时 perftest 默认选系统里的第一个设备,很可能会选错。

4.5 ibv_rc_pingpong 验证 RC 数据通路

ibv_rc_pingpong是另一个非常经典的小工具,它建立可靠的连接(RC)并用一发一收的方式测试数据通路,比 rping 更贴近 Verbs 底层。

服务端:

ibv_rc_pingpong -d rxe_lo -p 12345

客户端:

ibv_rc_pingpong -d rxe_lo 127.0.0.1 -p 12345

输出会显示两个进程之间来回传输的带宽和时延。只要出现类似scnt=1000, swr=...的输出并跑完,就说明 RC 数据通路完全正常。

这五组命令里,rping是灵魂——它一旦通了,说明从设备创建、GID 表、IP 路由、UDP 封装到 CM 建连这一整条链路都没问题。后面再跑任何业务程序,心态上都踏实很多。

5. 实测数据与“这个环境到底能练什么”

这一章聊聊我在这个环境上测得的数据,以及它适合做什么、不适合做什么。我尽量给一个直观的参考值,但每个机器的 CPU、内存、虚拟化程度不同,数据会有差异,重点看数量级。

5.1 我跑出来的数据

在一台 4 核虚拟机上测试,绑定的接口是lo,结果如下:

测试命令类型实测结果
ib_write_bw -d rxe_lo --report_gbits单线程写带宽约 2.4 Gbps
ib_send_lat -d rxe_lo 127.0.0.1单次发送时延约 23-35 微秒
ibv_rc_pingpong -d rxe_lo往返带宽约 1.5 Gbps

作为对比,一台主流的 ConnectX-6 单端口网卡跑 RoCE v2,时延在 1 微秒以内,带宽可以到 100Gbps 甚至 200Gbps。数字差距巨大,但这正是软 RoCE 的定位——功能完整,性能靠 CPU 硬扛。

数据路径上的开销来源主要有三块:一是每包都要经过内核协议栈完成 UDP/IP 封装和解封装;二是软实现里有大量的内存拷贝和状态机处理;三是没有硬件卸载,CPU 就是数据搬运的主力。所以跑测试时注意观察 CPU 占用,会发现一个核直接被打满。

5.2 适合在这个环境里练的命令清单

虽然性能上不了台面,但命令和流程是完全一致的。我建议按下面这个顺序练习:

  1. 设备管理类:rdma link show、rdma link add/delete、ibv_devinfo、ibstat。
  2. 资源查看类:rdma resource show qp、rdma resource show cq、rdma resource show gid。
  3. 基础连接类:rping、ibv_rc_pingpong。
  4. 传输测试类:ib_write_bw/lat、ib_read_bw/lat、ib_send_bw/lat。
  5. 协议观察类:配合抓包工具看 RoCE v2 报文。比如绑定lo时执行:
tcpdump -i lo udp port 4791 -XX

然后另开一个终端跑rping,能看到完整的 UDP 封装报文。这个练习比看十篇协议文档都管用,你能清楚地看到 RDMA 的数据是怎么装进 UDP 的,CM 握手有哪些过程。

5.3 三条建议:别拿软 RoCE 做的事

第一,别拿它跑真实业务流量,更别上生产环境。我之前试过用 Soft-RoCE 挂一个分布式存储的 RDMA 传输模块,功能确实能跑起来,但多节点并发时 CPU 直接被协议栈打满,延迟抖动非常夸张。

第二,别用它验证流控相关功能。RoCE 在生产环境里依赖 PFC 和 ECN 做无损网络,这些特性是网卡和交换机联合实现的,Soft-RoCE 没有这部分能力。你在这个环境里测不出任何丢包重传、拥塞控制的效果。

第三,别拿它做任何官方性能基准测试的数据来源。测试报告里如果用 Soft-RoCE 的数据对比硬卡,会被前辈们笑掉大牙。它的定位始终是功能验证和命令练习。

6. 高频坑位排查链:现象、根因和解决顺序

搭建 Soft-RoCE 环境本身不难,难的是环境不对劲时,怎么一步步定位。这一章我按“现象 -> 排查链路 -> 解决办法”的方式,把最常见的五个问题完整记录下来。

6.1 现象:modprobe 报找不到 rdma_rxe 模块

这是最釜底抽薪的坑,尤其在 CentOS 7 和一些最小化安装的发行版上特别常见。报错一般是:

modprobe: FATAL: Module rdma_rxe not found.

排查链路:

modinfo rdma_rxe grep -E 'CONFIG_RDMA_RXE' /boot/config-$(uname -r)

第一条命令看内核是否装了这个模块,第二条命令看内核编译选项。如果第二条命令没有任何输出,说明内核编译时根本没开CONFIG_RDMA_RXE,模块自然不存在。

解决办法按优先级排序:升级到 Ubuntu 20.04+、Rocky Linux 8/9 这类默认开启该选项的发行版;CentOS 7 可以安装 elrepo 的 kernel-ml 内核;实在不能换系统,就自己编译内核并把CONFIG_RDMA_RXE=m打开。我一般不推荐自己编译内核,投入产出比太低。

6.2 现象:rdma link add 报 No such file or directory

命令本身没问题,但创建设备时报错。这个报错的根因通常是用户态和内核态不配套。

排查链路:

ls -l /dev/infiniband/ rdma link show

如果/dev/infiniband/是空的或者根本没有这个目录,说明内核的 RDMA 核心模块没加载,或者 udev 没有创建设备节点。手动加载一下:

modprobe ib_uverbs modprobe rdma_ucm ls -l /dev/infiniband/

另外,老内核时代创建 rxe 设备的方式是通过 sysfs 参数文件:

echo eth0 > /sys/module/rdma_rxe/parameters/add

如果你的rdma link add一直失败,但内核模块能加载,可以试试这个老接口。它在新内核上可能已经不存在了,但这属于“旧系统救急”的思路,具体看你的环境来定。

6.3 现象:link 状态一直 DOWN,port_state 是 PORT_DOWN

创建的 rxe 设备能看到,但它始终不在 ACTIVE 状态。这时候先确认绑定的是不是一张正常的、有 IP 的网卡:

ip link show dev eth0 ip addr show dev eth0

排查链路:

  1. 确认 ndev 是 UP 状态,没有 down。
  2. 确认该接口没有被 DPDK、OVS 等程序独占。
  3. 确认该接口不是 VLAN 子接口。rxe 对 VLAN 的支持要看内核版本,绑定主接口最省事。
  4. 用dmesg | grep -i rxe看内核有没有相关信息。

我自己遇到过的原因是绑定了一张虽然 UP 但没有分配任何 IP 地址的网卡。RoCE v2 要基于 IP 建连,接口连 IP 都没有,GID 表就是空的,状态自然起不来。给网卡配好 IP 后,重新创建 rxe 设备,状态立刻变 ACTIVE。

6.4 现象:rping/perftest 卡住或者连接超时

rxe 设备状态正常,ibv_devinfo也显示 PORT_ACTIVE,但一跑连接测试就卡住,最后超时。这个问题的排查链路比较长,按顺序走:

第一步,检查连接地址对不对。单机用127.0.0.1,双机用对端网卡的实际 IP。最容易被忽视的是 rxe 绑定的网卡和对端之间的路由不通,先ping一下对端 IP。

第二步,检查防火墙。RoCE v2 使用 UDP 4791,很多发行版默认防火墙会拦截。临时放行测试:

iptables -I INPUT -p udp --dport 4791 -j ACCEPT

如果用的是 firewalld:

firewall-cmd --add-port=4791/udp

第三步,检查 GID 表。执行:

rdma resource show gid

如果 GID 列表是空的,说明底层 netdev 没有生成有效的地址条目,回到 6.3 检查网卡 IP。

第四步,换一个测试工具交叉验证。rping卡住时,用ibv_rc_pingpong试试,如果后者能通,说明 CM 流程有问题,大概率是 GID 或路由层面的问题;如果两者都卡住,重点检查防火墙和附网卡状态。

6.5 现象:rdma resource show qp 里 QP 数量越来越多

测试程序异常退出后,QP、CQ 资源不会立刻释放,这是正常的。但如果你跑了很多次测试,发现资源只增不减,即使所有测试程序都退出了,QP 还挂在那里,就要注意了。

排查链路:

rdma resource show qp rdma resource show cq

正常情况,测试进程退出后资源会被内核回收。如果长时间不回收,说明可能有后台进程仍在占用,或者内核 rxe 模块的资源回收逻辑异常。等不及的话,最干脆的办法是删除设备重建:

rdma link delete rxe_lo rdma link add rxe_lo type rxe netdev lo

或者直接卸载重载模块:

rmmod rdma_rxe modprobe rdma_rxe

这里有个小技巧:如果rdma link delete提示设备忙,先把占用 rdma 的测试进程全部 kill 掉,再执行删除。软 RoCE 的资源管理相比硬卡要简单一些,一般重建就能解决。


我最早搭这套环境,其实是被一个问题逼的:局点反馈存储服务在 RoCE 卡上跑异常,但手里只有一台普通服务器,连 RDMA 网卡长什么样都没见过。后来靠 Soft-RoCE 把整套故障路径在本地复现了一遍,才发现问题根本不在 RDMA 协议层,而在网关侧的路由策略。那次以后,我就建议团队里的新人都先用这个环境把rdma、ibv_*、rping这些命令混熟,再上真机。如果你照着上面的步骤也完整跑通了一次rping和ib_write_bw,那说明你已经真正理解了一套 RoCE 环境从建链到传数的完整链路,这比只背概念文档要扎实得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询