第二部分 · 3 / 7
底层 verbs 封装
第一部分那张对象表,在代码里就是这些 Go 类型和方法。引用包注释 doc.go:
「The library mirrors the object model of rdma-core: Device, Context, PD, MR, CQ, QP, AH and CompChannel.」
典型的资源创建链
// 1. 枚举并打开设备
devs, free, _ := gordma.GetDeviceList()
defer free()
ctx, _ := devs[0].Open() // → *Context
defer ctx.Close()
// 2. 保护域 + 注册内存(返回带 lkey/rkey 的 MR)
pd, _ := ctx.AllocPD()
mr, _ := pd.RegMRBuffer(65536, gordma.AccessLocalWrite|gordma.AccessRemoteWrite)
buf := mr.Bytes() // GC 安全的可读写切片
// 3. 完成队列 + 队列对
cq, _ := ctx.CreateCQ(256, nil) // 第二个参数是可选的完成通道
qp, _ := pd.CreateQP(gordma.QPInitAttr{
Type: gordma.QPTypeRC,
SendCQ: cq, RecvCQ: cq,
Cap: gordma.DefaultQPCapacity(),
})
MR:内存注册与那两把钥匙
RegMRBuffer(size, flags) 分配并注册一块缓冲区,flags 是 AccessFlag 位掩码,控制网卡能对它做什么:
| AccessFlag | 含义 |
|---|---|
AccessLocalWrite | 允许本地写(接收缓冲区必需) |
AccessRemoteWrite | 允许远端 RDMA Write 进来 |
AccessRemoteRead | 允许远端 RDMA Read |
AccessRemoteAtomic | 允许远端原子操作 |
注册后这些方法取出关键信息:
mr.Bytes() // []byte,GC 安全
mr.LKey() // 本地 key
mr.RKey() // 远端 key(发给对方授权 RDMA 访问)
mr.Addr() // 虚拟地址(远端 Write/Read 的落点)
mr.Len() // 长度
QP 状态机就是三个方法
第一部分讲的 INIT → RTR → RTS,在 gordma 里就是 QP 上的三个方法,对端参数用
RCConnParams 携带(详见 第一部分 · QP 与状态机):
qp.ModifyToInit(portNum, access)
qp.ModifyToRTR(params) // params 含对端 QPN/PSN/GID/MTU…
qp.ModifyToRTS(params)
投递工作请求
发送/接收都用结构体描述(postwr.go),再 post 到 QP。SGE 是 scatter/gather 元素,
指向已注册 MR 的一段:
// 构造一个覆盖 MR [off, off+length) 的 SGE
sge := gordma.SGEFromMR(mr, 0, 1024)
wr := gordma.SendWR{
WRID: 1,
Opcode: gordma.OpSend, // 或 OpWrite / OpRead
SGList: []gordma.SGE{sge},
Signaled: true, // 要求产生完成项
}
对单边操作,SendWR 里还要填 RemoteAddr + RKey;对 UD,则填 AH + RemoteQPN + RemoteQKey。
小消息可设 Inline: true 走内联优化。
轮询完成
完成项是扁平值类型 WorkCompletion(cq.go),可复用切片避免每次分配。先查状态:
if !wc.Status.OK() { // Status != WCSuccess
// 失败:RNR 重试耗尽 / 长度错误 / 保护错误…
}
// wc.WRID 对回 post 的 id;wc.ByteLen 收到字节数;wc.Opcode 操作类型
查询能力 / 端口
需要时可以查设备和端口属性来决定参数(MTU、GID 表长度、是否 RoCE 等):
| 类型 | 用途 |
|---|---|
DeviceAttr | 设备能力:MaxQP / MaxCQE / MaxMR / 固件版本…(QueryDevice) |
PortAttr | 端口属性:State / ActiveMTU / LID / LinkLayer…(QueryPort) |
gordma 教程