本页目录

RDMA (Remote Direct Memory Access)

覆盖: RDMA 架构 → InfiniBand/RoCE/iWARP → verbs API → Queue Pair → Memory Region → 内核旁路 → 与 Linux 网络栈集成 内核版本: 3.x ~ 6.x

概述

RDMA 允许一台机器直接读写另一台机器的内存,⁠绕过远程 CPU 和内核⁠。延迟从传统 TCP/IP 的 ~50μs 降到 ~1μs,同时 CPU 零参与数据传输。Linux 通过 ib_core + 厂商驱动 (mlx5, qedr, hns) 提供统一的 RDMA 接口。

三种传输

InfiniBandRoCEv2iWARP
网络层IB L2/L3UDP/IP (dst port 4791)TCP/IP
硬件IB HCA融合以太网卡融合以太网卡
依赖IB 交换机DCB/PFC (无损以太网)标准 TCP 卸载
内核支持ib_coreib_core + rdma_rxe(SW)iw_cm

核心抽象: Queue Pair (QP)

每个 QP = Send Queue (SQ) + Receive Queue (RQ) + Completion Queue (CQ)

SQ: 本端发起的 RDMA 操作 (SEND, RDMA_WRITE, RDMA_READ)
RQ: 等待远端 SEND 的缓冲区 (先 post 缓冲, 收到 SEND 后填充)
CQ: 完成通知 (操作完成后硬件写 CQE)

QP 状态机:
  RESET → INIT → RTR (Ready To Receive) → RTS (Ready To Send)

Memory Region (MR)

// RDMA 硬件直接写远端内存 → 需要内存"注册" (pinning)
// 注册: ibv_reg_mr() → 硬件锁定物理页 + 生成 access key (rkey/lkey)
// 
// 为什么需要注册?
//   RDMA HCA 旁路了内核 → 不能依赖 CPU 页表做地址转换
//   → 需要物理地址的直接映射 + 锁定的页面 (不能 swap/page fault)

// 按需分页 (ODP) / 隐式 MR (IMR):
//   减少注册开销 → 按需 pin/unpin

Verbs API

// 用户态: libibverbs

// 找到设备
ibv_get_device_list()

// 创建 QP
ibv_create_qp(pd, &qp_init_attr)

// Post work request (发送)
ibv_post_send(qp, &wr, &bad_wr)
// RDMA_WRITE: 直接写远端内存 (最常用)
// RDMA_READ:  直接读远端内存
// SEND:       发消息 (远端需要 pre-post RECV)

// Completion
ibv_poll_cq(cq, num_entries, &wc)  // 读 CQE

内核旁路与 Linux 集成

内核旁路对比:数据面绕开内核,连接建立仍靠内核

传统 TCP 经内核 app socket TCP/IP netdevice 网卡

RDMA 旁路内核 app verbs 用户态驱动 网卡 (完全旁路内核!)

但连接建立仍需内核:RDMA CM 走完整流程 RDMA CM(连接管理) IP 地址解析 + 路由查找 建立 RC QP

RDMA 靠 verbs 直连网卡,数据面完全绕开内核协议栈,延迟从 ~50μs 降到 ~1μs; 但连接建立阶段(RDMA CM)依然要走内核做地址解析和路由查找,不是"零内核参与"。

参考

  • 源码⁠: drivers/infiniband/core/, drivers/infiniband/hw/mlx5/, include/rdma/
  • 文档⁠: Documentation/infiniband/
  • LWN: "RDMA and the Linux kernel"

关键词: RDMA, InfiniBand, RoCE, QP, Memory Region, verbs, kernel bypass, ib_core