RDMA Memory Region (MR) 机制详解:地址转换与内存保护

RDMA Write 与 RDMA Read 是进行大量数据传输时首选的操作类型,Send 和 Receive 操作通常用于传输一些控制信息。在实际执行 RDMA 操作时,会面临一些关键的技术挑战。本文将深入介绍 Memory Region(MR,内存区域) 机制,它用于解决 RDMA 操作在实际执行过程中的地址转换和内存安全问题。


一、RDMA 操作面临的两个核心问题

1.1 问题场景回顾

先回忆一下 RDMA Write 操作的场景:

复制代码
1. 计算机1的应用程序向计算机2的内存中写入一段数据
2. 通知驱动程序给本地的 RDMA 网卡下发一个 WQE 到 SQ 中
3. WQE 中包含:
   - 源数据缓存的地址
   - 目的数据缓存的地址
   - 数据长度等信息
4. 网卡解析 WQE 后,从源数据缓存读取数据
5. 封装成数据包发送到对端网卡
6. 计算机2的网卡收到数据包后,解析出数据、长度、目的地址
7. 最后把数据写到计算机2的内存中

1.2 问题一:虚拟地址到物理地址的转换

问题描述:

层面 地址类型 说明
应用程序 虚拟地址 通过驱动程序向 WQE 中写入的地址是虚拟地址
RDMA 网卡 物理地址 网卡需要使用物理地址才能通过总线访问主机内存

为什么网卡不能使用 MMU?

复制代码
CPU 的 MMU 模块:
  - 可以通过查询操作系统建立的系统页表得到物理地址
  - 但 RDMA 网卡无法使用 MMU

RDMA 网卡无法访问系统页表的原因:
  
  1. 没有能力:
     - 系统页表是按照 MMU 能理解的格式建立的
     - 每种 CPU 体系结构的页表格式不完全相同
     - RDMA 网卡无法理解各种不同格式的页表
  
  2. 没有权限:
     - 页表是系统的核心功能
     - 为了保障操作系统的安全,不能和外设共享
     - 允许外设直接访问页表会带来严重的安全隐患

核心问题: RDMA 网卡如何才能获得缓存的物理地址?

1.3 问题二:内存访问的安全性

问题描述:

复制代码
假设网卡有能力获取缓存的物理地址:
  
  但如果应用程序恶意地或因为 bug 指定了一个非法的虚拟地址:
  
  可能的后果:
  ├─ 网卡被误导去读写其他应用程序的内存
  ├─ 网卡被误导去读写系统关键位置的内存
  └─ 网卡被误导去访问其他设备的地址空间

如何防范这种安全隐患?

1.4 解决方案:MR 机制

为了解决上述两个问题,InfiniBand 引入了 MR 机制


二、MR 的基本概念

2.1 MR 的定义

根据 InfiniBand 标准中的定义:

MR 是一个经过注册的、虚拟地址连续的、任意大小的内存区域,支持 RDMA 网卡进行本地内存访问(后者可选)。

2.2 MR 的本质

复制代码
MR 在本质上:
  - 由程序在内存中申请的一段缓存
  - 用于保存待收发的数据
  - 是一段特殊的内存

按照标准:
  1. 程序先申请一段缓存
  2. 调用 RDMA 软件框架提供的 Verbs API ibv_reg_mr 注册这段缓存
  3. 注册后,这段缓存才能被称为 MR
  4. 然后 RDMA 网卡才能访问这段缓存

2.3 MR 示意图

复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                           主机内存                                       │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌─────────────────────┐                                               │
│  │        MR 1         │  ← 经过注册的内存区域 1                        │
│  │  虚拟地址连续        │                                               │
│  │  任意大小           │                                               │
│  └─────────────────────┘                                               │
│                                                                         │
│  ┌─────────────────────┐                                               │
│  │        MR 2         │  ← 经过注册的内存区域 2                        │
│  │                     │                                               │
│  └─────────────────────┘                                               │
│                                                                         │
│  ┌─────────────────────┐                                               │
│  │        MR 3         │  ← 经过注册的内存区域 3                        │
│  │                     │                                               │
│  └─────────────────────┘                                               │
│                                                                         │
│  ... 系统中可以有很多 MR ...                                            │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

关键点:
  - MR 就是一段特殊的内存
  - 一个系统中可以有很多 MR
  - 必须先注册,网卡才能访问

2.4 术语说明

注: 为了区分操作系统建立的供 MMU 查询的页表,和 RDMA 驱动程序建立的供 RDMA 网卡查询的 MR 地址转换表,我们把前者称为 系统页表


三、MR 如何解决地址转换问题

3.1 MR 注册过程

复制代码
应用程序调用 ibv_reg_mr 注册内存:

┌─────────────────────────────────────────────────────────────────────────┐
│                           应用程序                                       │
│                              │                                          │
│                              │ 1. 申请内存缓存                          │
│                              ▼                                          │
│                     ┌─────────────────┐                                 │
│                     │   内存缓存       │                                 │
│                     │ (虚拟地址连续)   │                                 │
│                     └────────┬────────┘                                 │
│                              │                                          │
│                              │ 2. 调用 ibv_reg_mr                       │
│                              ▼                                          │
├─────────────────────────────────────────────────────────────────────────┤
│                           RDMA 驱动程序                                  │
│                              │                                          │
│                              │ 3. 查询系统页表                           │
│                              │    获取虚拟地址到物理地址的映射           │
│                              ▼                                          │
│                     ┌─────────────────┐                                 │
│                     │  MR 地址转换表   │                                 │
│                     │                 │                                 │
│                     │ 虚拟地址 → 物理地址                              │
│                     │ 0x1000   → 0x8000                               │
│                     │ 0x1004   → 0x9000  (物理页可能不连续)            │
│                     │ ...             │                                 │
│                     └────────┬────────┘                                 │
│                              │                                          │
│                              │ 4. 将转换表下发到网卡                     │
│                              ▼                                          │
├─────────────────────────────────────────────────────────────────────────┤
│                           RDMA 网卡                                      │
│                              │                                          │
│                              ▼                                          │
│                     ┌─────────────────┐                                 │
│                     │  网卡硬件        │                                 │
│                     │  MR 地址转换表   │                                 │
│                     │  (可直接查询)    │                                 │
│                     └─────────────────┘                                 │
└─────────────────────────────────────────────────────────────────────────┘

3.2 地址转换流程

复制代码
RDMA 操作时的地址转换:

1. 应用程序在 WQE 中填写虚拟地址
   └─ 例如:addr = 0x12340000

2. RDMA 网卡收到 WQE,解析出虚拟地址

3. 网卡查询自己的 MR 地址转换表
   └─ 虚拟地址 0x12340000 → 物理地址 0x87654000

4. 网卡使用物理地址进行 DMA 操作
   └─ 通过总线访问主机内存

关键点:
  - 驱动程序在注册 MR 时已经完成了地址转换表的构建
  - 网卡硬件可以直接查询自己的转换表,无需访问系统页表
  - 转换表格式由网卡硬件定义,不依赖 CPU 架构

3.3 为什么这种方式可行?

问题 传统方式的问题 MR 机制的解决方案
页表格式不同 每种 CPU 架构页表格式不同,网卡无法理解 RDMA 驱动程序负责统一处理,向网卡下发网卡能理解的格式
权限问题 系统页表是核心功能,不能和外设共享 MR 转换表由驱动程序专门为网卡创建,不涉及系统页表共享
效率问题 每次访问都要查系统页表 转换表在注册时一次性构建,网卡直接使用

四、MR 如何解决内存安全问题

4.1 安全机制概述

复制代码
MR 注册时的安全检查:

┌─────────────────────────────────────────────────────────────────────────┐
│                           应用程序                                       │
│                              │                                          │
│                              │ 调用 ibv_reg_mr                          │
│                              │ 参数:虚拟地址、长度、访问权限            │
│                              ▼                                          │
├─────────────────────────────────────────────────────────────────────────┤
│                           RDMA 驱动程序                                  │
│                              │                                          │
│                              │ 安全检查:                               │
│                              │ 1. 虚拟地址是否有效?                    │
│                              │ 2. 该应用程序是否有权限访问这段内存?    │
│                              │ 3. 内存是否被锁定(防止换页)?          │
│                              │                                          │
│                              │ 检查通过 → 注册成功                      │
│                              │ 检查失败 → 返回错误                      │
│                              ▼                                          │
│                     ┌─────────────────┐                                 │
│                     │       MR        │                                 │
│                     │  访问权限:读/写 │                                 │
│                     │  R_Key:0x1234  │  ← 访问密钥                     │
│                     └─────────────────┘                                 │
└─────────────────────────────────────────────────────────────────────────┘

4.2 R_Key 机制

R_Key(Remote Key) 是 MR 注册时生成的一个访问密钥:

复制代码
R_Key 的作用:

1. 唯一标识一个 MR

2. 访问控制:
   - 远端应用程序进行 RDMA Write/Read 时,必须提供 R_Key
   - 网卡验证 R_Key 的有效性
   - 只有持有正确 R_Key 的请求才能访问对应内存

3. 权限验证:
   - MR 可以设置访问权限(只读/只写/读写)
   - 网卡会检查操作类型是否与权限匹配

示例:
  ┌─────────────────────────────────────────────────────────────────┐
  │                        WQE 内容                                 │
  ├─────────────────────────────────────────────────────────────────┤
  │  opcode = RDMA_Write                                            │
  │  addr = 0x12340000           ← 虚拟地址                         │
  │  remote_addr = 0x11110000    ← 远端虚拟地址                     │
  │  len = 100                                                      │
  │  key = R_key = 0x1234        ← 访问密钥                         │
  └─────────────────────────────────────────────────────────────────┘
  
  远端网卡收到请求后:
  1. 根据 R_Key 找到对应的 MR
  2. 检查 R_Key 是否有效
  3. 检查 remote_addr 是否在 MR 的地址范围内
  4. 检查操作类型(Write)是否在 MR 的权限范围内
  5. 全部通过后,才执行写入操作

4.3 内存锁定(Pin Memory)

问题: 操作系统可能会将内存页换出到磁盘,导致物理地址变化。

解决方案: MR 注册时锁定内存页。

复制代码
内存锁定机制:

普通内存:
  ┌─────────────────┐
  │    虚拟内存页    │
  └────────┬────────┘
           │
           │ 可能被换出到磁盘
           ▼
  ┌─────────────────┐
  │    磁盘空间      │
  └─────────────────┘

MR 注册的内存:
  ┌─────────────────┐
  │    虚拟内存页    │
  └────────┬────────┘
           │
           │ 被锁定,不会被换出
           ▼
  ┌─────────────────┐
  │    物理内存页    │  ← 物理地址固定不变
  └─────────────────┘

关键点:
  - MR 注册时,驱动程序会锁定(pin)对应的物理内存页
  - 锁定后的内存不会被操作系统换出到磁盘
  - 物理地址保持不变,网卡可以安全地使用 MR 地址转换表

4.4 边界检查

复制代码
MR 边界检查:

应用程序注册 MR:
  - 虚拟地址:0x10000000
  - 长度:1024 字节
  - 有效范围:0x10000000 ~ 0x100003FF

远端请求访问:
  - remote_addr = 0x10000500  ← 超出 MR 范围!
  - len = 100

网卡检查:
  1. 根据 R_Key 找到 MR
  2. 检查 remote_addr (0x10000500) 是否在 MR 范围内
  3. 0x10000500 > 0x100003FF → 超出范围
  4. 拒绝访问,返回错误

结果:
  - 防止越界访问其他内存区域
  - 保护了系统的内存安全

五、MR 的完整工作流程

5.1 MR 注册流程

复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│ 第一步:应用程序申请内存                                                 │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  void *buffer = malloc(1024 * 1024);  // 申请 1MB 内存                 │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 第二步:调用 ibv_reg_mr 注册 MR                                         │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  struct ibv_mr *mr = ibv_reg_mr(                                       │
│      pd,                    // Protection Domain                       │
│      buffer,                // 虚拟地址                                │
│      1024 * 1024,           // 长度                                    │
│      IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE                  │
│  );                                                                     │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 第三步:驱动程序处理注册请求                                             │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  1. 验证应用程序对该内存的访问权限                                       │
│  2. 查询系统页表,构建虚拟地址到物理地址的映射                           │
│  3. 锁定物理内存页(防止换页)                                           │
│  4. 构建 MR 地址转换表                                                  │
│  5. 分配 R_Key                                                          │
│  6. 将 MR 地址转换表下发到网卡硬件                                       │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 第四步:返回 MR 信息给应用程序                                           │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  mr->addr      = buffer;          // 虚拟地址                          │
│  mr->length    = 1024 * 1024;     // 长度                              │
│  mr->lkey      = 0x1234;          // 本地访问密钥                       │
│  mr->rkey      = 0x5678;          // 远程访问密钥                       │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

5.2 MR 在 RDMA 操作中的使用

复制代码
RDMA Write 操作中 MR 的使用:

请求端:
┌─────────────────────────────────────────────────────────────────────────┐
│                                                                         │
│  // 准备 WQE                                                            │
│  struct ibv_send_wr wr;                                                 │
│  wr.sg_list->addr   = local_buffer;     // 本地 MR 的虚拟地址           │
│  wr.sg_list->lkey   = local_mr->lkey;   // 本地 MR 的 lkey              │
│  wr.wr.rdma.remote_addr = remote_addr;  // 远端 MR 的虚拟地址           │
│  wr.wr.rdma.rkey   = remote_mr->rkey;   // 远端 MR 的 rkey              │
│                                                                         │
│  // 网卡收到 WQE 后:                                                   │
│  // 1. 使用 lkey 查询本地 MR 地址转换表                                  │
│  // 2. 将 local_buffer 转换为物理地址                                   │
│  // 3. 通过 DMA 读取数据                                                │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    │ 网络传输
                                    ▼
响应端:
┌─────────────────────────────────────────────────────────────────────────┐
│                                                                         │
│  // 网卡收到数据包后:                                                   │
│  // 1. 从数据包中提取 remote_addr 和 rkey                               │
│  // 2. 使用 rkey 查找对应的 MR                                          │
│  // 3. 验证 rkey 有效性                                                 │
│  // 4. 验证 remote_addr 在 MR 范围内                                    │
│  // 5. 验证操作权限(是否允许远程写)                                    │
│  // 6. 查询 MR 地址转换表,得到物理地址                                  │
│  // 7. 通过 DMA 写入数据                                                │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

六、MR 与系统页表的对比

6.1 对比表

对比项 系统页表 MR 地址转换表
创建者 操作系统 RDMA 驱动程序
使用者 CPU 的 MMU RDMA 网卡硬件
格式 CPU 架构相关 网卡硬件定义
访问权限 仅内核可修改 驱动程序可修改
共享性 不能与外设共享 专门为网卡创建
内存锁定 支持换页 锁定不换页
查询时机 每次 CPU 访问内存 MR 注册时一次性构建

6.2 关系示意

复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                              主机内存                                    │
└─────────────────────────────────────────────────────────────────────────┘
         │                                    │
         │ CPU 访问                            │ RDMA 网卡访问
         ▼                                    ▼
┌─────────────────────────┐      ┌─────────────────────────┐
│       系统页表          │      │     MR 地址转换表        │
│  (CPU 架构相关格式)      │      │  (网卡硬件定义格式)       │
│                         │      │                         │
│  虚拟地址 → 物理地址     │      │  虚拟地址 → 物理地址     │
│  支持换页               │      │  内存已锁定              │
└─────────────────────────┘      └─────────────────────────┘
         │                                    │
         │ MMU 查询                            │ 网卡硬件查询
         ▼                                    ▼
┌─────────────────────────┐      ┌─────────────────────────┐
│        CPU              │      │      RDMA 网卡          │
└─────────────────────────┘      └─────────────────────────┘

关键点:
  - 两套独立的地址转换机制
  - 系统页表:通用、支持换页、CPU 使用
  - MR 转换表:专用、内存锁定、RDMA 网卡使用

七、MR 的访问权限

7.1 权限类型

复制代码
// MR 访问权限标志(来自 rdma-core)

IBV_ACCESS_LOCAL_WRITE     // 允许本地写
IBV_ACCESS_REMOTE_WRITE    // 允许远程写
IBV_ACCESS_REMOTE_READ     // 允许远程读
IBV_ACCESS_REMOTE_ATOMIC   // 允许远程原子操作
IBV_ACCESS_MW_BIND         // 允许绑定内存窗口

7.2 权限验证

复制代码
权限验证流程:

请求端发起 RDMA Write:
  ┌─────────────────────────────────────────────────────────────────┐
  │  WQE: opcode = RDMA_Write                                       │
  │       rkey = 0x5678                                             │
  └─────────────────────────────────────────────────────────────────┘
                            │
                            ▼
响应端网卡验证:
  ┌─────────────────────────────────────────────────────────────────┐
  │  1. 查找 rkey = 0x5678 对应的 MR                                 │
  │  2. 检查 MR 是否设置了 IBV_ACCESS_REMOTE_WRITE 权限              │
  │     - 如果设置了 → 允许写入                                      │
  │     - 如果未设置 → 拒绝访问,返回权限错误                        │
  └─────────────────────────────────────────────────────────────────┘

0voice · GitHub

相关推荐
c++逐梦人2 小时前
Linux进程信号
linux·服务器
徐子元竟然被占了!!2 小时前
ENSP学习-路由器
网络·学习
逸Y 仙X2 小时前
文章九:ElasticSearch索引字段常见属性
java·大数据·服务器·数据库·elasticsearch·搜索引擎
9稳2 小时前
基于plc的自动化立体仓库控制系统设计
开发语言·网络·数据库·嵌入式硬件·plc
野犬寒鸦2 小时前
JVM垃圾回收机制深度解析(G1篇)(垃圾回收过程及专业名词详解)
java·服务器·jvm·后端·面试
清水白石0082 小时前
协程不是线程:深入理解 Python async/await 运行机制
java·linux·python
va学弟2 小时前
Java 网络通信编程(7):完善视频通信
java·服务器·网络
fengpan20042 小时前
ubuntu下vscode使用串口
linux·运维·服务器
Predestination王瀞潞2 小时前
5.3.1 通信->HTTP3超文本传输协议标准(IETF RFC 9114):HTTP(HypetText Transfer Protocol)
网络协议·tcp/ip·http