【RDMA】23. RDMA之基于CM API的QP间建链--未消化

【RDMA】RDMA 学习资料总目录_bandaoyu的博客-CSDN博客SavirRDMA 分享1. RDMA概述https://blog.csdn.net/bandaoyu/article/details/112859853https://zhuanlan.zhihu.com/p/1388747382. 比较基于Socket与RDMA的通信https://blog.csdn.net/bandaoyu/article/details/1128613993. RDMA基本元素和编程基础https://blog.csdn.net/bandaoyu/article/de.

https://blog.csdn.net/bandaoyu/article/details/120485737

作者:Savir
链接:https://zhuanlan.zhihu.com/p/494826608

原创文章,欢迎非商业转载及引用,转载及引用请注明出处。

写在前面:写专栏以来收到了不少读者的提问,其中不乏角度刁钻以及有深度的问题,自己在为大家解答疑惑的过程中也学习到了很多,对我来说已经有相当大的收益了。付费咨询完全看缘分,咱也不指着这个吃饭,大家的问题无论通过何种渠道提出我都会认真解答。另外最近发现知乎有莫名其妙吞评论的现象,遇到了几次我自己能看到,别人看不到的情况。大家的疑问我都会在一周内回复,如未收到回复请私信我。

我们在前面的文章“RDMA之基于Socket API的QP间建链”中介绍了RDMA Queue Pair间基于Socket API的建链方式。Socket API学习成本低,使用也很方便,但是对于使用Infiniband协议的节点来说,这是一种“带外”的建链方式。所谓“带外”,指的区别于数据传输通道的另外一条传输通道。用人话讲,就是使用Infiniband协议的节点,需要TCP/IP协议的支持,才能使用Socket进行建链。这就要求节点使用的Infiniband网卡支持TCP/IP,或者部署有另外一块传统以太网卡。

那么有没有Infiniband协议的网卡可以直接使用的QP间建链方式呢?有,那就是大名鼎鼎的CM。CM是RDMA技术中专门用来在QP之间建立连接的机制,它有一套专属的报文格式、交互流程和用户接口。

之前有很多读者都问过关于CM的问题,标准文档比较晦涩,网上资料也比较少。而在本文中,我将对CM进行一次全方位科普。介绍其概念、目的、使用场景、交互流程以及实现原理,关于报文格式、编程方法等更多细节,请读者期待后续的文章。

概述

CM这一缩写有多重含义,它既可以指协议,也可以指RDMA网络中的一个管理角色,还可以指编程接口(API)。

通信管理协议

CM在作为协议时的全称为Communication Management Protocol,即通信管理协议。它指的是一种建立于Infiniband/RoCE协议基础之上的建链方式。

类似于TCP协议的“三次握手”,CM协议也是通过报文的多次往返来建立连接的,同时它也规定了断链的方式。

通信管理器

CM作为Infiniband/RoCE通信系统中的角色时,全称为Communication Manager,即通信管理器。这是一个比较抽象的概念,它的作用是建立和维护两个节点间的连接。虽然抽象,但是它是有“实体”的,RDMA软件协议栈中实现了CM管理器的功能

CM编程接口

CM作为Infiniband/RoCE/iWARP的用户编程接口时,全称也是Communication Manager,即通信管理接口。CM接口之于CM协议,就如Socket接口之于TCP协议,其调用流程也和Socket非常相似,我们也可以说,CM API是基于RDMA而非传统以太网实现的类Socket接口。

我们来总结一下,上面几个概念的关系是:用户通过调用CM编程接口,控制CM通信管理器发出和接收CM协议的报文。它们的关系如下图所示:

【RDMA】23. RDMA之基于CM API的QP间建链--未消化_第1张图片

CM相关概念间的关系

它们经常被当成一个整体提及,即使单指其中一项时也比较容易识别,因此本文的剩余部分中,我不会特别区分这几个概念。


为什么需要CM

最主要的原因我其实已经在本文的最开始做出了解释——因为Infiniband协议没有Socket这种通道来在双方交换业务数据前传递必要的信息,比如QPN、Virtual Address和Remote Key等等。它需要一种不依赖于以太网的QP间建联方式,所以会有CM协议和通信管理器的存在。

建链作为一个由用户发起和中止的动作,自然也需要用户的编程接口来对其进行控制,因此就需要定制出CM API。

CM诞生于RoCE之前。RoCE v1和v2协议中都使用了Infiniband协议的传输层,而CM是基于Infiniband传输层实现的,因此RoCE v1/v2自产生开始就天然支持CM建链。而又因为RoCE底层是基于以太网的,一般支持RoCE v2的网卡都会支持TCP/IP协议,因此大多数RoCE网卡都可以支持Socket和CM两种建链方式。

iWARP的情况比较特殊。iWARP自成体系,它通过IETF的RFC 5044和RFC 6581(详情见“iWARP”一文)对于建链方式做出了规定。iWARP的做法是规定了一套基于在TCP之上的MPA层的交互流程,与CM协议毫不相关。并且由于在TCP层上面加了一层,往往由各个厂商自己在驱动程序中进行差异化实现,所以也无法使用标准Socket API

iWARP后来逐渐和Infiniband/RoCE统一了软件接口和软件栈,这其中就包括CM API。它虽然使用着CM API,但是底层还是按照其RFC中的规定所实现的。


协议分层

我们在之前的文章“Verbs”中讲解过Verbs接口,它作为目前最主流的RDMA API,对用户隐藏了下层协议的细节。从Verbs API看RDMA各个协议的分层关系是下图这个样子:

【RDMA】23. RDMA之基于CM API的QP间建链--未消化_第2张图片

Verbs API视角的协议层次

各种协议的分层差异我们在专栏之前的文章中有涉及过,就不在本文展开了。注意对于一般的RDMA网卡来说,上图中Verbs API下面的所有协议层次,都是硬件实现的

CM API的目的跟Verbs一样,它定义了一套Infiniband/RoCE/iWARP协议通用的建链接口,对用户隐藏了底层差异。从CM API看,协议分层是下图这样:

【RDMA】23. RDMA之基于CM API的QP间建链--未消化_第3张图片

CM API视角的协议层次

除了分层关系,跟上面Verbs的协议分层图另一个比较大的差异是,对于RoCE/Infiniband来说,CM和MAD层是软件实现的;对于iWARP来说,建链时使用的MPA及以下各层,也是软件实现的

下面我们来简单讲一下上图中还没有涉及过的几个层次:

MPA层

MPA层的全称是Marker PDU Aligned framing,它是iWARP协议族的最底层,向下基于TCP层,向上为DDP层提供服务。我们在“MPA”一文中对它的功能做了详细的介绍,其中就包括建链部分的报文和流程分析,感兴趣的读者可以去继续了解。

MAD层

MAD全称为Management Datagram,即管理数据报。我们在“RDMA基本服务类型”一文中讲过,数据报是面向连接的反义词,就是通信双方不需要建立连接。我们很容易联想到UD服务类型的全称是不可靠数据报,其实MAD层就是基于IB传输层的UD服务类型实现的。也就是说,它在UD服务类型的报文的基础上,利用其Payload部分又实现了一层协议。

协议视角

MAD层通常不直接向用户提供功能,它主要作为中间层向上支持GS(General Services)和SM(Subnet Management)两种服务。SM只用于Infiniband网络,我也不了解,咱们暂且不提。General Service包括性能管理、设备管理、应用管理以及本文的主角——CM连接管理。

之前在“Queue Pair”一文中我曾经提到过两个特殊的保留QP——QP0以及QP1。这两个QP之所以特殊,是因为它们是专门用于收发MAD层管理报文的。QP0和QP1由内核协议栈创建,无法被用户直接使用。其在软件协议栈中的QP类型分别为SMI(Subnet Management Interface)和GSI(General Services Interface),但是实际上就是UD类型的QP,只是因为其特殊的权限,所以取了两个专有的类型名。

我们来思考一下,为什么MAD使用的是UD,而不是RC呢?UD服务类型最大的特点便是可以把报文发送给任意节点,也可以接收来自任何节点的报文(当然也要保证合法性)。对于CM这种需要试探性地收发、收发频率低、无需保证可靠性的报文,UD自然称为了首选。所有的节点只需要建立一个专门用于CM的UD(GSI) QP,就可以和所有其他任意节点间进行建链的交互。试想如果用RC来实现,每一对CM连接都需要独立的RC QP,这在复杂组网情况下将消耗大量的内存资源,而且两端也很难协商到底用哪个QPN收发MAD报文。

我们在“Socket建链”一文中讲到,UD QP之间通信,至少要知道对端的QPN和Queue Key,只有对端校验通过后才会接收我们的报文。MAD如何解决这个问题呢?非常简单,所有的GSI QP都必须使用相同的QPN,即QP1;以及相同的Queue Key——特殊的值0x8001_0000。而最高位为1的Queue Key都是特权Key,普通的用户无法使用,这也就保证了CM只能由内核态协议栈来管理。

软件视角

MAD层除了处理自己这一层的报文之外,还对Infiniband/RoCE协议的CM层提供了RDMA资源上的支持,包括PD、MR、QP、CQ等等,是CM层的基础。

MAD层的细节我们不在本文展开,以后有空给大家讲。

CM层

协议视角

顾名思义,这一层自然指的是CM协议,细节我们在后面的小节介绍。

软件视角

软件层面的CM层包含两个功能,一方面负责为用户提供类似Verbs API的CM API,并处理用户对API的调用。另一方面根据网卡使用的协议来组装或者解析报文。

发送方向上,如果是RoCE/Infiniband协议,则CM层会负责组装CM协议报文,并下送给MAD层做进一步处理,最后通过GSI QP发送建链报文;如果是iWARP协议,则它会调用各个厂商注册的回调函数组装MPA层的报文,厂商的驱动最终会调用Socket接口,由内核协议栈继续组装TCP/IP层的报文并发送。

接收方向上,CM层也负责使用RoCE/Infiniband时MAD+CM协议的报文解析,或者在使用iWARP协议时,调用网卡驱动注册的回调函数对MPA报文进行解析。

我们以一个基于RoCE v2的CM报文为例,它的结构如下图所示:

CM报文层次示意图


CM协议

下面我们介绍用于Infiniband/RoCE设备的CM协议。CM协议中,RC和UD服务类型使用的是不同的报文和交互流程,主要差异点在于,因为RC是面向连接的,所以其建链过程中也必须经历建立连接——数据交互——断开连接的过程;而UD无连接,所以双方在获得必要的信息后,就可以进行数据交互了,最后也不用断开连接。

RC QP建链

RC QP的CM建链和断链流程和TCP非常相似,如下图所示,建链是一个“三次握手”的流程:

【RDMA】23. RDMA之基于CM API的QP间建链--未消化_第4张图片

RC QP间的CM建链流程

RC QP的CM建链报文交互(参考自IB Specification Release 1.4 Figure 132)

  1. 首先Client端要发起一个REQ(Request)消息,表示一个连接请求,消息的报文中携带有连接参数,比如本端要连接的QP的QPN(这个QP是在CM建链流程中通过CM API创建的,下文会介绍)、起始PSN、重传次数上限等等。另外也可以跟iWARP的MPA建链一样携带一些自定义的Private Data,用于满足用户的定制化需求。
  2. Server端在Client端发起连接请求前就一直处于监听状态,当它监听到连接请求后,CM层会对连接参数进行校验和记录,而Private Data会被上送给用户进行校验。校验通过后,Server端会发送REP(Reply)消息,表示接受之前的连接请求,并且在消息报文中携带自己的连接参数——包括QPN、起始PSN等等。REP报文也可以携带自定义的Private Data。
  3. Client端收到REP消息后,将对其中的内容进行校验和记录,然后发送一个RTU(Ready To Use)消息,表示同意你的参数,可以利用双方约定好的QP进行数据交互了。

如上图所示,Client端在发出RTU消息之后就可以发送数据了,而Server端在接收到RTU消息后才可以发送数据。

上述过程中,如果任意一个校验过程中检出了错误,则会回复给对端一个REJ(Reject)消息,终止本次连接流程,消息报文中会携带拒绝连接的原因。

RC QP断链

RC QP的断链一般是一个“四次挥手“的过程。关于断链的过程,IB规范并没有规定两端谁先发起、后发的一方是否要先回复Reply后再发送Request等细节,下图中的例子只是一种可能的情况:

【RDMA】23. RDMA之基于CM API的QP间建链--未消化_第5张图片

RC QP间的CM断链流程

  1. 首先Client端发送DREQ(Disconnect Request)消息,表示自己想要断开某个连接,消息中携带着指定连接的ID以及QPN等信息。这个过程也可以携带Private Data,用于定制化功能。
  2. Server端收到DREQ消息并校验通过后,回复一个DREP(Disconnect Reply)消息,表示同意断链请求。
  3. Server端发送DREQ消息,同1。
  4. Client端收到DREQ消息,校验通过后回复DREP,同2。

上图中Client端和Server端收到对端回复的DREP消息后,就可以销毁跟对端有关的CM软硬件资源了。

UD QP建链

UD QP的CM建链流程相对于RC要简单,主要原因自然是UD服务类型不用建立连接,也不需要保证可靠性,对端收不收的到无所谓。由上层应用的逻辑保证建链的完成,比如Client端可以在一定时间内没收到Reply就重发Request。这个过程下图所示:

【RDMA】23. RDMA之基于CM API的QP间建链--未消化_第6张图片

UD QP间的CM建链流程

首先需要解释一个名词——SIDR,全称为Service ID Resolution Protocol,大家别被又一个Protocol吓到,它的过程非常简单:

  1. Client端发送请求消息SIDR_REQ(SIDR Request),其中会携带一个Service ID字段,表明它需要Server端提供的服务。这个过程中也可以携带Private Data用于定制化实现。
  2. Server端收到SIDR_REQ消息后,会对请求进行校验。校验通过后,在回复消息SIDR_REP(SIDR Reply)中会携带一个和Service ID对应的可用QP的QPN以及Queue Key,此后Client就可以以它为目的QP发送数据给Server。这个过程中也可以携带Private Data。

Client端收到Server发出的回复后,就可以从报文中获取对端可以用来接收消息的QPN和Q_Key了,至此SIDR的标准交互流程就结束了。至于Service ID和QPN的对应关系,IB规范中并没有做出规定,这个可以由用户应用程序自行决定。

细心的读者可能会发现,这个流程中Server端好像不知道Client端的QPN。

这是因为作为被动一方的Server端并不一定要知道Client端的QPN。如果Server端也有向Client端发送消息的需求的话,才需要通过其他方式获得Client端的信息。具体的实现由用户决定,比如Client端可以在首个Send报文的Payload部分就携带本端的QPN、Q_Key等信息;也可以通过在Send with immediate消息中携带立即数,这个立即数即为Client端的QPN或者Q_Key。

CM报文交互的内容很多,我们不在本文中展开,以后有时间再单独讲。感兴趣的读者可以结合文末的实验和IB Specification的第12章自行学习。

另外请大家一定注意:整个CM建链过程中出现了两个QP,一个是用于处理CM和MAD报文的GSI(UD)类型的QP,一个是建链之后两端具备的一对相互之间可以发送Send消息的QP。用户无法使用GSI QP来传递业务消息,只能使用后者。

另外对于RC QP来说,此时两端并未掌握对端的Virtual Address和Remote Key。所以如果要进行RDMA Write/Read操作,还需要通过这一对QP间Send消息来传递VA和R_Key。这个过程也是由用户自己决定如何实现的。

实验

好了,下面我们来做个试验。本次实验中,我们将分别通过Soft-RoCE和Soft-iWARP设备来观察CM建链的报文。

准备工作

虚拟机环境及其配置过程同“RoCE & Soft-RoCE”和“iWARP & Soft-iWARP”两篇文章。

本次执行的示例程序是rdma_server/client,以及udaddy。它们的源码都位于rdma-core仓库的librdmacm/examples目录下。如果按照“RoCE & Soft-RoCE”一文的步骤安装了用户态动态链接库的几个软件包,那么是可以直接执行这三个可执行程序的。

rdma_server/rdma_client

它们是配对执行的两个示例应用程序,使用RC服务类型,在两端通过调用CM API实现了“建链——数据交互——断链”的过程,数据交互使用的是Send操作类型。

udaddy

这是个UD QP的CM建链示例应用程序,在两端的UD QP之间通过CM建链后进行Send操作类型的数据交互。

抓包

Wireshark抓包的配置步骤不再赘述,请大家参考“RoCE & Soft-RoCE”一文。

RoCE v2 RC

我们首先来看一下RoCE v2的RC QP间的CM建链,该实验中用到的是Soft-RoCE(RXE)设备。

Server端执行:

rdma_server

Client端执行:

rdma_client -s 192.168.217.128

下图是抓包的结果,可以看到分成了三个部分:完成CM建链之后,利用建链好的RC QP,做了一次ping-pong操作,最后进行了断链。

【RDMA】23. RDMA之基于CM API的QP间建链--未消化_第7张图片

RoCE v2 RC QP CM抓包结果

我们打开26号报文,可以看到Request报文的分层关系,也可以看到CM报文中的QPN等信息:

【RDMA】23. RDMA之基于CM API的QP间建链--未消化_第8张图片

CM REQ报文

27号是Reply报文,从中也可以看到CM层的报文里有QPN等信息:

【RDMA】23. RDMA之基于CM API的QP间建链--未消化_第9张图片

CM REP报文

总结一下,上面的整个流程如下图所示,整个通信流程都是通过RoCE v2报文完成的。对比“Socket建链”文末中Socket建链的报文交互图,相信读者可以更好的理解本文最开始提到的Socket建链对于RoCE/Infiniband协议来说是一种“带外”的方式的含义。

【RDMA】23. RDMA之基于CM API的QP间建链--未消化_第10张图片

基于CM建链的RoCE v2报文交互流程

RoCE v2 UD

然后我们继续使用相同的Soft-RoCE设备抓取RoCE v2 UD QP的CM建链报文。

Server端执行:

udaddy

Client端执行:

udaddy -s 192.168.217.128

报文如下图所示,可以看到SIDR协议交互之后,就进行了数据交互,数据交互使用的是Send with Immediate操作类型,即带立即数的Send。如果展开报文的话,会发现这个立即数就是QPN。

【RDMA】23. RDMA之基于CM API的QP间建链--未消化_第11张图片

RoCE v2 UD QP CM抓包结果及SIDR_REQ报文

上图中我们顺便也展开了443号报文,这是一个SIDR_REQ消息,wireshark当前并不支持对其的解析,所以我们只能对照IB规范来解析其内容了。SIDR_REP也是一样,我就不贴图了。

iWARP RC

我们卸载Soft-RoCE设备并加载Soft-iWARP设备,并执行rdma_server和rdma_client,就可以观察到iWARP协议的CM建链报文了。

可以看到明显的分成了四个部分:TCP建链、MPA建链、数据交互和TCP断链。MPA的内容我们在“MPA”一文中有介绍,此处不再展开讲了。

【RDMA】23. RDMA之基于CM API的QP间建链--未消化_第12张图片

iWARP RC QP CM建链抓包结果

通过对Soft-RoCE和Soft-iWARP的RC QP的CM建链实验我们可以发现,同样的程序,不需要修改就可以跑在两种协议类型的设备上,这就是CM API作为统一的RDMA CM建链接口的最大价值所在。

除了上面的应用程序外,RDMA Write/Read操作类型也有对应的示例,比如rping,感兴趣的读者可以自己执行并抓包。

好了,本文对于CM建链就科普到这里,下一篇将给大家介绍CM API的使用。

参考内容

  1. Connection Queue Pairs. RDMAmojo. Connecting Queue Pairs - RDMAmojo RDMAmojo
  2. IB Specification. Chapter 12 Communitcation Management. IBTA
  3. IB Specification. 13.4 Management Datagrams. IBTA
  4. rdma_cm(7). Linux man page. rdma_cm(7): RDMA communication manager - Linux man page (die.net)
  5. rdma_client(1). Linux man page. rdma_client(1) - Linux man page (die.net)
  6. rdma_server(1). Linux man page. rdma_server(1) - Linux man page (die.net)
  7. udaddy(1). Linux man page. udaddy(1) - Linux man page (die.net)

你可能感兴趣的:(网络,java,开发语言)