3、RoCE v2协议深度解析:UDP封装、GID与LID、GRH(全局路由头),在跨DC场景下的路由行为

好,咱们进入RoCE v2的核心。说实话,很多搞网络的朋友一听到RDMA就觉得是InfiniBand的专利。其实RoCE v2的出现,彻底改变了这个局面。它让RDMA跑在普通以太网上,而且还能跨数据中心。

我个人习惯把RoCE v2看作「披着UDP外衣的InfiniBand」。为什么这么说?咱们一层层剥开看。

3.1 从RoCE v1到v2:为什么必须改?

RoCE v1直接把InfiniBand的报文封装在以太网头里, EtherType是0x8915。这在单个二层网络里跑没问题,但一出广播域就抓瞎了。我记得早期有个项目,客户想把两个机房的RoCE网络打通,结果发现v1根本过不了三层网关。

RoCE v2的改进很聪明——它把IB的报文塞进了UDP包里。具体来说:

  • 源端口:用哈希算法算出来,用于负载均衡
  • 目的端口:固定4791(IANA分配的)
  • UDP Checksum:建议启用,但很多硬件实现里可以关掉

你想想看,UDP包是可以被普通路由器转发的。这就意味着RoCE v2天然支持三层路由。嗯,这里要注意:不是所有路由器都能正确处理RoCE v2的UDP包,尤其是涉及到ECMP哈希的时候。

核心变化一句话:RoCE v2用UDP封装换来了三层路由能力,这是跨DC互联的基础。

3.2 GID与LID:两种地址,两种玩法

RoCE v2里有两个地址概念,我刚开始学的时候也绕了一阵子。

LID(Local Identifier)

这是InfiniBand网络里的16位本地标识符。在RoCE v2里,LID其实被弱化了。为什么?因为RoCE v2跑在IP网络上,LID只在子网内部有意义。跨DC场景下,LID基本用不上。

我曾经在一个测试环境里看到有人纠结LID配置,其实大可不必。RoCE v2的转发决策主要看GID。

GID(Global Identifier)

GID才是RoCE v2跨DC的核心。它是一个128位的地址,结构如下:

GID = Global_Header + Subnet_Prefix + Interface_ID
     = 64位前缀 + 64位接口标识符

说白了,GID就是IPv6地址的变体。RoCE v2的GID通常直接映射到IPv6地址。每个RoCE网卡至少有一个GID,对应一个IPv6地址。

我的经验:在配置跨DC RoCE时,一定要确保两端GID的Subnet Prefix一致。否则报文到了对端会被当成非法源地址丢弃。我踩过这个坑,排查了整整一个下午。

3.3 GRH(全局路由头):跨DC的导航仪

GRH是RoCE v2报文里最重要的头部。它其实就是IPv6的扩展头,包含了完整的路由信息。

GRH的结构长这样:

+----------------+----------------+----------------+----------------+
| Version(4)     | Traffic Class(8)| Flow Label(20) | Payload Len(16)|
+----------------+----------------+----------------+----------------+
| Next Header(8) | Hop Limit(8)   |                                |
+----------------+----------------+                                |
|                         Source GID (128 bits)                     |
|                                                                   |
+-------------------------------------------------------------------+
|                       Destination GID (128 bits)                  |
|                                                                   |
+-------------------------------------------------------------------+

注意看,GRH里包含了源和目标GID。这跟IPv6路由头的思路一模一样。当RoCE v2报文穿越三层网络时,中间路由器就看这个GRH来决定下一跳。

我个人习惯把GRH理解成「快递单上的地址标签」。没有它,报文就是个盲盒,谁都不知道该往哪送。

3.4 跨DC场景下的路由行为

好,重点来了。RoCE v2报文在跨DC时到底怎么走?我画了一张图,帮你理清整个流程。

数据中心A 数据中心B Server A GID: 2001::1 Server B GID: 2001::2 Leaf1 Leaf2 Spine1 Spine2 DC GW Router DC GW Router WAN链路 ① RoCE v2报文 (UDP封装+GRH) ② 查GRH目标GID ③ 路由到DC2 ④ 解封装交付 图例 服务器 路由器

整个路由过程其实就三步:

  1. 封装:Server A发出RoCE v2报文,加上UDP头和GRH。GRH里的目标GID填的是Server B的IPv6地址。
  2. 转发:Leaf1和Spine1看到GRH,发现目标GID不在本DC,于是查路由表,把报文扔给DC出口路由器。
  3. 跨DC传输:DC GW Router通过WAN链路把报文送到对端。对端路由器再根据GRH逐跳转发到Server B。

⚠️ 重要提醒:跨DC场景下,WAN链路的MTU必须大于RoCE v2报文的最大尺寸(通常需要9000字节的巨型帧支持)。否则报文会被分片,RDMA性能直接崩盘。我曾经见过一个案例,客户跨DC RoCE跑不起来,最后发现是运营商链路的MTU只有1500。

3.5 避坑指南:跨DC RoCE路由的常见问题

讲几个我实际踩过的坑:

  • ECMP哈希不均匀:RoCE v2的UDP源端口是哈希算出来的,但有些老式路由器只看IP五元组,导致所有RoCE流量走同一条链路。解决方案是升级支持RoCE感知哈希的设备。
  • PFC死锁:跨DC时,PFC(优先级流控)的暂停帧可能被WAN链路延迟放大,造成死锁。我建议在DC边界关闭PFC,改用DCQCN做拥塞控制。
  • GID冲突:两个DC如果用了相同的IPv6子网前缀,GID会冲突。规划时要确保每个DC的GID前缀全局唯一。

我的建议:在部署跨DC RoCE之前,先用iperf或qperf打流测试UDP连通性。如果普通UDP都过不去,RoCE v2肯定也不行。别问我怎么知道的——说多了都是泪。

好了,RoCE v2协议的核心就这些。记住一句话:UDP封装给了它跨DC的能力,GRH给了它路由的智慧,GID给了它唯一的身份。下一节咱们聊聊实际部署中的配置细节,到时候我会拿出我珍藏的几份配置模板。

本章小结:

  • RoCE v2用UDP封装(目的端口4791)实现三层路由
  • GID是128位全局标识,映射到IPv6地址
  • GRH包含源/目标GID,是跨DC路由的核心
  • 跨DC场景需注意MTU、ECMP哈希、PFC死锁等问题
专注资料整理