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、关闭节能、巨页)
相关推荐
Terasic友晶科技2 小时前
2-DE10-Nano的HDMI音频传输案例——基于FPGA的I2S控制模块设计
fpga开发·音视频·i2s·de10-nano·hdmi音频传输
ZPC82103 小时前
x86 + FPGA 网卡通信实时性能优化清单
fpga开发·性能优化
学习永无止境@4 小时前
DMA/Bridge Subsystem for PCI Express V4.2
fpga开发·xdma
ZPC82105 小时前
x86 与 FPGA 网卡通信实时性
arm开发·fpga开发
XMAIPC_Robot5 小时前
基于ARM+FPGA的电火花数控硬件平台总体设计(一)
运维·服务器·人工智能·fpga开发·边缘计算
慕云山里被狗追5 小时前
rv1126bp lvds调试
fpga开发
星华云9 小时前
[FPGA]Spartan6 Uart固定波特率读写JY901P惯导模块
fpga开发·verilog·jy901p·惯导模块
s090713620 小时前
ZYNQ无SD卡纯NAND Flash启动Linux全攻略
linux·fpga开发·zynq·nand flash启动
jjinl1 天前
AG32VF407RGT6 开发流程记录
fpga开发