没有真实RDMA网卡也能学!本文手把手教你用两台VMware Ubuntu虚拟机搭建Soft-RoCE模拟RoCEv2环境,完整运行ib_send_bw带宽测试,并基于Wireshark抓包深入拆解RDMA报文交互全过程。从ARP广播、TCP控制面建连,到RC Send大消息拆包(First→Middle→Last)、ACK确认机制,再到AETH流控信用值、PSN序列号、QP状态机------一文讲透RDMA可靠连接(RC)的数据面与控制面交互原理。适合网络工程师、存储开发、AI基础设施从业者入门RDMA技术栈。
关键词:RDMA、RoCEv2、Soft-RoCE、ib_send_bw、perftest、Wireshark抓包、RC可靠连接、QP状态机、BTH、AETH、VMware Ubuntu、RDMA原理、零拷贝网络
1 、RDMA测试环境准备
1)两台 VM:
- Node-A:192.168.95.128,网卡 ens33,主机名 node-a
- Node-B:192.168.95.130,网卡 ens33,主机名 node-b
- 已加载
rdma_rxe,已用rdma link add rxe_0 type rxe netdev ens33绑定业务网卡 - 已装
rdma-core / ibverbs-utils / perftest等 RDMA 软件栈 - 普通 IP 已互 ping 通,UDP 4791 未屏蔽
2)验收三条命令:
# 两端rdma link show# 期望:link rxe_0/1 state ACTIVE physical_state LINK_UP netdev ens33ibv_devinfo -d rxe_0# 期望 port 1 state PORT_ACTIVE,link_layer Ethernet;Soft-RoCE 常 active_mtu=1024
防火墙放 RoCEv2 数据面:
sudo ufw allow 4791/udp
2、ib_send_bw 测试结果
1)服务端 Node-A:
ib_send_bw -d rxe_0 -x 2 --report_gbits

客户端 Node-B:
ib_send_bw -d rxe_0 -x 2 --report_gbits 192.168.95.128

2)测试结果分析:
从测试结果可以看到,服务端:只起监听、post recv(收),不主动发业务数据
ib_send_bw -d rxe_0 -x 2 ...
客户端:连服务端、post send(发),测"客户端→服务端"的 Send 带宽
ib_send_bw -d rxe_0 -x 2 ... 服务端IP
perftest 官方对 send_bw 的描述就是 server 收、client 发,算吞吐;RC 模式下服务端也要 poll CQ 收完成,但业务数据方向默认是客户端→服务端。 默认 RC、默认单向;要双向加 -b(bidirectional)。
3)ib_send_bw是否需要CPU参与?
Send 不像 Write/Read 那样只靠 RKey 写远端内存,它要求:
客户端 SQ 里 post send WQE
服务端 RQ 里提前 post recv WQE
数据到对端后匹配 recv buffer,再出 CQE。两端 CPU 都要参与(发端发、收端收+poll),所以叫双边;但"双边"不等于"双向",默认仍只发一个方向。
4、测试参数解读
关键字段深度解读
1. local address / remote address 中的 GID
- 格式:254:128:00:00:00:00:00:00:XX:XX:XX:XX:XX:XX:XX:XX
- 这是 IPv6 格式的 RoCEv2 GID,前 8 字节固定为 fe80::(链路本地地址前缀),后 8 字节由 MAC 地址或 IPv4 地址转换而来。
- 虽然你用的是 IPv4 地址(192.168.95.128),但 RoCEv2 的 GID 仍以 IPv6 格式呈现,Wireshark 中也会显示为 fe80::...。
- -x 2 指定使用 IPv4 类型的 GID index 2,所以实际通信基于 IPv4,但 GID 本身是 IPv6 格式。
2. LID 0000
- LID(Local Identifier)是 InfiniBand 子网内的 16 位地址,用于 IB 模式寻址。
- Soft-RoCE 运行在以太网上,没有 IB 子网管理器,因此 LID 始终为 0。
- 真机 IB 网络中 LID 非零,RoCE 环境下 LID 也为 0。
3. QPN 0x0011
- QP 编号,范围 0x0001~0xFFFF。
- 两端 QPN 恰好相同(0x0011),这是巧合,不影响通信。
- 每个 QP 唯一标识一条连接。
4. PSN (Packet Sequence Number )
- 初始 PSN 随机生成,之后每发送一个包递增。
- 服务端 PSN=0x1d9c33,客户端 PSN=0xf6a92d,两者独立。
- RC 模式下,接收端通过 PSN 检测丢包和乱序,并触发重传。
5 、抓包深入分析 RDMA 通信原理和交互过程
1 )Ib_send 总共发送1000 次数据,每次数据量64KB ,由于MTU 是1024B ,所以64KB 的数据块会拆分成64 个RDMA 报文进行发送。

2 )以下是报文交互抓包截图(共52849 个RDMA 报文):
1~6:ARP广播报文
7~37:RDMA控制面报文,TCP建链报文
38~52837:RDMA数据发送报文,RDMA报文
52838~52849:RDMA控制面报文,TCP断链报文



1. 前 6 个 ARP 广播报文
- 原因:虚拟机网卡(MAC 地址为 VMware_c0:00:08)在发起通信前,需要知道目标 IP(192.168.95.27,通常是网关或同网段测试对端)的 MAC 地址。
- 作用:通过广播 ARP Request(Who has 192.168.95.27 Tell 192.168.95.1)进行地址解析,这是以太网通信的标准前置动作。
2. 第 7 到 37 个 TCP 报文
- 原因 :perftest 工具(包含 ib_send_bw)在默认情况下不使用 RDMA CM (除非加了 -R 参数),而是自己开一条普通的 TCP Socket 控制连接来进行带外握手。
- 作用 :RDMA 的可靠连接(RC)在真正发数据前,两端必须交换核心连接参数,包括双方的 QP 号(QPN )、起始包序列号(PSN )、全局标识符(GID )、内存密钥(RKey )和缓冲区地址等。TCP 连接(图中使用端口 18515)就是用来完成这个"建连协商"的。
- 细节:图中 7-9 是 TCP 三次握手,10-37 是双方通过 TCP 发送协商参数(包含 PSH 数据标志),最后通过 TCP 四次挥手(或测试结束后的断开)关闭控制连接。
3. 第 38 个报文开始是 RC Send 报文
- 原因 :当 TCP 控制面完成参数交换,并将 QP(队列对)状态机切换到 RTS (Ready To Send ,就绪发送态) 后,真正的 RDMA 数据面传输才开始。
- 特征 :此时数据完全绕过内核 TCP/IP 协议栈,由网卡硬件直接封装成 RoCEv2 报文(UDP 端口 4791)。图中显示为 RC Send First 和 RC Send Middle,这就是客户端向服务端单向发送的 RDMA 业务测试数据。
4. 大消息拆包(First + Middle... + Last )
- 现象:第38个是 RC Send First,第39-100个是 RC Send Middle,第101个是 RC Send Last。
- 原因 :ib_send_bw 默认会发送一条较大的测试消息(例如你之前提到的 64KB)。而以太网有 MTU(最大传输单元)限制(例如 1024 或 4096 字节)。网卡硬件会自动将这条大消息拆分成多个小包进行发送。
- 字段含义 :
- First :拆分的第一个包。它除了携带数据载荷外,还包含关键的 RETH(RDMA 扩展传输头),里面记录了远程内存地址、RKey 等信息(如果是 Write 操作)。
- Middle :拆分的中间数据分片。只携带纯数据载荷,没有 RETH 头。
- Last :拆分的最后一个包,标志着这条大消息传输结束。
- PSN 递增 :在这个过程中,每个包的 BTH 头部里都有一个 PSN (包序列号) 在严格递增(模 2^24),用于保证收发顺序和丢包检测。
5. 可靠确认(RC Acknowledge )
- 现象:第102个是 RC Acknowledge 报文。
- 原因 :RC(可靠连接)模式类似于 TCP,需要接收端给发送端回确认信。接收端网卡 (服务端)在成功按序收到这一整条消息(从 First 到 Last,PSN 连续无缺失)后,会向发送端网卡(客户端)回复一个 ACK 报文。
- 机制:这个 ACK 报文里包含了 AETH(确认扩展传输头),告诉发送端"我已经成功收到了截止到某个 PSN 的所有数据"。如果中间丢了包,接收端会回 NAK,触发发送端的 Go-Back-N 重传机制。
6. 触发确认(AckReq 标志)
- 细节 :你可能在 Wireshark 里展开第101个 RC Send Last 包,会发现 BTH 头部里有一个 AckReq (请求确认) 标志位被置 1。
- 作用:发送端在发送关键包(通常是消息的最后一个包,或者按一定窗口间隔)时,会要求接收端必须立刻回复 ACK。这就是为什么 ACK 紧跟在 Last 包之后立刻出现的原因。
7. 下一条消息的传输(循环)
- 现象:第103个开始又是 RC Send First。
- 原因:ib_send_bw 是一个带宽测试工具,它会连续不断地发送多条测试消息。当第一条消息完成传输并确认后,网卡立刻开始拆包并发送第二条测试消息,周而复始。
8. 第 52038~52045 个报文:TCP 控制连接断开
- 背景:正如之前提到的,ib_send_bw 在测试前会通过 TCP 端口(如 18515)建立一条控制连接,用来交换 QP 号、PSN、RKey 等核心参数。
- 交互过程 :当 RDMA 数据测试完成(第 52037 个报文是最后一条消息的 ACK)后,测试工具(perftest)正常退出,TCP 控制连接也随之关闭:
- 52038-52040:.130(客户端)向 .128(服务端)发送带有 FIN, PSH, ACK 的报文。其中 FIN 表示发送方数据已发送完毕,请求关闭连接;PSH 提示将剩余数据立刻交给应用层;ACK 确认收到之前的数据。
- 52041-52042:.128(服务端)回复 ACK 确认客户端的断开请求,并也发送了自己的 FIN, PSH, ACK 请求关闭反向连接。
- 52043:.130 回复 ACK 确认服务端的 FIN。
- 52044-52045:.130 又发送了 RST, ACK。RST 表示强制重置/断开连接。在 TCP 中,当程序快速退出、端口关闭或连接异常时,常会发送 RST 来立即释放连接资源,跳过标准的 TIME_WAIT 等待状态。
6、RDMA报文解析
1 )RC Send First 报文

重点看一下UDP头和BTH头
a)UDP头:
端口 :源端口 57236(随机高位端口),目的端口 4791。4791 是 IANA 分配给 RoCEv2 的官方固定端口,Wireshark 借此识别出其上层协议为 InfiniBand/RDMA。
b)BTH头:
BTH 是 RDMA 报文必须携带的 12 字节基础头部,核心字段如下:
- Opcode: Reliable Connection (RC) - SEND First (0) :
- RC (可靠连接):表示这条连接是点对点、保序且可靠的,需要接收端回 ACK 确认。
- SEND First :表示这是双边 Send 操作 大消息拆分之后的第一个分片包。它携带了消息的初始数据,后续会跟随 SEND Middle 和 SEND Last 包。
- Destination Queue Pair (QP): 0x000011:目的端队列对号。RDMA 通信通过 QP 进行,数据被投递到对端的这个特定 QP 中。
- Packet Sequence Number (PSN): 858106:包序列号。RC 服务用 PSN 来严格保证包的顺序交付和丢包检测重传。
- Partition Key (PKey): 65535:分区键(默认全权限分区)。
- Acknowledge Request: False:当前首包未强制请求立即确认(通常会在最后的 SEND Last 包中将该位置为 True,要求对端回复 ACK)。
RC Send Middle报文除了PSN编号增长,其他字段与RC Send First相同
RC Send Last的Acknowledge Request 字段为true 。
2 )RC Acknowledge 报文

a)BTH头:
- Opcode: Reliable Connection (RC) - Acknowledge (17):明确标识这是 RC 服务的 ACK 报文。
- Destination Queue Pair: 0x000011:确认报文发往发送端的 QP 11。
- Packet Sequence Number (PSN): 858169 :核心字段。这个 PSN 对应发送端最后发出的那个包的序列号。接收端通过此字段告知发送端:"截止到 858169 号包的数据我已全部按序收到"。
b)确认扩展头(AETH):
AETH 是 ACK 报文特有的扩展头,用于传达确认状态和流控信息:
- Syndrome: 31, Ack :确认状态码。31 表示正常的正确认( ACK )。如果是丢包或错误,这里会显示 NAK 及相关错误码。
- Credit Count: 31 :流控信用值。相当于接收端告诉发送端"我的接收缓冲区还剩 31 个包的容量,你可以继续发"。这是 RC 可靠传输和流控机制的关键部分。
- Message Sequence Number: 1:消息序列号,用于标记确认的是第几条消息。