RDMA入门简介
本文是对 OFA Training 第一部分的总结。
这是一份很好的学习RDMA的入门材料,从原理讲起,更容易理解。
关键术语
1. RDMA – Remote Direct Memory Acces
一种应用程序之间的通信机制
- Remote:说明通信双方处于远端
- Direct:说明通信不需要“更高权限者”的参与
- Memory:说明数据需要从应用A的虚拟地址转移到应用B的虚拟地址
2. Verbs
应用程序用来控制、执行RDMA操作的API
3. Channel Adapter - CA
允许应用程序直接进行RDMA操作的I/O设备
CA的概念中包含了硬件和软件两个部分
CA目前有三种类型
- iWARP
- InfiniBand
- RocE
4. Requester, Responder
- RDMA请求发送方可能发送一个“READ”、“WRITE”请求到RDMA接收方
- WRITE请求是将发送方写数据到接收方
- READ请求是发送方读数据到接收方
RDMA简介
回顾现有的I/O机制
- 按照冯诺依曼体系结构来看,现有的主机通常包括:CPU、MEM、IO子系统
- 所有的硬件资源被OS所管理:应用程序想要使用IO资源需要通过OS申请、访问、释放。
应用程序使用的是虚拟地址
IO设备使用的是物理地址
地址的转换完全由OS来管理
注:IO设备也可能用虚地址访存,参考IOMMU、SMMU
- 应用程序几乎所有的IO操作,都需要发起系统调用,由OS完成
- 应用程序通常IO操作包括三类:存储、网络、IPC
一种新的IO机制:Channel IO
IO Channel可以在两个应用程序间建立直接的IO通道
- OS负责创建IO通道,但OS不负责IO传输
- 逻辑上看如下图
IO通道物理结构如下图
- 一个IO通道可以在两个Channel Adapters上建立
- IO通道对上层应用提供API进行控制、传输,称为channel interface
- channel interface是运行在用户态的
消息传递
地址翻译
1. 三次地址翻译概述
远程通信需要进行三次地址翻译,如下图所示
2. 三次地址翻译实现方式
基于OS实现三次地址翻译
- OS来完成虚拟→物理/物理→虚拟地址的翻译
- OS实现的地址翻译可以保证,每个应用程序对应的虚拟地址都是独立的。
基于通道适配器CA来实现三次地址翻译
通道适配器来完成地址翻译的话则不需要OS介入,如下图所示
地址映射表保存在通道适配器CA中,但是由OS创建;OS不介入到地址翻译的过程中
3. 远端虚拟地址直接访问
一个IO通道可以暴露给应用程序A一段本机不存在的虚拟地址
- 换言之,这段虚拟地址被映射到了远端的应用程序。
- RDMA技术就是在解决:应用程序A如何直接访问远端应用程序的虚拟地址?
RDMA通信原理简介
回顾socket通信原理
- socket应用程序会将应用程序要发送的数据,从应用缓冲区拷贝到内核缓冲区中。
- OS中的TCP栈负责将内核缓冲区的字节传输到远端。
- OS中的TCP栈只负责传输字节(这里没有消息的概念),是字节流
RDMA通信架构
大概可以分为三层:软件层接口、RDMA协议层、网络传输层
软件层接口
软件层接口
- 提供一个应用程序可以访问的队列接口,用来将应用程序发来的请求保序
- 是一个面向消息的架构(区别于socket是面向字节流的)
队列接口
- 包含两种队列
- QP:等待被执行的任务队列(Queue Pair)
- CQ:已经完成的任务队列(Completion queue)
- CQ中的一个标识可能标志多个QP中的任务已完成
- 包含两种队列
Queue Pair
如下图所示
QP总是成对出现的,包含一个发送队列、一个接受队列
一个应用程序可以创建多个QP,一个QP只对应一个应用程序
Work requests 任务请求
一个 Work requests ,WR 描述了一个等待被执行的任务,可能是一个发送任务,也可能是一个接受任务
应用程序发起一个任务请求,任务请求会被保存到队列中,称为Post a WR
- Work Queue中的一个Work reqeuest称为Work Queue Element (WQE – pronounced wookie)
- completion queue entry 称为 CQEs ,pronounced cookie
Queue接口是异步的
- 应用程序发起请求后,不等待任务完成
- 一旦一个或多个任务被完成,CQ中会放入CQE来通知应用程序
QP队列中的WRE序列问题
- 一个WR(QP中的一个队列)中的所有发送请求是严格保序的
- 一个WR中的所有接受请求是严格保序的
- 发送队列和接受队列中的元素没有序列要求
- QP之间没有序列要求
QP的连接
- 一旦两个应用程序通过设备相连,两个应用程序对应的QP也就连接起来了
- 应用A向发送队列写入的WR,会发送到通道的另一端。
- 再一次强调,一个QP只能用于一个应用程序
软件层接口的使用
- 用户创建一个用来收/发消息的 Work Request
- 为了发送消息,用户使用 Post Send Request , or Post Receive Request Verbs(API) 来将这个WR填充到到某个QP的发送队列或者接受队列
RDMA协议层
RDMA协议层主要用于地址的转换
RDMA的消息种类
- SEND/RECEIVE: 进行通道IO
如下图所示
流程如下所示
- 请求方Post一个SEND WR到对应的发送队列中
- SEND WQE中描述了发送端buffer的信息,以及目的端口号DLID、目的QP号
- 相应方Post一个RECEIVE WR到对应的接受队列中
- RECEIVE WR描述了下一个接受的信息可以用的内存地址
- 接受端buffer信息一定要先于发送端信息被post
- 请求方Post一个SEND WR到对应的发送队列中
- RDMA READ/WRITE :进行远端内存操作
响应方的buffer由“虚拟地址 + RDMA Key”组成的描述符所描述
- 响应方需要将本端的buffer描述符通过SEND 消息传递给请求方
- 请求方使用收到的描述符,对远端内存进行READ/WRITE操作,之后响应方对buffer不可读写
- 直到请求方通知响应方WR/RD完成,响应方的应用程序才能读写buffer
RDMA Write
响应方的CA处理dst VA → dst PA 的地址翻译
RDMA READ
左侧是请求方,右侧是响应方
请求方的CA处理src VA到src PA的地址转换(读回的数据写入到哪里的问题)
- SEND/RECEIVE: 进行通道IO
RDMA 协议层总结
- SEND/RECEIVE 请求是一个端到端的操作
- 一个SEND操作,会消耗一个请求方QP的WQE,也会消耗一个响应方QP的WQE
- RECEIVE WQE 一定要在 SEND WQE 之前发出
- RDMA READ/WRITE 提供了应用程序可以直接访问远端内存缓冲的方法
网络传输层
- 传输层必须对上提供可靠的、面向连接的服务
- “可靠”的含义:数据必须按序交付给接收方,并且不能出现重复和错误
- 不能出现错误:如果出现错误,可靠的服务要么可以从字节序列中恢复错误(比如编码方式可以容错),要么报告给应用程序
- “连接”的含义
- 连接指的是两个主机的两队QP进行连接
Verbs 简介
Verbs API是应用程序进行RDMA消息传递的编程接口,如下图所示
可以想像成底层为两端的QP对/两端的CQ对建立了虚拟的IO通道
应用程序使用channel IO 进行通信的流程
- 打开一个HCA(Host CA)
- 创建一个Protection Domain
- 创建一个Queue Pair
- 创建一个/或一组 Completion Queue
- 注册内存区域Memory Regions
- 发起任务请求Work reqeust
- 等待CQ的完成任务通知
Verbs的含义
- Verb一次最早由InfiniBand Architecture Specification提出,大约在1999年
- 一个Verb更多地是在描述一个动作“语义”,并没有描述编程接口,也与各个OS特性无关的
- 不同厂商的RDMA实现:RoCE、IB、IWARP,均对用户提供统一的Verbs API接口
RDMA的隔离和保护机制
- Protection Domain的隔离与保护
每个PD和下列组件绑定在一起
- 一个或者多个QPs
- 一段内存区域
- 一个应用程序
PD由Verbs调用而分配出来
PD确保只有注册到该虚拟内存的QP才能访问它。
- Memory Registration
- 应用程序可以向HCA注册一段内存区域
- HCA返回这段内存的描述符
- Virtual Address
- RKEY
- LKEY
- LKEY是用来让应用程序访问这段内存的
- RKEY是用来让远端应用程序访问这段内存的(将会传给远端的调用者,此时本地是响应者)
- Channel
- 用户通过Memory Registration 方法来创建本进程绑定的WQ和CQ,
- 创建出来的通道位于本进程的虚拟地址范围内。
- 读写访问不涉及内核态切换
- channel之间的隔离依靠OS提供的进程隔离机制
- 用户通过Memory Registration 方法来创建本进程绑定的WQ和CQ,