第一部分 · 4 / 6
传输类型 RC / UD
QP 有不同的传输类型,决定了它的可靠性、连接性和能用哪些操作。 gordma 主要关注两种:RC(可靠连接)和 UD(不可靠数据报), 分别类比 TCP 和 UDP。此外还要区分双边与单边两类操作语义。
RC vs UD
| 维度 | RC(可靠连接)类比 TCP | UD(不可靠数据报)类比 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 教程