第一部分 · 4 / 6

传输类型 RC / UD

QP 有不同的传输类型,决定了它的可靠性、连接性和能用哪些操作。 gordma 主要关注两种:RC(可靠连接)UD(不可靠数据报), 分别类比 TCP 和 UDP。此外还要区分双边与单边两类操作语义。

RC vs UD

维度RC(可靠连接)类比 TCPUD(不可靠数据报)类比 UDP
连接性面向连接,一个 QP 对一个对端无连接,一个 QP 可发往多个对端
可靠性保证有序、可靠送达(硬件重传)不保证,可能丢失/乱序
消息大小可超大(大消息硬件分片)单条不能超过路径 MTU
支持操作Send/Recv + RDMA Write/Read仅 Send/Recv
寻址建连时确定对端每次发送指定对端(AH + QPN + QKey)
适用大多数点对点通信一对多、广播、服务发现

gordma 的类型常量(types.go):

const (
    QPTypeRC QPType = 2  // 可靠连接
    QPTypeUC QPType = 3  // 不可靠连接(非主要目标)
    QPTypeUD QPType = 4  // 不可靠数据报
)

双边操作 vs 单边操作

这是 RDMA 区别于普通网络的另一个核心概念,按「对端 CPU 是否参与」分两类:

双边 (Two-sided):Send / Recv
接收方必须预先投递接收 WR,发送方的 Send 才有落点。双方 CPU 都参与,语义最像 socket。RC 和 UD 都支持。
单边 (One-sided):RDMA Write / Read
发起方凭 rkey + 远端地址,直接读写对端已注册内存,对端 CPU 完全不感知,时延最低。仅 RC 支持。

gordma 的操作码(postwr.go)正好对应这几类:

const (
    OpSend     SendOpcode = 0  // 双边 SEND(消耗对端一个 recv WR)
    OpWrite    SendOpcode = 1  // 单边 RDMA WRITE
    OpWriteImm SendOpcode = 2  // RDMA WRITE 带立即数
    OpRead     SendOpcode = 3  // 单边 RDMA READ
)

这也解释了第三部分的工具命名:go_send_* 测双边 Send,go_write_* / go_read_* 测单边 Write/Read。

UD 的两个特别之处

UD 因为无连接,在 gordma 里有两个要注意的细节:

  • 每条收到的数据报前面有 40 字节的 GRH(Global Routing Header)。接收缓冲区要多留 GRHLength = 40 字节,跳过它才是真正的负载。
  • 用 AH(Address Handle)寻址:发送前要根据对端 GID/QPN 构造地址句柄。 gordma 的 AHAttr 描述这些信息,UDConnParams 携带 QKey(两端必须一致才能收)。
// UD 接收:前 40 字节是 GRH,需跳过
const GRHLength = 40

type UDConnParams struct {
    QKey    uint32  // 两端必须匹配,数据报才被接受
    PortNum int
}
下一步 上面多次提到 GID。它到底是什么、为什么有「GID 索引」?下一节讲 RoCE 与 GID——这是 RoCE 组网里最常踩坑的地方。
gordma 教程