🐱PS:

本文是对该博客(https://zhuanlan.zhihu.com/p/144099636)的一个学习笔记。

若考虑使用哪种服务类型的QP,指路:https://www.rdmamojo.com/2013/06/01/which-queue-pair-type-to-use/

可靠服务

IB协议中是这样描述可靠服务的:可靠服务在发送和接受者之间保证了信息最多只会传递一次,并且能够保证其按照发送顺序被接收。

IB通过以下三个机制来保证可靠性:

  • 在IB协议的可靠服务类型中,使用了应答机制来保证数据包被对方收到。即接收端在接收到数据包后返回ACK。IB的可靠服务类型中,接收方不是每一个包都必须回复,也可以一次回复多个包的ACK。
  • IB协议使用CRC进行数据校验。发端会对Header和Payload(有效载荷,也就是真正要收发的数据)通过一定的算法得到一个校验值放到数据包的末尾。对端收到数据包后,也会用相同的算法计算出校验值,然后与数据包中的校验值比对,如果不一致,说明数据中包含错误(一般是链路问题导致的),那么接收端就会丢弃这个数据包。
  • IB协议中有PSN(Packet Sequence Number,包序号)进行保序,即每个包都有一个递增的编号。PSN可以用来检测是否丢包,比如收端收到了1,但是在没收到2的情况下就收到了3,那么其就会认为传输过程中发生了错误,之后会回复一个NAK给发端,让其重发丢失的包。
    • PSN是每个QP都具有的,不同QP间是相互独立的。

ICRC 校验发生在IB链路层, 而NAK是IB 传输层的功能。NAK会发生,但是发生在下一个packet (with no ICRC error)。比如,PSN为10的数据包在传输到响应方时出现了某种损坏,由于ICRC错误,响应方IB链路层将会丢弃该数据包。这时IB 传输层 会看到 PSN=9 后面跟着 PSN=11。PSN=11 会触发IB传输层发起NAK。

不可靠服务

没有上述这些机制来保证数据包被正确的接收,属于“发出去就行,我不关心有没有被收到”的服务类型。

基于连接的服务

每个QP都和另一个远端节点相关联。在这种情况下,QP Context(简称QPC)中包含有远端节点的QP信息。在建立通信的过程中,两个节点会交换包括稍后用于通信的QP在内的对端信息。在连接服务类型中的每个QP,都和唯一的另一个QP建立了连接,也就是说QP下发的每个WQE的目的地都是唯一的。

基于数据报的服务

与连接相反,发端和收端间不需要“建立管道”的步骤,只要发端到收端物理上是可以到达的,那么我就可能从任何路径发给任意的收端节点。

  • IB协议对其的定义是这样的:

    对于数据报服务来说,QP不会跟一个唯一的远端节点绑定,而是通过WQE来指定目的节点。和连接类型的服务一样,建立通信的过程也需要两端交换对端信息,但是数据报服务对于每个目的节点都需要执行一次这个交换过程。

比如,在数据报类型的QP的Context中,不包含对端信息,即每个QP不跟另一个QP绑定。QP下发给硬件的每个WQE都可能指向不同的目的地。与连接服务类型一样,本端QP可以和哪个对端QP发送数据,是在准备阶段提前通过某些方式相互告知的。这也是上文“数据报服务对于每个目的节点都需要执行一次这个交换过程”的含义。

RC

基于连接的可靠服务,类比TCP/IP协议栈传输层的TCP。

RC用于对数据完整性和可靠性要求较高的场景,跟TCP一样,因为需要各种机制来保证可靠,所以开销自然会大一些。

由于RC服务类型和每个节点间需要各自维护一个QP,假设有N个节点要相互通信,那么至少需要**N * (N - 1)**个QP,而QP和QPC本身是需要占用网卡资源或者内存的,当节点数很多时,存储资源消耗将会非常大。

UC

基于连接的不可靠服务。

  • 注意UC支持WRITE却不支持READ操作

    因为read需要请求端网卡保存上下文等信息(比如保存一些状态以等待某个发出去的READ返回数据),如果是不可靠的话,包丢失会造成网卡永久等待READ返回,这种行为不太符合常理,因此不可靠连接无法支持READ;

RD

基于数据报的可靠服务。各厂商选择实现是否支持该服务。

UD

基于数据报的不可靠服务,类比TCP/IP协议栈传输层的UDP。

UD硬件开销小并且节省存储资源,比如N个节点需要相互通信,只需要创建N个QP就可以了,但是可靠性跟UDP一样没法保证。用户如果想基于UD服务类型实现可靠性,那么需要自己基于IB传输层实现应用层的可靠传输机制。

  • 注意UD不支持WRITE操作,只能用于SEND

    无论是可靠连接还是不可靠连接,都要求QP一对一连接(即文中的“建立管道”),也就是说READ和WRITE都需要一对一连接,但数据报无需一对一连接,因此没有一对一连接这个前提,所以无法支持WRITE

各服务类型支持的操作

Untitled

一些问题及回答

如果一个qp占用了某udp src port,同一机器上的非rdma 的 udp程序还能用这个udp 源端口号吗?

可以复用,IB规范对这个UDP Source Port没有做规定,一般是用这个域段做链路间的负载均衡。有的厂商通过驱动里做HASH得出一个值然后配到了硬件里,有的厂商甚至都没有做,估计是个随机值或者固定值。

rdma中rc和ud能否拥有相同的qp number,网卡驱动根据qp type进行区分?

不可以。这不止是修改驱动的问题,从API、整个RDMA软件栈和硬件实现来看,QP类型和QPN都是QP的固有属性之一,QP类型不同,调用API时传递的参数、软件栈的处理、QPC/WQE的布局、硬件的处理都会有差异。虽然理论上可以这么搞,但是代价是破坏了一个成熟的标准,相当于自己重新定义了一种协议。

RC和UD它们的具体应用场景是在哪里?

RC用在对可靠性要求较高的场景,但是因为需要建立很多QP来维持进程间的连接,所以对内存的消耗很大。使用UD的话,每个进程只需要保留一个QP就可实现对整个组网内的其他进程通信,但是可靠性需要由上层保证。此外还有一种XRC服务,相比于RC可以节省通信所需的QP数。