从零读懂RDMA UD send:硬件视角下的“无连接”数据报
今天我们接着聊RDMA UD send你可能会被不可靠”“无连接”这几个字吓到会说这不就是UDP嘛RDMA为什么要做一个这样的东西。但是事实上UD在RDMA里占据着不可替代的位置控制消息、多播同步、IPoIB的广播都靠它。在开始详细描述之前我们首先需要解释一下UD的“无连接”问题例如RC QP在发送数据之前必须经历REQ/REP/RTU三次握手双方交换QPN、起始PSN、MTU等参数QP状态机从Reset走到RTS这才算“建链成功”。这个过程由硬件参与状态机固化在QP上下文里。而UD完全没有这个流程那他的信息是如何交换获取的呢常见的有一下几种方式Socket/CM交换双方先通过一个TCP连接或RDMA CM互相告知自己的UD QPN和地址然后各自用这些信息去发UD消息静态配置在集群配置文件中写死对方QPN和地址程序启动时读取多播/广播发现发送端往一个已知的多播组发送“我是谁我的QPN是多少”的广播包感兴趣的对端收到后记录下来并直接回复所以UD的“无连接”仅仅是指硬件QP没有RC那种显式的连接建立状态机而不是说软件不需要知道对方是谁。这个区别必须一开始就讲清楚否则后面的所有内容都会让人困惑。一、硬件眼中的UD极简的QP上下文对于UD的QP上下文来说硬件只需要记住以下信息本端QPN接收Q_Key一些标志位不需要维护PSN没有窗口没有重传计时器没有对端状态。硬件看到这样的“小身板”就知道这个QP可以开很多个。二、发送硬件从WQE里拿到一切应用程序要发UD消息必须先拿到对端的QPN和地址然后将全部的信息在WR里填好而驱动把WR转换成WQE写入SQ敲门。网卡硬件从SQ里取出WQE然后按顺序执行下面的步骤DMA取数据拿着WQE里的本地数据指针通过PCIe DMA把数据从主机内存搬到网卡内部的包缓冲区。因为UD不能拆包如果数据长度超过路径MTU硬件会直接报错CQE里的状态码告诉你是长度超限。获取头部信息通过QP和WQE获取目的/源IP地址、目的/源MAC地址、UDP端口RoCEv2固定4791、目的LID/GID等。构造IB传输头BTH DETHBTHOpCode UD Send OnlyDest QP WQE中的remote_qpnPSN 0占位。DETH8字节包含Q_Key32位和Source QPN24位。构造RoCEv2封装并计算ICRC。发送将完整数据包通过物理端口发出。立即产生CQE不等待任何ACK发完后直接在CQ中生成完成条目无重传、无计时器、无PSN跟踪。三、接收Q_Key是门禁多播是复制接收端网卡从线缆上抓到包解完LRH/GRH看到OpCode是UD Send Only就知道这是一个UD包。接下来要决定这个包应该交给哪个QP这个流程主要分为以下几步从DETH里取出Q_Key和Source QPN。看BTH里的DST QPN此时有两种情况如果DST QPN是一个具体数值那么直接用这个数值去QP Table里找对应的UD QP。找到且类型匹配就继续找不到或类型不对则直接丢弃报文。如果是特殊值0xFFFFFF那么说明这是一个多播包此时要去多播组成员关系表找到所有加入该多播组的本地QP然后每个QP都复制一份。Q_Key校验找到目标QP后检查包里的Q_Key是否等于该QP预设的接收Q_Key。DMA写内存从目标QP的RQ里取出一个预先post好的Receive WQE拿到接收缓冲区地址。硬件把包的有效载荷去掉所有头部通过DMA写入主机内存。产生CQE如果一张网卡上有3个QP都加入了同一个多播组硬件收到一个多播包时会在网卡内部把数据包复制3份分别DMA到3个接收缓冲区然后出3个CQE。四、总结UD的“无连接”三个字经常被误解为“不需要知道对方是谁就能发消息”。经过这篇文章你应该明白硬件确实不需要握手但软件必须在发送前通过某种方式拿到对方的QPN和地址然后显式地填进WQE。硬件只负责执行不负责发现。这种设计是RDMA追求极致性能的一个缩影把复杂的事情交给软件发现、协商、错误恢复让硬件专注于最核心的数据搬移。理解了这个分工你就真正看懂了UD。