3、RoCEv2协议栈解析:以太网、IP、UDP、BTH、RETH、原子操作等报文结构逐层拆解

RoCEv2(RDMA over Converged Ethernet version 2)是目前高性能计算与分布式存储网络中应用最广泛的RDMA承载协议。与RoCEv1直接在以太网二层(EtherType 0x8915)上承载InfiniBand报文不同,RoCEv2将IB报文封装进UDP/IPv4或UDP/IPv6报文之中,从而实现了跨三层路由的传输能力。这一设计使得RoCEv2能够适应大规模数据中心Spine-Leaf组网,但也带来了更复杂的报文解析需求。本章将从实际抓包出发,逐层拆解RoCEv2报文从以太网帧头到IB传输层(BTH)再到RDMA操作报文(RETH、原子操作等)的完整结构,帮助读者建立从字节流到语义的映射能力。

RoCEv2 报文协议栈分层结构 Wireshark 解析视角:从物理帧到RDMA语义 L2 以太网帧头 目的MAC(6B) | 源MAC(6B) | EtherType=0x0800(IPv4) 或 0x86DD(IPv6) 14 字节 L3 IP 头 版本/IHL | DSCP | 总长度 | 标识/分片 | TTL | 协议=17(UDP) | 源IP | 目的IP 20 字节 (IPv4) L4 UDP 头 源端口(动态) | 目的端口=4791 | UDP长度 | UDP校验和(必须启用) 8 字节 IB BTH (Base Transport Header) OpCode(8b) | SE(1b) | M(1b) | Pad(6b) | TVer(8b) | PKey(16b) | DestQP(24b) | A(1b) | 保留(7b) | PSN(24b) 12 字节 RETH / 原子操作头 (可选) RETH: VA(64b) | RKey(32b) | DMA长度(32b) | 原子: VA(64b) | RKey(32b) | 交换/比较数据(64b) 16 / 28 字节 Wireshark 过滤:udp.port == 4791 | ib.bth.opcode | ib.bth.dest_qp

上图展示了RoCEv2报文在Wireshark中的协议栈分层视图。与普通TCP/IP报文相比,RoCEv2的关键差异在于:UDP目的端口固定为4791(IANA分配的RoCEv2端口),且UDP校验和必须为有效值(不可设置为0)。从抓包分析的角度,我们需要依次剥离以太网头、IP头、UDP头,然后进入IB协议栈的BTH(基础传输头)解析,最后根据OpCode字段判断后续是否跟随RETH(RDMA扩展传输头)、原子操作头或仅包含纯Payload。下面将逐层展开详细拆解。

3.1 以太网与IP层:识别RoCEv2流量的入口

核心原理:RoCEv2报文在以太网层的EtherType字段通常为0x0800(IPv4)或0x86DD(IPv6),这与普通UDP流量完全一致。因此,仅凭以太网头无法区分RoCEv2与普通UDP流量,必须深入解析UDP目的端口。在IP层,RoCEv2使用普通IP路由机制,支持DSCP(差分服务代码点)标记以实现优先级调度。值得注意的是,RoCEv2报文通常不允许IP分片——因为RDMA要求报文原子性,分片会导致接收端无法重组完整的RDMA消息。

判断方法:在Wireshark中,使用过滤表达式 udp.port == 4791 可以快速筛选出所有RoCEv2报文。若需要进一步区分读写操作,可结合 ib.bth.opcode 字段过滤。对于IPv6环境,过滤条件相同,但需注意IPv6扩展头可能影响报文偏移量计算。

字段长度(字节)典型值/说明Wireshark显示
目的MAC6接收方网卡MACeth.dst
源MAC6发送方网卡MACeth.src
EtherType20x0800 (IPv4)eth.type
IP协议117 (UDP)ip.proto
DSCP1通常为46 (EF) 或 26 (AF31)ip.dsfield.dscp
经验提醒:在无损以太网环境中,RoCEv2流量通常配合PFC(优先级流控)使用。抓包时若发现DSCP值异常(如为0),可能导致交换机未正确映射到优先队列,引发丢包。

3.2 UDP层:RoCEv2的“伪装”与校验和强制要求

核心原理:RoCEv2选择UDP作为L4承载,主要目的是利用UDP端口号实现多租户隔离,并借助UDP校验和保证数据完整性。与普通UDP不同,RoCEv2要求UDP校验和必须计算且有效——这是RoCEv2规范(IBTA 1.2.1)的强制要求。若校验和错误,接收端网卡将直接丢弃报文,且不会产生ICMP错误消息。

操作流程:在Wireshark中,可通过 udp.checksum.status == 0 过滤校验和错误的报文。对于RoCEv2分析,建议在Wireshark首选项中启用“Validate UDP checksums if possible”,以便快速识别被网卡或交换机损坏的报文。

# 常用Wireshark过滤表达式
udp.port == 4791                    # 所有RoCEv2报文
udp.port == 4791 && ip.dst == 192.168.1.10  # 发往特定IP的RoCEv2
udp.checksum.status == 0            # 校验和错误的报文(需开启校验验证)
风险提示:某些网卡支持Rx Checksum Offload,导致Wireshark抓到的报文校验和字段显示为0x0000。此时应检查网卡高级属性中的“接收校验和卸载”设置,或使用 ethtool -K eth0 rx on 关闭卸载以获取真实校验和。

3.3 BTH(基础传输头):RDMA操作的核心语义

核心原理:BTH是每个RoCEv2报文必须包含的IB传输头,长度为12字节。它承载了OpCode(操作码)、目的QP号(Queue Pair)、PSN(包序列号)等关键信息。OpCode决定了后续报文类型:是发送(Send)、写(Write)、读(Read)还是原子操作。BTH中的PKey用于分区隔离,类似于VLAN在以太网中的作用。

关键字段拆解:

  • OpCode(8位):高4位表示操作类型(0x00=Send,0x04=Write,0x08=Read,0x0C=Atomic),低4位表示是否首包/中间包/尾包。
  • DestQP(24位):目的队列对编号,用于标识接收端的QP上下文。
  • PSN(24位):包序列号,用于乱序检测和重传判断。
  • PKey(16位):分区键,必须与接收端QP配置的PKey匹配。
OpCode值操作类型后续头典型场景
0x00Send FirstRETH (可选)SEND操作首包
0x04Write FirstRETHRDMA Write首包
0x08Read RequestRETHRDMA Read请求
0x0CAtomic Compare&Swap原子操作头原子比较交换
0x11Atomic Fetch&Add原子操作头原子取加
实战要点:在Wireshark中,展开 InfiniBand 协议树即可看到BTH各字段。重点关注 ib.bth.opcode 和 ib.bth.dest_qp。若OpCode显示为“Reserved”,说明报文被错误解析或存在非标准实现。

3.4 RETH与原子操作头:RDMA操作的地址与长度信息

核心原理:RETH(RDMA Extended Transport Header)用于RDMA Read/Write操作,包含虚拟地址(VA)、RKey(远程内存访问密钥)和DMA长度。RKey是保护机制的核心——接收端网卡通过RKey验证发送方是否有权访问指定内存区域。原子操作头则包含VA、RKey以及操作数(Compare&Swap的旧值/新值,或Fetch&Add的加数)。

案例拆解:假设某分布式存储节点通过RDMA Write将4KB数据写入对端内存。抓包显示:

InfiniBand
  BTH
    OpCode: Write First (0x04)
    DestQP: 0x001234
    PSN: 0x000001
  RETH
    Virtual Address: 0x00000000_7fff0000
    RKey: 0x12345678
    DMA Length: 4096

分析过程:该报文是RDMA Write的首包,目标QP为0x001234,写入地址为0x7fff0000,长度4096字节。若后续还有中间包(OpCode=0x05)和尾包(OpCode=0x06),则总长度可能超过单包承载能力(通常为MTU-40字节)。

常见误区:初学者常将RETH中的VA误认为物理地址。实际上,VA是虚拟地址,需经过网卡MMU(内存管理单元)转换为物理地址。若RKey无效或VA越界,网卡将产生Local Length Error或Remote Access Error,并在完成队列(CQ)中上报错误事件。

3.5 完整报文解析实战:从字节流到语义

操作流程:以下是一个完整的RoCEv2 Read Request报文解析步骤:

  1. 确认以太网EtherType=0x0800,IP协议=17,UDP目的端口=4791。
  2. 展开UDP头,记录源端口(动态分配)和UDP长度。
  3. 进入InfiniBand协议树,读取BTH中的OpCode=0x08(Read Request)。
  4. 解析RETH中的VA、RKey和DMA长度,确认请求的远程内存范围。
  5. 检查PSN连续性,判断是否存在丢包或乱序。

案例闭环:某AI训练集群出现训练速度下降,抓包发现大量重传。分析过程:

  • 初始现象:训练任务吞吐量从120Gbps降至80Gbps,GPU利用率波动。
  • 关键数据:Wireshark统计显示重传率3.2%,PSN跳变频繁。
  • 分析判断:过滤 tcp.analysis.retransmission 不适用(RoCEv2无TCP),改用 ib.bth.psn 排序发现PSN间隙。
  • 实际操作:使用 ib.bth.psn 作为Y轴绘制IO图,发现周期性PSN回退。
  • 结果对比:定位为交换机ECMP哈希不均导致单链路拥塞,调整哈希算法后重传率降至0.1%。
  • 复盘经验:RoCEv2排障必须关注PSN连续性,而非TCP序列号。
总结复盘:RoCEv2报文解析的核心在于理解“UDP端口4791”是入口,BTH的OpCode是语义核心,RETH/原子头是操作细节。建议读者在Wireshark中加载 InfiniBand 解析器,并保存常用过滤表达式为按钮,提升日常分析效率。