1、RoCEv2 实现原理
RoCE(RDMA over Converged Ethernet),即基于以太网的RDMA技术,允许在不依赖infiniband专用硬件的情况下使用RDMA。RoCE v2版本基于以太网的UDP协议,UDP目标端口4791保留给RoCE v2流量,将IB的传输层作为UDP的payload(即TCP/IP协议栈的应用层)数据。协议栈对照图如下:

RoCE v2的报文格式如下:

2、先看一下各个头结构
2.1 Eth 帧结构

对于RoCE v2 with IPv4: type设置为 0x0800.
- DMAC(Destination MAC)是目的MAC地址。DMAC字段长度为6个字节,标识帧的接收者。
- SMAC(Source MAC)是源MAC地址。SMAC字段长度为6个字节,标识帧的发送者。
- Type(类型字段)用于标识数据字段中包含的高层协议,该字段长度为2个字节。类型字段值为 0x0800的帧代表IP协议帧;类型字段值为0806的帧代表ARP协议帧。
- Data(数据字段)是网络层数据,最小长度必须为46字节以保证帧长至少为64字节,数据字段的最大长度为1500字节。
- FCS(循环冗余校验字段)提供了一种错误检测机制。该字段长度为4个字节。
2.2 IP 头部结构定义
IP协议是TCP/IP协议族中的核心协议。TCP、UDP、ICMP和IGMP数据都通过IP数据传输。IP协议提供了一种尽力而为、无连接的数据包交付服务。"无连接"意味着IP协议是不维护网络单元中数据报相关的任何链接状态信息,每个数据报独立于其他数据报处理,这就意味着IP数据报可不按顺序交付。
主要说一下IPv4:

固定头部分为20B,可选长度最长为40B,所以头部长度在20~60B
具体的IP 头部介绍,参考之前的写的文章:
linux之网络子系统(10)-MAC帧、数据报、段 的头部信息-CSDN博客
这里只介绍几个部分:
1、区分服务(DS和ECN) :8bits。DS为区分服务字段(6bits),ECN为显示拥塞通知(2bits)。DS代表了不同的QoS(服务质量)策略,ECN代表类在拥塞时做出的不同策略。例如:0110 10(Differentiated Services Codepoint:Assured Forwarding 31)和00
ECN对报文在路由器中转发策略的影响:
1、当拥塞发生时,针对ECN=00的报文,走原有普通非ECN流程,即,进行RED丢包。
2、当拥塞发生时,针对ECN=01或ECN=10的报文,都需要修改为ECN=11,并继续转发流程。
3、当拥塞发生时,针对ECN=11的报文,需要继续转发。
| CT | CE | Name |
|---|---|---|
| 0 | 0 | Not ECT |
| 0 | 1 | ECT(1) |
| 1 | 0 | ECT(0) |
| 1 | 1 | CE |
RED介绍:Random Early Detection(随机早期检测)
功能:它是一种拥塞避免机制。它不像传统方式那样等队列满了才丢包,而是通过监控平均队列长度来提前预判拥塞。
工作流程:它会随机选择一部分数据包进行丢弃(或标记),以此向发送端"暗示"网络即将拥堵,请主动减速,从而避免后续出现更严重的丢包和延迟
CT:Non ECN-Capable Transport(不支持ECN的传输)
含义:这类报文不支持显式拥塞通知(ECN)机制。当发生拥塞时,它们无法理解"标记",因此对它们只能走传统路线------即直接丢包(比如通过你提到的RED算法)。
CE:Congestion Encountered(遇见拥塞)
这是一个"拥塞标记"。当网络设备(如路由器)发生拥塞时,如果遇到支持ECN的报文(CT=01或10),它不会直接丢包,而是把报文的这个标记位改为 11(即打上CE标记),相当于告诉接收端:"网络已经堵了,快通知发送端减速"

2、标识:16bits。
发送主机通常在每次发送数据报时将一个内部计算器加1,并将此值赋给标识字段。IP是无连接服务,该字段不是为了表明顺序,数据报不存在按序接收的问题。当数据报由于长度超过网络的MTU而必须分片时,这个标识字段的值就被复制到所有的数据报片的标识字段中,等到重组的时候,相同标识符的值的数据报就会被重新组装成一个数据报
3、标志 :3bits。用于分片。例如:010b.
低位(最右)叫做MF (More fragments):取零表示这是最后一个分片了,取1表示后面还有若干个数据。
中间位叫DF (Don't fragments):表示不进行分片。
最高位(最左):保留位,还未使用。
4、片偏移 :13bits。例如:0 0000 0000 0000b
在数据报分片后,该片在分组中的相对位置,片偏移以8B为基本单位。说明,分片的长度必须都是8B的整数倍。
5、生存周期(TTL) :8bits。例如:0x33H。数据报在网络中的寿命,为数据报经过路由器的数据量,每经过一个路由器,该值就减一,到零则视为不可达,被抛弃。
6、协议 :8bits。例如:0x11H(17,为UDP协议).指明上层协议,即数据部分携带的是哪种协议的数据。**常见17(UDP)**和6(TCP),此处的RoCE v2 是基于UDP 实现的,所以是17.
2.3 UDP 头部结构
UDP(User Datagram Protocol)是一种保留消息边界的简单的面向数据报(无连接)的传输层协议。提供差错检测,是尽最大努力的交付。
将ip和udp放在一起说,是因为UDP在IP协议上改动比较小,只增加了最基本的服务:复用、分用和差错检测。
注意:IP协议是没有提供差错检验的,IP协议的检验和只对IP协议的头部进行了检验。
DNS使用的是UDP协议。
UDP 首部:

UDP 头部具体介绍,参考链接:
linux之网络子系统(10)-MAC帧、数据报、段 的头部信息-CSDN博客
这里只介绍,在RoCE v2 中, UDP的目的端口是固定的, 是 4791。
2.4 IB BTH+
- BTH(Base Transport Header),是对消息的传输层描述,包括OpCode, Destination QPN, 发送方PSN等字段。

- RETH(RDMA Extended Transport Header),这部分是可选的,SEND的时候不需要,WIRTE的时候存在,主要用于描述远端的VA、RKey、DMA length信息。

- DETH (DATAGRAM EXTENDED TRANSPORT HEADER ),这是CM API 建链时, 才有的头部信息,是可选的,后面会抓包分析。

3、wireshark抓包分析报文头部信息
我自己抓的包,没有打开UDP头部,先借用网友的图:

InfiniBand传输层之上就是payload,即应用层数据(data)。
当报文超过RDMA的MTU时,RDMA传输层会做拆包,本例中我们使用RDMA WRITE像对端写入4096字节的数据,RDMA MTU选择的是1024,所以会被差分成4个报文,具体的报文内容如下图,请留意报文中Opcode的细微差异(Write First, Write Middle, Write Last):

关于RC(Reliable Connection)类型链接所有的OpCode如下表,感兴趣的话可以查看InfiniBand Architecture Specification的第九章节Transport Layer。

表中说明SEND也可能会出现拆包,类似的也有Send First, Send Middle, Send Last这几种传输层OpCode,关于RDMA Send的抓包如下图:
