0
点赞
收藏
分享

微信扫一扫

【RDMA】RDMA编程入门


一、前言


本文所讲述的主要是IBoE的RDMA编程,主要是ROCE、iWrap,与IB可能略有不同。

二、基本概念

1、队列和队列成员

关键词:点对点通信、QP(SQ+RQ)、CQ、*QE

RDMA提供了基于消息队列的点对点通信,每个应用都可以直接获取自己的消息,无需OS和协议栈的介入。

【RDMA】RDMA编程入门_封装

队列:QP (Queue Pairs) 和CQ

RDMA提供了基于消息队列的点对点通信,当应用需要通信时,就会创建一条Channel连接,每条Channel的两端各有一对队列(Send Queue(SQ)和Receive Queue(RQ)),合称Queue Pairs(QP),除此之外,两端还需要一个 完成队列-Complete Queue(CQ),CQ用来存放 发送和接收请求处理完成的通知。

队列成员:SQE、RQE、CQE等*QE

队列里面的成员叫xxE,SQ里面的成员叫SQE,RQ里面的叫RQE,CQ里面的就是CQE……

而发送队列SQ和接收队列RQ,统称工作队列WQ (work Queue),所以里面单元又叫WQE;

SR(发送请求)和RR(接收请求)都是WR=工作请求;

每当网卡发送or接收完成一个请求,会在CQ产生一个CQE,知会用户消息已经被处理完。

总结

SQ:发送队列,SQ中的单元叫SQE;

RQ:接收队列,RQ中的单元叫RQE;

SQ和RQ都是WQ,就像男人和女人都叫人,WQ中的单元叫WQE;

SR(发送请求)和RR(接收请求)都是WR=工作请求;

QP=SQ+RQ

CQ:完成队列,CQ中的单元叫CQE;

【RDMA】RDMA编程入门_内存地址_02

2、传输模式

简介

RDMA 单边和双边两种传输模式。

SEND/RECEIVE:

是双边操作,每一次数据传输都需要双边参与。

READ和WRITE :

是单边操作,除了第一次握手(获得对端的内存地址),后续的数据传输,单端直接DMA读写对端的内存。

第一次握手获得对端接收数据的内存地址后,本端明确信息的源和目的地址,数据的读或存都通过远端的DMA在RNIC与应用buffer之间完成,再由远端RNIC封装成消息返回到本端。对端的CPU毫无知觉。(所以WRITE完成后,一般要再发一个消息去通知对端:我已经完成一次操作了,去查看CQ队列吧。然后对端就会去读CQ队列,拿出CQE解析或者本地把数据写到哪里了,它再去处理数据)

在实际中,SEND/RECEIVE多用于连接控制类报文,而数据报文多是通过READ/WRITE来完成的。

双边

对于双边操作为例,A向B发送数据的流程如下:

首先,A和B都要创建并初始化好各自的QP,CQ

A 向SQ中放入一个发送请求(SQE),SQE描述指向一个等待被发送的数据的buffer地址 S_addr;

对于B,要提前向RQ中放入N个接收请求(RQE),RQE描述指向一块用于存储数据的buffer地址R_addr。

【RDMA】RDMA编程入门_大数据_03

A的RNIC异步从A的SQ中读取SQE(WQE),读到刚才放入的SQ,解析到这是一个SEND消息,从S_addr中将数据直接DMA到B。数据流到达B的RNIC后,B从RQ中消耗掉一个RQE(WQE),从RQE中解析出存数据的地址R_addr,并把数据直接存储R_addr。

AB通信完成后,A的CQ中会产生一个完成消息CQE表示发送完成。与此同时,B的CQ中也会产生一个完成CQE消息表示接收完成。即每个WQ中WQE的处理完成都会产生一个CQE。

双边操作与传统网络的底层buffer pool类似,收发双方的参与过程并无差别,区别在零拷贝、kernel bypass。

对于RDMA,这是一种复杂的消息传输模式,多用于传输短的控制消息。

单边

以WRITE为例:

【RDMA】RDMA编程入门_封装_04

 

首先,A和B都要创建并初始化好各自的QP,CQ。

双方握手交换信息。(A的buffer地址VA告知了B,B的buffer地址VB告知了A)

A把内存地址VA,key封装到专用的报文传送到B,这相当于A把数据buffer的操作权交给了B。

B把内存地址VB,key封装到专用的报文传送到A,这相当于B把数据buffer的操作权交给了A。

A要向B“发送”数据:

A 向SQ中放入一个发送请求(SQE),SQE描述指向一个等待被发送的数据的buffer地址 S_addr;

A的RNIC异步从A的SQ中读取SQE(WQE),读到刚才放入的SQ,解析到这是一个WRITE消息,从S_addr中将数据直接DMA到B的内存地址VB(范围内的某个地址VB+xx)。数据流到达B的RNIC后,B从A的SQE中解析出存数据的地址VB+xx,并把数据直接存储VB+xx。

AB通信完成后,A的CQ中会产生一个完成消息CQE表示发送完成。

与此同时,B的CQ中是否也要产生CQE,取决于A发过来的WR中设定的条件(又是为了减少中断。A可能想发多个消息合并为一个CQ)。

这个过程A、B两端不需要任何软件(CPU\内核)参与,只有两个网卡“悄咪咪”的完成了将A的数据存储到B的VB虚拟地址。

3、编程接口(verbs API)

Verbs API

由OpenFabrics推动实现的一组RDMA应用编程接口(API)。地位相当于以太网编程的socket接口。传统以太网的用户,基于Socket API来编写应用程序;而RDMA的用户,基于Verbs API来编写应用程序。

Verbs API是RDMA最基本的软件接口,业界的RDMA应用,要么直接基于这组API编写,要么基于在Verbs API上又封装了一层接口的各种中间件编写。(如rdma_cm)

Verbs api 分为用户态Verbs接口和内核态Verbs接口,分别用于用户态和内核态的RDMA应用。 对于Linux系统来说,由rdma-core和内核中的RDMA子系统(如intel的irdma)提供。




RDMAC(RDMA Consortium)和IBTA(InfiniBand Trade Association)主导了RDMA,RDMAC是IETF的一个补充,它主要定义的是iWRAP和iSER,IBTA是infiniband的全部标准制定者,并补充了RoCE v1 v2的标准化。

IBTA 定义了RDMA传输过程中应具备的特性行为,但没有规定Verbs的具体接口和数据结构原型。这部分工作由OFA(Open Fabric Alliance)组织来完成,OFA提供了RDMA传输的一系列Verbs API。

OFA开发出了OFED(Open Fabric Enterprise Distribution)协议栈,支持多种RDMA传输层协议。

OFED中除了提供向下与RNIC基本的队列消息服务,向上还提供了ULP(Upper Layer Protocols),通过ULPs,上层应用不需要直接到Verbs API对接,而是借助于ULP与应用对接,常见的应用不需要做修改,就可以跑在RDMA传输层上。<------------------ULP实现socket的api?

举报

相关推荐

0 条评论