A local-area RDMA network is usually referred to as a fabric. 所谓Fabric,就是支持RDMA的局域网(LAN)。
A channel adapter is the hardware component that connects a system to the fabric. CA是Channel Adapter(通道适配器)的缩写。那么,CA就是将系统连接到Fabric的硬件组件。 在IBTA中,一个CA就是IB子网中的一个终端结点(End Node)。分为两种类型,一种是HCA, 另一种叫做TCA, 它们合称为xCA。其中, HCA(Host Channel Adapter)是支持"verbs"接口的CA, TCA(Target Channel Adapter)可以理解为"weak CA", 不需要像HCA一样支持很多功能。 而在IEEE/IETF中,CA的概念被实体化为RNIC(RDMA Network Interface Card), iWARP就把一个CA称之为一个RNIC。简言之,在IBTA阵营中,CA即HCA或TCA; 而在iWARP阵营中,CA就是RNIC。 总之,无论是HCA、 TCA还是RNIC,它们都是CA, 它们的基本功能本质上都是生产或消费数据包(packet)
Verbs直译过来是“动词”的意思,它在RDMA领域中有两种含义:
1) 由IB规范所描述的一组抽象定义
规定了各厂商的软硬件在各种Verbs下应该执行的动作或者表现出的行为,IB规范并未规定如何编程实现这些Verbs,在这种含义下,Verbs是与操作系统无关的。举个例子,IB规范要求所有RDMA设备必须支持Create QP的行为(IB 规范11.2.5.1):
描述:
为指定的设备创建一个QP。
用户必须指定一组用于初始化QP的属性。
如果创建QP所需的属性有非法值或者缺失,那么应该返回错误,该QP不会被创建;如果成功, 那么返回该QP的指针和QPN。
……
输入:
设备指针;
SQ关联到的CQ;
RQ关联到的CQ,如果是XRC的INI QP,则可以不携带此参数;
……
输出:
新创建的QP的指针;
QP Number;
SQ的最大WR容量。
……
可以看出IB规范中的Verbs是对一个概念进行定义,讲的是“需要支持什么,但具体怎么实现我不做规定”。
2) 由OpenFabrics推动实现的一组RDMA应用编程接口(API)
既然是API,那么必然和运行的操作系统相关。Verbs API有Linux版本以及Windows版本(Windows版很久没有更新了)。
指开源RDMA用户态软件协议栈,包含用户态框架、各厂商用户态驱动、API帮助手册以及开发自测试工具等。rdma-core在github上维护https://github.com/linux-rdma/rdma-core,我们的用户态Verbs API实际上就是它实现的。
指开源的Linux内核中的RDMA子系统,包含RDMA内核框架及各厂商的驱动。RDMA子系统跟随Linux维护,是内核的的一部分。一方面提供内核态的Verbs API,一方面负责对接用户态的接口。
全称为OpenFabrics Enterprise Distribution,是一个开源软件包集合,其中包含内核框架和驱动、用户框架和驱动、以及各种中间件、测试工具和API文档。
开源OFED由OFA组织负责开发、发布和维护,它会定期从rdma-core和内核的RDMA子系统取软件版本,并对各商用OS发行版进行适配。除了协议栈和驱动外,还包含了perftest等测试工具。
(源码仓:https://github.com/linux-rdma/)下图为OFA给出的OFED的概览:
除了开源OFED之外,各厂商也会提供定制版本的OFED软件包,比如华为的HW_OFED和Mellanox的MLNX_OFED。这些定制版本基于开源OFED开发,由厂商自己测试和维护,会在开源软件包基础上提供私有的增强特性,并附上自己的配置、测试工具等。
以上三者是包含关系。无论是用户态还是内核态,整个RDMA社区非常活跃,框架几乎每天都在变动,都是平均每两个月一个版本。而OFED会定期从两个社区中取得代码,进行功能和兼容性测试后发布版本,时间跨度较大,以年为单位计
一个QP只和一个另外的QP相连。消息通过一个QP的发送队列可靠地传输到另一个QP的接收队列。数据包按序交付。RC连接很类似于TCP连接。
一个QP只和一个另外的QP相连。连接是不可靠的,所以数据包有可能会丢失。传输层不会出错的消息进行重传,错误处理必须由高层的协议来进行。
一个QP可以和其它任意的UD QP进行数据传输和单包数据的接收。不保证按序性和交付性。交付的数据包可能被接收端丢弃。支持多播消息(一对多)。连接很类似于UDP连接。
SR定义了数据的发送量、从哪里、发送方式、是否通过RDMA、到哪里。
RR定义用来放置通过非RDMA操作接收到的数据的缓冲区。如没有定义缓冲区,并且有个传输者 尝试执行一个发送操作或者一个带立即数的RDMA写操作,那么接收者将会发出接收未就绪的错误(RNR)。
内存窗口使应用程序对来自远程的对本地的内存访问有更灵活的控制。内存窗口(MW)作用于以下应用场景:
• 想动态地授予和收回已注册缓冲区的远程访问权限,这种方式相比较与将缓冲区取消注册之后 再注册或者重注册,有些更低的性能损耗代价。
• 想为不同的远程代理授予不同的远程访问权限,或者在一个已注册的缓冲区中的不同范围内授予 那些权限。
内存窗口和内存注册之前的关联操作称为绑定。不同的MW可以作用于同一个MR(即使有着不同的访问权限)。
地址向量用来描述本地节点到远程节点的路由。在每个UC/RC的QP中,都有一个地址向量存在于QP的上下文中。在UD的QP中,每个提交的发送请求(SR)中都应该定义地址向量。
一种集合,它的内部元素只能与集合内部的其它元素相互作用。这些元素可以是AH,QP,MR和SRQ。保护域用来队列对(QP)与内存注册和内存窗口想关联,这是一种授权和管理网络适配器对主机系统 内存的访问。PD也用来将基于不可靠数据报(UD)的QP关联到地址处理(AH),这是一种对UD目的端的访问控制。
网络适配器可能会发送异步事件来通知子网管理器(SW)系统中发生的事件。有两种异步事件:
- 附属事件:在私有对象(CQ,QP,SRQ)中发生的事件。这些事件会被发送到特定的进程。
- 非附属事件:在全局对象(网络适配器,端口错误)中发生的事件。这些事件会被发送到所有进程 。
用分散聚合元素来分散和聚合数据。这些元素包括:地址:本地数据缓冲区的地址,缓冲区是数据聚合的终点或者是数据分散的源头。 大小:数据的大小会写到这个地址或者从这个地址读取。 L_key:注册到这个缓冲区的MR的本地标志。
轮询CQ中的完成信息是为了获取已提交的WR(发送或者接收)的详细信息。如果我们在WR中发现一个异常状态的完成,接下来的完成都会异常(同时WQ会被移至错误状态)。每个没有完成(被轮询到)的WR都属于待处理状态。只有在WR完成之后,发送/接收缓冲区才可能被使用/再使用/释放。应该经常检测完成状态。当一个CQE被轮询,那么它就被从CQ中移除。轮询通过 ibv_poll_cq 操作来实现。
关于队列的相关概念可参考RDMA技术详解——RDMA核心概念