4、RoCE协议栈:报文封装格式与版本演进

大家好,我是老张。今天我们来聊聊RoCE协议栈的核心——报文封装。说实话,很多刚接触RDMA的朋友,一看到报文格式就头大。其实没那么复杂,咱们一层层剥开来看。

4.1 RoCE的两种版本:v1和v2

RoCE从诞生到现在,主要有两个版本。我个人习惯把它们比作「两条不同的路」——都能到达目的地,但走法不一样。

特性 RoCE v1 RoCE v2
封装层 直接基于以太网类型 基于UDP封装
网络层 无(二层网络) 有IP头(三层路由)
适用场景 同一广播域内 跨网段、跨数据中心
GRH支持 可选 可选

嗯,这里要注意:RoCE v1只能在同一个二层网络里跑。什么意思呢?就是你的服务器和存储设备必须在同一个VLAN里,不能跨路由器。我在项目里遇到过,有人把v1的流量硬要往三层交换机上送,结果丢包丢到怀疑人生。

4.2 RoCE v1报文封装格式

RoCE v1的封装,说白了就是在标准以太网帧里直接塞了个IB(InfiniBand)的报文。它的格式长这样:

+------------------+------------------+------------------+
|  以太网头 (14B)   |   GRH (40B)      |   IB Payload     |
|  (DMAC+SMAC+Type)|  (全局路由头)     |   (数据段)       |
+------------------+------------------+------------------+
|  EtherType = 0x8915                     |                 |
+-----------------------------------------+-----------------+

关键点在于以太网头里的EtherType字段,它被设置为0x8915。这个值就是RoCE v1的身份证。交换机看到这个值,就知道「哦,这是RDMA流量」。
GRH(Global Routing Header)是40字节的全局路由头,它包含了源和目标GID(全局标识符)。

避坑指南:我曾经在配置RoCE v1时,忘了检查交换机的EtherType过滤规则。结果流量全被当成未知协议丢弃了。后来排查了整整两天才发现——交换机默认不转发0x8915的帧。所以,记得在交换机上放行这个EtherType。

4.3 RoCE v2报文封装格式

RoCE v2就灵活多了。它把IB报文封装在UDP里,这样就能走三层网络了。格式如下:

+------------------+------------------+------------------+------------------+
|  以太网头 (14B)   |   IP头 (20B)     |   UDP头 (8B)     |   IB Payload     |
|  (DMAC+SMAC+Type)|  (源/目标IP)      |  (端口: 4791)    |   (数据段)       |
+------------------+------------------+------------------+------------------+
|  EtherType = 0x0800 (IPv4) 或 0x86DD (IPv6)          |                 |
+-------------------------------------------------------+-----------------+

你想想看,RoCE v2最大的变化是什么?
对,就是多了UDP头。UDP的目标端口固定为4791。这个端口号是IANA分配给RoCE v2的专用端口。有了UDP封装,路由器就能识别并转发这些报文了。

小技巧:我在实际部署中,习惯用tcpdump -i eth0 udp port 4791来抓取RoCE v2流量。这样能快速确认RDMA报文是否正常发出。如果抓不到包,先检查UDP端口是否被防火墙拦截了。

4.4 GRH(全局路由头)详解

GRH是RoCE协议里一个比较特殊的存在。它其实是从InfiniBand协议里继承过来的。说白了,GRH就是IB世界的「IP头」——它负责在InfiniBand网络中做路由寻址。

GRH的结构如下:

+--------+--------+--------+--------+
| 版本(4b)| 流量类(8b)| 流标签(20b) |
+--------+--------+--------+--------+
|  载荷长度(16b)   | 下一头(8b) | 跳数限制(8b) |
+------------------+--------+--------+
|        源GID (128位)               |
+------------------------------------+
|        目标GID (128位)             |
+------------------------------------+

这里有个容易混淆的点:GRH在RoCE v1和v2中都是可选的。为什么?因为RoCE本身是跑在以太网上的,以太网有自己的MAC地址做二层寻址。GRH更多是为了兼容InfiniBand的生态。

注意:如果你的RoCE网络需要跨子网通信,或者使用了多路径路由,那么GRH就是必须的。我见过有人图省事,在跨网段场景下省略了GRH,结果RDMA连接死活建立不起来。后来加上GRH,问题立刻解决。

4.5 报文封装对比总结

为了让你看得更清楚,我画了一张对比图:

RoCE v1 封装 以太网头 GRH (可选) IB Payload EtherType = 0x8915 RoCE v2 封装 以太网头 IP头 UDP头 GRH (可选) IB Payload EtherType = 0x0800 (IPv4) 或 0x86DD (IPv6) UDP端口 = 4791 关键区别:RoCE v1 是二层协议,RoCE v2 是三层协议。v2 通过UDP封装实现了路由能力。

从这张图可以看得很清楚:
RoCE v1的报文结构更简单,但局限在二层网络。
RoCE v2虽然多了IP头和UDP头,但换来了跨网段通信的能力。说白了,这就是用「多一层封装」换「更大的灵活性」。

我的建议:新项目直接上RoCE v2。为什么?因为现在数据中心都在往Spine-Leaf架构演进,v1的二层限制太死。而且v2的UDP封装对ECMP(等价多路径)更友好,能充分利用带宽。我在最近三个数据中心项目里,全部用的RoCE v2,效果很好。

好了,关于RoCE的报文封装,今天就聊到这里。记住一句话:v1是二层直连,v2是三层路由。搞清楚了这一点,后面的PFC、ECN这些流控机制,理解起来就顺了。


专注资料整理