第二部分 · 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) 分配并注册一块缓冲区,flagsAccessFlag 位掩码,控制网卡能对它做什么:

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 走内联优化。

轮询完成

完成项是扁平值类型 WorkCompletioncq.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
下一步 以上每一步在高层 rdmanet 里都被隐藏了。下一节看 高层 rdmanet 是怎么把它们收成 SendMsg/RecvMsg 的。
gordma 教程