什么是RDMA
RDMA(RemoteDirect Memory Access)技术全称远程直接内存访问,就是为了解决网络传输中服务器端数据处理的延迟而产生的。它将数据直接从一台计算机的内存传输到另一台计算机,无需双方操作系统的介入。这允许高吞吐、低延迟的网络通信,尤其适合在大规模并行计算机集群中使用。RDMA通过网络把资料直接传入计算机的存储区,将数据从一个系统快速移动到远程系统存储器中,而不对操作系统造成任何影响,这样就不需要用到多少计算机的处理能力。它消除了外部存储器复制和上下文切换的开销,因而能解放内存带宽和CPU周期用于改进应用系统性能。而实现RDMA的协议就是Infiniti Band.
Infiniti Band
简介
通道适配器Channel Adapter(CA):网卡设备。
子网:一些有相同子网ID和相同的子网管理器的端口和链路的集合。
一个报文的有效荷载(payload)部分最大可以包含4KB数据。CA如果需要发送的报文大于此长度,需要对此进行切分,分为多个包传输。每个报文分为payload、路由报文头(header)、CRC校验等。
子网管理器(SM)会在子网启动时发现所有设备,配置它们,并在后续周期性检查子网的拓扑结构是否被修改;在配置过程中,子网管理器会为每个端口配置一个独有的本地ID和一个相同的子网ID,用以标识子网和端口位置。
IB协议的本质是CA间的内存空间进行数据交换,分三类消息传输:
写目标CA内存:从本地CA的内存传输信息到目标CA的内存;
读目标CA内存:从目标CA的内存读取信息,并存储在本地CA的内存中;
对目标CA原子操作:对目标CA的内存执行原子操作(读/改/写),并将返回的数据存储在本地CA的内存。
写目标CA内存分为两种情况:
发送操作:报文不会指定数据写入目标CA 的内存地址,由目标CA自行决定;
RDMA写操作:报文会指定数据写入目标CA 的内存地址,报文包括了有效荷载,请求报文的内存起始地址、报文长度和允许该RDMA写操作的一个密钥。
读目标CA内存:向目标CA发出读指定内存中数据的请求,目标CA会返回一个或多个携带数据的响应报文,本地CA将报文中的数据存储到本地内存中。
对目标CA原子操作分为以下两种原子操作:
原子读取和加法操作:目标CA收到请求后,从其本地的指定内存中读取数据,与报文中的加数相加,并将结果写回本地内存。目标CA将读回的初值以原子响应包的形式返回给请求端CA。收到响应数据包后,请求端CA将读数据写入自己的本地内存。
原子比较和交换操作:报文中携带比较值和待写入的值,目标CA收到请求后从其本地的指定内存中读取数据,将读取的数据与报文中待比较的数值比较,若相等,将待写入的值写入指定位置,返回的响应操作与上述加法原子操作一致。
IB协议类似于以太协议,也有链路层、网络层、传输层和上层协议,可以参考《Infiniband Architecture Specification》。
l 物理层定义了数据在线缆上传输的物理信号、编码、帧定界符。
l 链路层定义了流控机制以及如何在子网内传输。有两种报文:
l Link Management Packet:用于链路的训练和维护,端口间参数的协商,如:比特率、带宽,也用于传输流控信用和维护链路完整性,只工作在链路层,不受流控影响,不会转发到其它链路。
l Data Packet:用于数据传输。
l 链路层流控是基于信用的,链路上的接收端向发送端发送信用,表示接收端能接收的数据报数量,每个虚拟通道VL的流控是分开隔离的。VL15不受流控影响。
l 网络层使用GID进行路由,GID才有IPv6地址格式。
l 传输层用于将数据传递给争取的QP,当报文长度超过MTU时,发送端的传输层要负责分片,接收端传输层负责重组。每个报文会分片一个PSN,根据PSN来确定是否有分组丢失。当其中一个分片丢失,会丢弃后续所有分片,直到发送者重传了该分片。
l ICRC和VCRC为报文提供完整性保护,ICRC用于覆盖报文中不变化的部分,VCRC覆盖整个报文。
帧格式
l LRH:占8字节,类似于以太的ETH头,用于交换机间的报文转发。通过目的LID和源LID来实现二层网络寻址。LID类似于MAC地址,由子网管理器给每个端口分配一个本地唯一的ID。所有的报文都需要LRH。
l GRH:占40字节,采用以太的IPv6头格式,用于路由器之间的报文转发。通过目的GID(DGID)和源GID(SGID)来实现三层网络寻址。GID类似于IPv6地址,全球唯一。除了子网管理报文外的所有其它报文都需要GRH。
l BTH:占12字节,类似于以太的TCP/UDP头,包括Opcode、DestQP和PSN。Opcode表示报文操作类型,DestQP表示对端CA的目标QP(Queue Pair),PSN(Packet Sequence Number)表示报文序列号,可以用于报文顺序检查和报文重传。
本质上,IB报文转发和以太网一样,基于LRH头来实现二层网络转发,基于GRH头实现三层网络路由。
RDMA write可以携带immediate data一同传输,在RDMA write的最后一个切片会携带immediate data,位于ETH后payload前,和payload不同,immediate data不需要写入本地内存。
LRH
LRH(local route header)是链路层的报文头,长度8字节。LRH用于二层网络路由,交换机根据端口转发表会修改SLID和DLID。
VL:占4bit,virtual line,虚拟通道,共16个,VL 15专用于子网管理,数据包经过子网时,VL值会变化,计算ICRC不包括该字段;
LVer:占4bit,link version,标志LRH的版本,应该设置为0,如果接收设备不支持该版本,那么将丢弃该报文;
SL:占4bit,Service Level,服务级别,每个端口都会维护一个SL到VL的映射表;
LNH:占2bit,Link Next Header,标志了跟在LRH之后的header,比如GRH、BTH等,取值定义如下:
DLID:占16bit,目的LID;
Packet Length:占11bit,报文长度,单位4字节,从LRH第一字节开始到VCRC之前的最后一个字节的报文长度;
SLID: 占16bit,源LID;
LID类似于以太网的mac地址,IB交换机根据LID来进行二层转发,报文转发到下一跳时,会替换DLID和SLID,但是不同的是LID是动态分配的,每次上电可能都不一样;
在RC、UC、RD(包括XRC)服务需要校验DLID和SLID,UD服务不需要校验,SLID不能是一个组播LID;
所有的Header包括两字节的VCRC的长度是126,payload的最大长度是4K,因此Packet Length的最大值为(4096 + 126 – 2) / 4 = 1055;对于IBA报文来说,允许传输的报文Packet Length最小值是6,即24字节,包括LRH,对于raw报文,允许传输的报文Packet Length最小值是5,即20字节,包括LRH。
报文传输过程中,VL、SLID、DLID可能被交换机修改,ICRC计算不能包括这些字段。
GRH
GRH(global route header)是网络层的报文头,长度40字节,结构定义和IPv6报文头格式一样,但IBA没有定义GID和IPv6地址之间的映射关系。不是所有的报文都需要GRH,GRH用于三层网络路由。
IPVer:占4bit,版本号,参考IPv6,其值固定为6;
TClass:占8bit,数据流通信类型和优先级,IBA没有具体指定取值,实现上需要和SL之间做映射;
FlowLabel: 占20bit,用于标志那些需要按序交付的一组报文;
PayLen:占16bit,从GRH之后的第一字节开始到ICRC最后一个字节的长度,单位4字节;
NxtHdr:占8bit,Next Header,下一个协议头;IBA报文,该设置为0x1B;对于raw报文,GRH相当于Ipv6 Header,取值就是TCP/UDP等的proto;
HopLmt:占8bit,表示报文在被丢弃之前允许经过的跳数,防止路由循环;将该字段设置为0或1,将确保数据包不会转发到本地子网之外;路由器应该丢弃值为0或1的报文,否则就需要将该字段减一;
SGID:占128bit,源全局ID;
DGID:占128bit,目的全局ID;
GID类似于IPv6中的IP地址,IB路由器根据GID进行路由,GID和mac地址一样由厂商自己分配,全球唯一。
存在以下情况之一,必须包含GRH头:
1.组播报文;
2.报文的目的地是一个端口,且和源端口不在同一个子网;
关于FlowLabel,如果报文不使用FlowLabel,那么应该设置为0;如果一组报文需要按序交付,那么应该使用相同的FlowLabel;如果一个QP使用了FlowLabel且FlowLabel非0,那么从该QP发出的所有报文都应该使用相同的FlowLabel;传输过程中,路由器可以修改FlowLabel,但是必须保证所有需要按序交付的报文使用相同的值。
报文传输过程中,HopLmt和FlowLabel可能被修改,ICRC计算不能包括这些字段。
BTH
BTH(Base transport header)是传输层头,占12字节,用于将数据送到指定的QP中,数据超过MSS需要切片。只用于IBA报文,RAW报文不需要BTH。
OpCode:占8bit,code[7:5] 定义服务类型,code[4:0]定义该服务类型下的传输类型;同时允许自定义厂商OpCode,取值如下:
SE:占1bit,Solicited Event,指示对端产生一个CQ事件;对报文头进行验证,要忽略该字段;以下Opcode需要置1:
l SEND Only
l SEND Last
l SEND Only with Immediate
l SEND Last with Immediate
l SEND Only with Invalidate
l SEND Last with Invalidate
l RDMA WRITE only with Immediate
l RDMA WRITE Last with Immediate
M:占1bit,Migration Request,1表示连接或EE Context已迁移,0表示状态未改变;
Pad:占2bit,填充的pad的个数,payload按照4字节对齐;
Tver:占4bit,Transport Header Version,IBA传输设置为0;如果接收方不支持指定的传输版本,则分组将被丢弃;
Partition Key:占16bit,标志了目标QP所属的分区,只有相同key的端口才能互相通信,默认全F;
F/Res1:占1bit,FECN,0表示没有收到FECN,1表示经过了拥塞点,计算ICRC不包括该字段;
B/Res1:占1bit,BECN,0表示没有经过拥塞点或经过了拥塞点但没有被标记,1表示该报文属于向前拥塞,在ACK报文或CN BTH中会被置1,计算ICRC不包括该字段;
Reserved6:占6bit,应该设置为0,计算ICRC不包括该字段;
Destination QP:占24bit,目的QP number,如果是UD组播报文,那么目的QP为0xFFFFFF;
A:占1bit,Acknowledge Request,表示是否需要对端回复一个ACK;
Reserved7:占7bit,应该设置为0,计算ICRC不包括该字段;
PSN-Packet Sequence Number:占24bit,一个报文占一个PSN,对端通过PSN来判断是否有丢包或重复报文。SEND/WRITE/ATOMIC 场景下,next_psn = (curr_psn + 1) % 2^24,READ场景下,下一个rdma request的PSN不是直接+1,而是要预留出预期read rsp 报文个数。
F/Res1、B/Res1、Reserved6、Reserved7不包括在ICRC范围内。
如果Destination QP是QP0,那么不检查Partition KEY;如果是QP1,Partition KEY和响应者该端口的任何一个Partition KEY匹配即可;如果非QP0和QP1,对于RD类型来说,Partition KEY和响应者EE-Context的Partition KEY匹配即可;否则,Partition KEY必须和响应者对应RQ的Partition KEY匹配。
扩展的传输层报文头
RDETH
RDETH(Reliable Datagram Extended Transport Header)占 4字节,仅用于RD,由BTH的Opcode指定。
EE-Context:End-to-End Context,占24bit,EE-Context的ID,表示此报文使用的 EE (End-to-End)上下文,用于在任意两个端节点之间复用/解复用可靠的数据报数据包。EE-Context为可靠传输状态提供了一个上下文,类似于用于可靠连接的上下文。
DETH
DETH(Datagram Extended Transport Header)占8字节,仅用于RD和UD,由BETH的opcode指定。
Queue Key:占32bit,访问目标队列的key;
Source QP:占24bit,源QP的Number。
RETH
RETH(RDMA Extended Transport Header),占16字节,仅用于RDMA request(Read/Write)的第一个报文,由BTH的opcode指定。
VA:占64bit,数据存放的虚拟地址,可以从任何边界开始,不用考虑对齐;
Remote Key:占32bit,该虚拟地址的访问权限;
DMA Length:占32bit,数据的长度。
响应者应该检查访问权限,访问不能越界,任何非法的访问都会导致报文丢弃,对于可靠服务,会响应一个NAK报文。
AtomicETH
AtomicETH(Atomic Extended Transport Header)占28字节,仅用于Atomic Request报文,由BTH的opcode指定。
VA:占64bit,数据存放的虚拟地址;
Remote Key:占32bit,该虚拟地址的访问权限;
Swap Data:占64bit,要交换或者增加的数据,大端格式;
Compare Data:占64bit,要参与比较的数据,大端格式;
XRCETH
XRCETH(XRC Extended Transport Header)占4字节, XRC send, XRC RDMA Read/Write or XRC Atomic Request携带的报文头。
XRC SRQ:占24bit,XRC SRQ的number。
AETH
AETH(ACK Extended Transport Header)占4字节,仅用于ACK报文、RDMA Read Response的第一个或最后一个报文,由BTH的opcode指定。
Syndrome:占8bit,ACK或NAK报文相关信息;如果是ACK,且是RC服务类型,就表示Limit Sequence Number(LSN);如果是NAK,则表示错误码;如果是RNR NAK,就表示请求者重传需要等待的时间,取值如下:
C CCCC:encoded end-to-end flow control credits,只对RC有效,表示相对于MSN的可用的WQE个数,其余服务类型设置为0;
T TTTT取值如下:
N NNNN的取值如下:
MSN:占24bit,Message Sequence Number,发送者对队列上的每个WQE进行顺序编号,叫做Send Sequence Number,响应者返回MSN就表示最近完成的SSN,发送者以此决定哪些WQE已完成。
AtomicAckETH
AtomicAckETH(Atomic ACK Extended Transport Header)占8字节,仅用于Atomic Respose报文,由BTH的opcode指定。
Original Remote Data:占64bit,原子操作之前远端内存中的数据,大端格式。
ImmDt
ImmDt(Immediate Data)占4字节,仅用于Send或Write请求报文的最后一个报文。
Immediate Data:占32bit,立即数;
IETH
IETH(Invalidate Extended Transport Header)占4字节,SEND with Invalidate request 的最后一个报文会携带。
R_Key:占32bit,R_Key被响应者用来失效内存区域或内存窗口。
Payload
Payload不会出现在RDMA Read Requests、 Acknowledge、CmpSwp、FetchAdd和 Atomic Acknowledge packets中。Payload不能超过MTU大小,超过需要分片,且只允许最后一片长度不足MTU。Payload的长度必须4字节对齐,pad的长度由BTH的Pad字段指定。
ICRC
ICRC占4字节,用于覆盖那些报文传输过程中不会改变的字段。ICRC只用于IBA报文,Raw报文不使用ICRC,因为Raw报文哪些字段传输过程中会改变是未知的。
如果报文只在子网内传播,没有GRH,那么ICRC计算范围如下:
1.LRH,除开VL字段;
2.BTH,除开resv字段;
3.ETH(如果存在);
4.payload(如果存在);
如果报文在子网间传播,有GRH,那么ICRC计算范围如下:
1.除开整个LRH;
2.GRH除开Tclass、FlowLabel、Hoplmt;
3.BTH,除开resv字段;
4.ETH(如果存在);
5.payload(如果存在);
计算ICRC时,除开的字段用全1替换。
ICRC使用和以太一样的CRC32多项式0x04C11DB7,计算过程如下:
1.CRC32的初值为0xFFFFFFFF;
2.计算按照大端字节序进行,最高字节的最低位作为CRC计算的第一个bit;
3.对计算得到的比特序列进行补全,得到ICRC。
VCRC
VCRC占2字节,用于覆盖所有报文字段,包括Raw报文,从LRH的第一个字节开始到VCRC之前的最后一个字节。当报文被交换机或路由器转发时,有些字段可能会发生变化,需要重新计算VCRC。
VCRC计算过程如下:
1.CRC 16的初值是0xFFFF;
2.计算按照大端字节序进行,LRH的第一个字节的最低有效位(LRH:LVer的第0位)是CRC计算的第一个bit;
3.对计算得到的比特序列进行补全,得到ICRC。