RDMA 杂记
本文旨在厘清一些概念上的细节,尽管更高抽象层次上的工作内容无此要求,但当我们深入到仿真代码中试图 debug 或者研究 rdma 的其他内容时,这是必要的。
什么是“流”
在 RDMA 中,什么是“流”?这个概念为何提出?有没有对应的物理实体,还是仅仅是方便理解的抽象概念?在普通的 TCP/IP 网络中,有没有类似的“流”的概念?
在 RDMA 中,什么是“流” (Flow)
在 RDMA(特别是目前数据中心主流的 RoCEv2)语境下,“流”通常指的是一对 Queue Pair (QP) 之间的通信连接。
更具体地说,一个 RDMA 流由以下特征定义:
- 五元组 (5-tuple):由于 RoCEv2 封装在 UDP/IP 之上,网络设备(交换机)看到的“流”是由
Source IP, Dest IP, Protocol (UDP), Src Port, Dst Port决定的。 - 注意:在 RoCEv2 中,
Dst Port通常固定为 4791 (RoCEv2),而Src Port通常由硬件根据流的特征(如 QP Number)计算哈希值生成,专门用于让交换机做 ECMP(等价多路径路由)负载均衡。
- 逻辑连接:当你建立一个 RC (Reliable Connected) 连接时,本质上就是建立了一条“流”,在端侧(NIC),一个流对应一个 QP(Queue Pair)。
一个流对应一个 QP(Queue Pair),这是针对 RC 来说的。在《以太网RDMA网卡综述_黄曼蒂》中介绍了其他情况:
使用 UD 而非 RC 传输方式可避免建立 1 对 1 的 QP 连接. Kalia 等人提出的 FaSST 使用 UD 提升网卡的可扩展性,并使用双边原语实现快速远程过程调用(remote procedure call,RPC),但并不保证可靠传输. He 等人提出的 RoUD 和 Singhvi 等人提出的 1RMA 则 在使用 UD 的基础上将拥塞控制、重传和流控机制等可靠传输功能上载至软件传输层. UD 相比 RC 更简单且扩展性更好,但 UD 不支持单边原语,无法传输大于 4KB 的数据,且在传输层实现可靠传输重新引入了 CPU 开销.
即,关于“一个 QP 能否对应多条流?”这个问题:
- RC (Reliable Connected) 模式: 不能(同时)
- UD (Unreliable Datagram) 模式: 可以
(应该是这样,你可以仔细阅读上面的论文。)
在 ns3 仿真中,一个流对应一个 message, message 会被 push 到 QP 中发送。这个 QP 可以是用完 message 即抛,也可以复用,具体取决于实现。
补充,RoCE v2中UDP的源端口和目的端口:
简而言之: 一个 RDMA 流就是为了完成特定应用任务,在两个端点之间持续传输的一系列数据包的集合。
更具体一点的视角:
- ns-3 实体:在 ns-3 代码中,一个
App或一个Qp对象往往代表一个流。 - 拥塞控制视角:当你研究 “Go-Back-N” 或 “ACK 丢失” 问题时,你是在流的粒度上讨论的。如果一个流的 ACK 丢了,只会导致这个 QP 重传,不会影响别的 QP。
这个概念为何提出
“流”的提出主要是为了管理复杂性和资源调度。
- 区分服务质量 (QoS):物理链路(光纤/铜缆)是共享的。通过定义“流”,我们可以区分不同的流量。例如,区分高优先级的控制流(CNP 包)和普通的数据流。
- 拥塞控制 (Congestion Control):拥塞通常不是发生在整个端口上,而是发生在特定的路径或特定的业务上。
- 如果没有“流”的概念,一旦发生拥塞,NIC 就只能暂停整个物理端口的发送(PFC 甚至 PAUSE 帧),这会误伤其他正常的通信(Head-of-Line Blocking, 队头阻塞)。
- 有了“流”,DCQCN 等算法才能精确地针对造成拥塞的那条流 (Target Flow) 降低速率,而不影响其他流。
- 负载均衡 (ECMP):数据中心网络通常有主干多路径。交换机需要将同一个“流”的数据包始终发送到同一条物理路径上,以避免乱序(关于这点,之后有新的发展)。“流”是负载均衡的最小粒度。
有没有对应的物理实体
它是一个抽象概念,没有单一的物理实体,但在硬件中有对应的物理状态记录。
- 物理上:它只是一串穿过网卡、网线、交换机芯片的电子或光子信号。并不存在一条物理的“管道”专门给某个流使用。
- 逻辑/硬件状态上:
- 在 RNIC (RDMA网卡) 中,流对应着 QP Context (QPC)。网卡上的 SRAM/DRAM 会存储这个流的状态(当前的 Sequence Number、ACK Number、拥塞窗口大小等)。这就是“流”存在的物理证据——显存中的状态条目。
- 在 交换机 中,流对应着流表(Flow Table)中的一个哈希条目,用于记录路由决策。
普通 TCP/IP 网络中有没有类似的“流”
有,且概念高度相似,但实现机制截然不同。
- TCP/IP 的流:
- 定义:同样基于五元组(Src IP, Dst IP, Src Port, Dst Port, Protocol=TCP)。
- 状态维护:由操作系统的 内核 (Kernel) 维护。对应内核中的
socket结构体和 TCB (Transmission Control Block)。 - 处理者:CPU。CPU 需要通过中断处理每个包,根据五元组找到对应的流上下文。
- RDMA 流 vs. TCP 流(关键区别):
| 特性 | TCP 流 | RDMA 流 (RC 模式) |
|---|---|---|
| 状态维护者 | OS Kernel (CPU) | RNIC (硬件) |
| 上下文切换 | 昂贵 (用户态<->内核态) | 无 (Zero-copy, Kernel Bypass) |
| 拥塞响应 | 丢包或 ECN 触发 TCP 算法 (如 Cubic) | ECN 触发硬件算法 (如 DCQCN) |
| 生命周期 | Socket connect() 到 close() | QP create 到 destroy |
| 乱序容忍度 | 较高 (TCP 栈负责重排) | 极低 (RDMA 硬件重排能力有限,依赖流的路径固定) |
RDMA 网络有乱序接收吗
传统的 RDMA(特别是 InfiniBand 和早期的 RoCE)严格要求顺序接收,不支持乱序;但现代的高级 RDMA 网卡和协议扩展已经开始支持乱序接收(Out-of-Order, OOO),以应对大规模以太网的挑战。
传统机制:严格顺序(Strict Ordering)
在经典的 RDMA 实现中(如标准 InfiniBand 和基础 RoCEv2),接收端必须按顺序接收数据包。
- 工作原理: RDMA 网卡(RNIC)通常使用 Go-Back-N 策略。如果发送方发送了数据包 1, 2, 3, 4,但接收方收到了 1, 3, 4(2 丢失或乱序滞后):
- 接收方会接收 1。
- 接收方会丢弃 3 和 4(即使它们是完好的)。
- 接收方发送 NACK(Negative Acknowledgment)或通过超时机制,要求发送方重传 2 以及 2 之后的所有包(即重传 2, 3, 4)。
- 为什么这样设计? RDMA 的核心是为了降低 CPU 负载,网卡直接将数据写入内存(DMA)。按序到达使得网卡可以非常简单地计算内存地址偏移量,无需复杂的缓冲和重组逻辑,从而保持极低的延迟。
为什么乱序在以太网 (RoCEv2) 中是个大问题
随着 RDMA 从专用的 InfiniBand 网络走向融合以太网(RoCEv2),“严格顺序”成为了性能瓶颈:
- ECMP 的局限性: 现代数据中心网络使用 ECMP(等价多路径路由)来负载均衡。为了避免乱序,网络设备通常基于“流哈希”(五元组)将同一个 RDMA 连接的所有包固定在同一条物理路径上。
- 哈希冲突与拥塞: 如果两个大流量的 RDMA 连接碰巧被哈希到了同一条路径,该路径会拥塞,而其他路径可能空闲。
- 无法使用 Packet Spraying: 理想情况下,我们希望将一个连接的数据包“喷洒”(Spray)到所有可用路径上,但这必然导致接收端乱序。
现代解决方案:乱序接收(OOO RDMA)
为了解决上述问题,一些新一代的高性能网卡引入了对乱序接收的硬件支持。它通常需硬件支持并启用特定配置。
硬件乱序缓冲(Bitmap & Windowing)
现代 RNIC 在硬件层面实现了一个重排序缓冲区(Reorder Buffer)。
- 机制: 当包 1, 3, 4 到达时,网卡不再丢弃 3 和 4,而是将它们暂时缓存在片上内存(On-chip memory)或主机内存的特定区域,并在 Bitmap 中标记。
- 结果: 等包 2 到达后,网卡将 1, 2, 3, 4 一次性提交给应用(实际中可能涉及部分提交以优化性能)。
- 优势: 这允许发送方使用自适应路由(Adaptive Routing)或包级负载均衡(Packet Spraying),极大地提高了带宽利用率。
协议层面的差异 (iWARP)
值得一提的是 iWARP 协议:
- iWARP 基于 TCP/IP。由于 TCP 协议本身就负责处理乱序和重组,iWARP 硬件天生就支持在乱序网络中工作,但其代价通常是比 RoCE 更高的延迟和更复杂的硬件实现。
总结对比
| 特性 | 传统 RDMA (IB / 老式 RoCE) | 现代 RDMA (支持 OOO 的 RoCE) | iWARP |
|---|---|---|---|
| 接收策略 | 严格顺序 | 支持乱序 | 支持乱序 (由 TCP 处理) |
| 丢包处理 | Go-Back-N (丢弃后续包,全部重传) | Selective ACK (仅重传丢失包)并非标准RoCE的核心,而是通过扩展(如SACK-RoCE或IRN)实现。 | TCP SACK |
| 多路径支持 | 仅支持基于流的 ECMP (易拥塞) | 支持 Per-Packet (包级) 负载均衡 | 支持 ECMP |
| 硬件要求 | 较低,逻辑简单 | 高,需要重排序缓冲区 | 高,需要 TCP 卸载引擎 |
| 主要瓶颈 | 头阻阻塞 (Head-of-Line Blocking) | 网卡缓存大小 | 协议栈复杂度和延迟 |
结论
RDMA 网络本身(物理层/链路层)经常发生乱序,但接收端是否能处理取决于网卡代数和配置。
- 如果你使用的是老旧硬件,RDMA 没有乱序接收能力,乱序会导致严重的性能下降(吞吐量暴跌)。
- 如果你使用的是现代高性能网卡(开启了 OOO/Adaptive Routing 功能),RDMA 有乱序接收能力,这是构建大规模高性能网络的关键技术。






