https://zhuanlan.zhihu.com/p/164908617
1 概述
RDMA与传统以太网区别。
1.1 RDMA和DMA区别
传统网络中,左边的节点在内存用户空间中的数据,需要经过CPU拷贝到内核空间的缓冲区中,然后才可以被网卡访问,这期间数据会经过软件实现的TCP/IP协议栈,加上各层头部和校验码,比如TCP头,IP头等。网卡通过DMA拷贝内核中的数据到网卡内部的缓冲区中,进行处理后通过物理链路发送给对端。如下:

使用了RDMA技术之后,这一过程可以简单的表示成下面的示意图:

1.2 RDMA的优势
主要是一些大型互联网企业在部署和使用。涉及到它的以下几个特点:
- 0拷贝:指的是不需要在用户空间和内核空间中来回复制数据。见上面图,没走kernel。Linux等操作系统将内存划分为用户空间和内核空间,在传统的Socket通信流程中CPU需要多次把数据在内存中来回拷贝。而通过RDMA技术,我们可以直接访问远端已经注册的内存区域。
- kernel bypass:在用户层就可以把数据准备好并通知硬件准备发送和接收。避免了系统调用和上下文切换的开销。

- CPU卸载:指的是可以在远端节点CPU不参与通信的情况下(当然要持有访问远端某段内存的“钥匙”才行)对内存进行读写,这实际上是把报文封装和解析放到硬件中做了。而传统的以太网通信,双方CPU都必须参与各层报文的解析。
1.3 协议
RDMA是技术,具体到协议的话就是:IB,RoCE,iWARP。

- Infiniband 2000年由IBTA(InfiniBand Trade Association)提出的IB协议是当之无愧的核心,其规定了一整套完整的链路层到传输层(非传统OSI七层模型的传输层,而是位于其之上)规范,但是其无法兼容现有以太网,除了需要支持IB的网卡之外,企业如果想部署的话还要重新购买配套的交换设备。
- RoCE RoCE从英文全称就可以看出它是基于以太网链路层的协议,v1版本网络层仍然使用了IB规范,而v2使用了UDP+IP作为网络层,使得数据包也可以被路由。RoCE可以被认为是IB的“低成本解决方案”,将IB的报文封装成以太网包进行收发。由于RoCE v2可以使用以太网的交换设备,所以现在在企业中应用也比较多,但是相同场景下相比IB性能要有一些损失。
- iWARP 比上面可靠性高,但是大规模组网时TCP会耗费很多内存资源,性能比上面的RoCE v2和IB差。
三者的关系如下:

1.4 相关社区和应用
- github上其仓库的名字为linux-rdma,里面的用户核心代码在rdma-core。
- UCX是一个建立在RDMA等技术之上的用于数据处理和高性能计算的通信框架,RDMA是其底层核心之一。

2 Socket与RDMA
传统以太网通过对上层应用提供了Socket接口作为API,而RDMA协议栈则向上层提供了verbs接口。


RDMA通过和Socket的对比,我们可以明显看到,数据收发绕过了内核并且数据交换过程并不需要CPU参与,报文的组装和解析是由硬件完成的。
3 元素(常用缩写)
对RDMA中最重要的各种队列的概念作了简单和通俗的介绍
下面用队列que而不是栈stack的原因是:软件上在存,硬件上在取,这样能保证用户的请求顺序能正确处理,这种方式也叫“Post”。
这里的WQ和CQ是相反的。

| 缩写/全称 | RDMA 中的含义 |
|---|---|
| WQ(Work Queue) | RDMA 中的工作队列,用于提交或接收操作请求。包括 Send Queue (SQ) 和 Receive Queue (RQ)。 |
| WQE(Work Queue Element) | 工作队列中的条目,描述一次 RDMA 操作,比如发送、接收、读、写等。 |
| QP(Queue Pair) | 队列对,由一个发送队列(SQ)和一个接收队列(RQ)组成,是 RDMA 通信的基本单元。 |
| SQ(Send Queue) | QP 的一部分,保存发送请求的工作队列。 |
| RQ(Receive Queue) | QP 的一部分,保存接收请求的工作队列。 |
| SRQ(Shared Receive Queue) | 共享接收队列,可供多个 QP 使用,提高接收队列的资源利用率。(因为使用RQ的情况比使用SQ少) |
| CQ(Completion Queue) | 完成队列,用于通知应用层 RDMA 操作完成的状态信息。 |
| CQE(Completion Queue Element) | 完成队列中的元素,表示一个 RDMA 操作的完成事件。 |
| WR(Work Request) | 向 WQ 提交的工作请求,由用户创建并插入 WQ,最终转化为 WQE。 |
| WC(Work Completion) | 完成事件,由 RDMA 层生成,表示 WR 的完成结果,写入 CQ 中。 |
3.1 SQ,RQ,QP,WQE关系图

WQ就是对象,这里的SQ和RQ是它的实例。在RDMA技术中通信的基本单元是QP,而不是节点。
3.2 总图

4 操作类型
RDMA中有多种通信模型/模式,根据数据收发时CPU的参与情况,它们可以分为需要收发两端参与的双端操作和只需要发起方参与的单端操作。
双端操作:send & recv,单端操作:write & read。
4.1 send & recv
在SEND-RECV操作中,不止发送端需要下发WQE,接收端也需要下发WQE来告诉硬件收到的数据需要放到哪个地址。发送端并不知道发送的数据会放到哪里,每次发送数据,接收端都要提前准备好接收Buffer,而接收端CPU自然会感知这一过程。

4.2 WRITE
本端在准备阶段通过数据交互,获取了对端某一片可用的内存的地址和“钥匙”,相当于获得了这片远端内存的读写权限。拿到权限之后,本端就可以像访问自己的内存一样**直接对这一远端内存区域进行读写。**这个钥匙通过SEND-RECV操作来完成,因为拿到钥匙这个过程总归是要由远端内存的控制者——CPU允许的。
本端是通过虚拟地址来读写远端内存的,上层应用可以非常方便的对其进行操作。实际的虚拟地址—物理地址的转换是由RDMA网卡完成的。

- 请求端APP以WQE(WR)的形式下发一次WRITE任务。
- 请求端硬件从SQ中取出WQE,解析信息。
- 请求端网卡根据WQE中的虚拟地址,转换得到物理地址,然后从内存中拿到待发送数据,组装数据包。
- 请求端网卡将数据包通过物理链路发送给响应端网卡。
- 响应端收到数据包,解析目的虚拟地址,转换成本地物理地址,解析数据,将数据放置到指定内存区域。
- 响应端回复ACK报文给请求端。
- 请求端网卡收到ACK后,生成CQE,放置到CQ中。
- 请求端APP取得任务完成信息。
4.3 READ
**“读”这个动作所请求的数据,是在对端回复的报文中携带的。**其他一致。
5 服务类型(没太明白)
就像TCP/IP协议栈传输层的UDP和TCP一样,RDMA技术也规定了在不同场景下的服务类型,不同的服务类型在可靠性和速率上各有侧重。
RDMA的基本通信单元是QP,而基于QP的通信模型有很多种,这就是服务类型。这个服务类型用可靠和连接来描述;
确定是不是可靠:
- 应答机制,A怎样才能知道B收到了呢,自然是B回复一个“我收到了”消息给A。在通信领域我们一般称这个回复为应答包或者ACK(Acknowledge),也可以一次回复多个包的ACK。
- 发端会对Header和Payload(有效载荷,也就是真正要收发的数据)通过一定的算法得到一个校验值放到数据包的末尾。对端收到数据包后,也会用相同的算法计算出校验值,然后与数据包中的校验值比对,如果不一致,说明数据中包含错误就丢掉
- 保证先被发送到物理链路上的数据包一定要先于后发送的数据包被接收方收到。IB协议中有PSN(Packet Sequence Number,包序号)的概念,即每个包都有一个递增的编号。PSN可以用来检测是否丢包,比如收端收到了1,但是在没收到2的情况下就收到了3,那么其就会认为传输过程中发生了错误,之后会回复一个NAK给发端,让其重发丢失的包。
确定是不是连接:
- 每个QP都和另一个远端节点相关联。在这种情况下,**QP Context(QPC)**中包含有远端节点的QP信息。可能包括队列的深度,队列的编号等等;连接的维护是通过QPC里面的记录,如果A的QP2想断开与B的QP7的“连接”然后与其他QP相“连接”,只需要修改QPC就可以了。两个节点在建立连接的过程中,会交换稍后用于数据交互的QP Number,然后分别记录在QPC中。
- 数据报(Datagram)与连接相反,只要发端到收端物理上是可以到达的,那么我就可能从任何路径发给任意的收端节点。
两个维度两两组合就形成了IB的四种基本服务类型:

RC和UD是应用最多也是最基础的两种服务类型,我们可以将他们分别类比成TCP/IP协议栈传输层的TCP和UDP。
6 Memory Region
网络通信的本质是数据在存储介质中的迁移,RDMA通过MR来对内存进行管理。MR就是一片特殊的内存区域。
APP提供虚拟地址(VA),经过MMU的转换的到物理地址(PA),为了防止恶意指定非法VA,IB协议提出MR概念。
RDMA软件层在内存中规划出的一片区域,用于存放收发的数据。IB协议中,用户在申请完用于存放数据的内存区域之后,都需要通过调用IB框架提供的API注册MR,才能让RDMA网卡访问这片内存区域。

RDMA硬件被称为HCA(Host Channel Adapter, 宿主通道适配器),IB协议中对其的定义是“处理器和I/O单元中能够产生和消耗数据包的IB设备”,为了与协议保持一致,我们在包括本文及之后的文章中都称硬件部分为HCA。
注册MR会产生两把钥匙,Local Key和Remote Key。这一对序列用于保障本端和远端内存区域的访问权限。本端和远端在进行真正的RDMA通信前,会先建立一条链路(socket或者CM),通过这个链路交换必须的信息(VA,Key,QPN),这个过程叫“建链”和“握手”。
注册MR之后会Pin住这块内存(锁页,就是操作系统觉得不用的内存内容就保存到硬盘去,要用的时候再搬回来),不让他去把暂时不用的内存保存在硬盘。因为,如果换页了,会导致VA-PA的映射关系改变。
7 Protection Domain(PD)
为了隔离各种RDMA资源,用PD将相关的软件资源“圈”到一起,各个保护域之间的资源无法相互访问。
一般情况下,MR的虚拟地址VA和秘钥R_Key是很难猜到的,已经可以保证一定的安全性了。但是为了更好的保护内存中的数据,把各种资源的权限做进一步的隔离和划分,又在每个节点中定义PD,如下图所示:

8 Address Handle
地址句柄,在UD等服务类型中,本端通过使用AH来指定对端节点。
假设A节点的某个QP要跟B节点的某个QP交换信息,除了要知道B节点的QP序号——QPN之外,还需要什么信息?要知道,QPN是每个节点独立维护的序号,不是整个网络中唯一的。比如A的QP 3要跟B的QP 5通信,网络中可不止一个QP5,可能有很多个节点都有自己的QP 5。所以我们自然可以想到,还需要找到让每个节点都有一个独立的标识。
传统TCP-IP协议栈中是IP地址表示网络层的每个节点。IB协议中是GID(Global Identifier,全局ID),128bits序列。
8.1 AH是什么
A是一组用于找到某个远端节点的信息的集合,在IB协议中,地址指的是GID、端口号等等信息;H类似指向某个对象的指针。
IB协议中有四种基本服务类型——RC、UD、RD和UC,其中最常用的是RC和UD。RC的特点是两个节点的QP之间会建立可靠的连接,一旦建立连接关系便不容易改变,对端的信息是创建QP的时候储存在QP Context中的;
UD的QP之间没有连接关系,想发给谁则在WQE中填好对端的地址信息即可。但不是用户直接填,而是提前准备地址薄,每次通过一个索引找到对端节点的地址信息。这个索引就是AH。
每次UD服务类型的通信之前,用户都要用IB给的API为每个可能的对端节点创建一个AH,然后这些AH放到一个安全区域,并返回一个Handle(指针/句柄)给用户。用户真下发WR的时候就把这个Handle传递进来。例如下图的A收到用户的任务(用本端QP4与B节点的QP3进行数据交换)。

8.2 AH作用
- UD无连接的特点,user就可以直接用WR指定目的地。user随意写地址信息,硬件就会真去执行,因此用来保证目的地址可用,提高效率。
- 用户创建AH时,只需要传递gid、端口号、静态速率等信息,而其他通信所需的地址信息(主要是MAC地址)是内核驱动通过查询系统邻居表等方式解析到的,底层没有必要暴露这些额外的信息给用户层。
- 可以使用PD对目的地址进行管理,除了QP,MR之外,AH也由PD来进行资源划分。
9 QP
最关键的概念,是软件给硬件下命令的媒介。
QP是que,按顺序存储WQE,WQE里面包含从哪里取多少数据给哪个目的地。

每个QP之间独立,可以作为用户独占的资源,一个用户可以使用多个QP。QP的服务类型还是那四种,RC,UD,RD和UC。所有源的QP和目标QP必须是同一类型。
- 硬件上,QP是一段包含着若干个WQE的存储空间,IB网卡会从这段空间中读取WQE的内容,并按照用户的期望去内存中存取数据。至于这个存储空间是内存空间还是IB网卡的片内存储空间,IB协议并未做出限制,每个厂商有各自的实现
- 软件上,QP是一个由IB网卡的驱动程序所维护的数据结构,其中包含QP的地址指针以及一些相关的软件属性