RDMA 与RoCE v2

一套最精简、能直接落地的 RDMA / RoCE v2 工程资料包,包含:关系再梳理、报文结构、FPGA 实现框架、x86 侧最简可用 C 代码、测试命令。

一、RDMA ↔ RoCE v2 关系(最终版)

  • RDMA :一套远程直接内存访问技术标准(API + 语义)
    • 零拷贝、内核旁路、CPU 不参与数据搬运
  • RoCE :RDMA over Converged Ethernet,以太网承载 RDMA
    • RoCE v1:L2 以太网,不可路由
    • RoCE v2:L3 UDP/IP 封装,可路由,现在唯一实用版本

可以记成:

RDMA = 能力 RoCE v2 = 以太网环境下跑 RDMA 的报文格式


二、RoCE v2 报文封装结构

plaintext

复制代码
以太网头 + IP头 + UDP头 + GRH + BTH + RDE + 载荷
  • GRH:Global Routing Header(RoCE v2 特有,用于路由)
  • BTH:Base Transport Header
  • RDE:RDMA 扩展头(Send/Read/Write/Atomic)

特点:

  • 就是一个标准 UDP 报文 ,端口默认 4791
  • 普通交换机可转发,支持三层路由
  • 无损网络建议开启 PFC / ECN(不强制,但延迟更稳)

三、FPGA 实现 RoCE v2 最小结构

你用 FPGA 做 RNIC(RDMA 网卡),核心就这几部分:

  1. PCIe DMA 引擎
    • 与 x86 主机内存交互(QP 队列、WQE、CQE)
  2. QP 管理模块(Queue Pair)
    • SQ + RQ:发送 / 接收队列
    • CQ:完成队列
  3. RoCE v2 协议栈
    • 封装 / 解封装 GRH/BTH/UDP/IP
    • 校验和卸载
  4. 以太网 MAC/PCS
    • 25G/100G 以太网时序处理
  5. 可靠传输控制(可选)
    • ACK、重传、滑动窗口(RC 模式)

数据流:

plaintext

复制代码
x86 提交 WQE → FPGA QP → 封装 RoCE v2 → 以太网发送

四、x86 侧 RDMA (ibverbs) 最简发送代码

依赖:libibverbs

c

运行

复制代码
#include <infiniband/verbs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUF_SIZE 1024

int main() {
    struct ibv_device **dev_list;
    struct ibv_context *ctx;
    struct ibv_pd *pd;
    struct ibv_mr *mr;
    struct ibv_cq *cq;
    struct ibv_qp *qp;
    struct ibv_qp_init_attr qp_attr = {};
    char *buf = malloc(BUF_SIZE);
    struct ibv_wc wc;
    int ret;

    // 1. 打开 RDMA 设备
    dev_list = ibv_get_device_list(NULL);
    ctx = ibv_open_device(dev_list[0]);
    ibv_free_device_list(dev_list);

    // 2. 保护域 + 注册内存
    pd = ibv_alloc_pd(ctx);
    mr = ibv_reg_mr(pd, buf, BUF_SIZE,
        IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE);

    // 3. 创建 CQ + QP
    cq = ibv_create_cq(ctx, 128, NULL, NULL, 0);
    qp_attr.send_cq = cq;
    qp_attr.recv_cq = cq;
    qp_attr.qp_type = IBV_QPT_RC;  // RC = 可靠连接
    qp = ibv_create_qp(pd, &qp_attr);

    // 4. QP 状态切换 (INIT->RTR->RTS)
    // 略(需要对方 QP 信息,实际代码需交换 GID/QP 号)

    // 5. 发送数据
    memset(buf, 0x5a, BUF_SIZE);
    struct ibv_sge sge = {
        .addr = (uint64_t)buf,
        .length = BUF_SIZE,
        .lkey = mr->lkey
    };
    struct ibv_send_wr wr = {
        .wr_id = 0x1234,
        .sg_list = &sge,
        .num_sge = 1,
        .opcode = IBV_WR_SEND,
        .send_flags = IBV_SEND_SIGNALED
    };
    struct ibv_send_wr *bad_wr;
    ret = ibv_post_send(qp, &wr, &bad_wr);

    // 6. 等待完成
    while (ibv_poll_cq(cq, 1, &wc) < 1);
    printf("RDMA Send 完成, status=%d\n", wc.status);

    return 0;
}

编译:

bash

运行

复制代码
gcc rdma_test.c -o rdma_test -libverbs

五、RDMA 常用操作(你和 FPGA 通信最常用)

  1. IBV_WR_SEND
    • 主动发消息,对方需提前 posted recv
  2. IBV_WR_WRITE
    • 直接写对方内存,对方 CPU 完全无感知
    • 最适合 FPGA → x86 低延迟上行
  3. IBV_WR_READ
    • 直接读对方内存
  4. Atomic
    • 原子加 / 比较交换,用于同步

实时通信首选:WRITE + 少量 SEND 同步


六、测试 RDMA 延迟 / 带宽命令

安装:perftest

bash

运行

复制代码
# 服务端(FPGA 或另一台机器)
ib_write_bw -d rdma0 -R  # RoCE v2
ib_write_lat -d rdma0 -R

# 客户端
ib_write_bw -d rdma0 -R 192.168.1.100
ib_write_lat -d rdma0 -R 192.168.1.100

典型结果:

  • 写延迟:1us 左右
  • 抖动:< 100ns
  • 100G 带宽可跑满

七、你接下来最该做的三件事

  1. 在 FPGA 上实现 RoCE v2 + QP + DMA
  2. x86 用 ibverbsRDMA_WRITE 上行
  3. 配合之前的系统优化(isolcpus、关闭节能、巨页)
相关推荐
水云桐程序员31 分钟前
FPGA开发需要的环境配置
fpga开发
LCMICRO-133108477462 小时前
长芯微LPS6288完全P2P替代TPS61288,是一款具有 15A 开关电流的全集成同步升压转换器
stm32·单片机·嵌入式硬件·fpga开发·硬件工程·同步升压转换器
Soari4 小时前
FPGA开发:Vivado 打开工程的两种方式详解(.xpr vs Tcl)
fpga开发
星华云6 小时前
[FPGA] ISE DDS IP核简单记录使用
fpga开发
Kong_19947 小时前
芯片开发学习笔记·二十五——UCIe
fpga开发·芯片开发
发发就是发9 小时前
I2C适配器与算法:从一次诡异的时序问题说起
服务器·驱动开发·单片机·嵌入式硬件·算法·fpga开发
ALINX技术博客18 小时前
【黑金云课堂】FPGA技术教程FPGA基础:流水灯实验
fpga开发·fpga
化屾为海1 天前
FPGA制造与测试全流程
fpga开发·制造
Aaron15881 天前
RFSOC+VU13P+RK3588的核心优势与应用场景分析
嵌入式硬件·算法·matlab·fpga开发·信息与通信·信号处理·基带工程
Aaron15881 天前
8通道测向系统演示科研套件
人工智能·算法·fpga开发·硬件工程·信息与通信·信号处理·基带工程