RDMA数据传输原理深入解读

没有真实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:消息序列号,用于标记确认的是第几条消息。
相关推荐
ShyanZh16 小时前
【Python3基础】19-Socket 与 TCP、UDP 编程
python·网络协议·tcp/ip·udp
流浪00120 小时前
计算机网络篇3:端口号与 socket:数据到达主机后,如何找到目标进程?
计算机网络·udp·tcp·端口·网络字节序
gwf2162 天前
Completion Queue(CQ)与中断处理:轮询、中断聚合与错误码 —— 面向AI集群的驱动级深度剖析
驱动开发·性能调优·pcie·rdma·ai集群·中断聚合·cq
91刘仁德2 天前
Linux网络编程从入门到实战:UDP/TCP协议与socket编程全解析
linux·网络·笔记·tcp/ip·udp
91刘仁德2 天前
传输层协议深度拆解:端口寻址、UDP 报文与 TCP 可靠性机制全解析
linux·网络·c++·网络协议·tcp/ip·udp·c
gwf2163 天前
内核RDMA子系统(ib_core)架构与核心数据结构:从驱动视角解构数据通路
linux内核·rdma·网卡驱动·mlx5·gpudirect·ib_core·内核架构
傲世仙尊3 天前
UDP底层与守护进程化-报头结构体skbuff指针移动与自成会话
驱动开发·网络协议·udp
自己的九又四分之三站台4 天前
TCP 与 UDP:从可靠字节流到无连接数据报,怎么选、怎么测
网络协议·tcp/ip·udp
liangshanbo12154 天前
面试题:游戏、直播为什么常用 UDP?KCP 是什么?为什么比 TCP 更适合低延迟场景?
tcp/ip·游戏·udp