【RDMA】librdmacm库和连接建立过程

概述:

rdma_cm是用于建立RDMA传输上的通信的管理器。

说明:

RDMA CM是一个用于建立可靠连接和不可靠数据报数据传输的通信管理器。它为建立连接提供了一个RDMA传输中立的接口。该API基于套接字,但为队列对(QP)的语义进行了调整:通信必须通过特定的RDMA设备进行,并且数据传输是基于消息的。

RDMA CM仅提供RDMA API的通信管理(连接建立/拆除)部分。它与libibverbs库定义的verbs API配合使用。libibverbs库提供了发送和接收数据所需的接口。

客户端操作:

此部分提供了通信的主动端(或客户端)的基本操作概述。一般的连接流程如下:

1. rdma_create_event_channel:创建接收事件的通道。
2. rdma_create_id:分配一个rdma_cm_id,类似于socket。
3. rdma_resolve_addr:获取本地RDMA设备以到达远程地址。
4. rdma_get_cm_event:等待RDMA_CM_EVENT_ADDR_RESOLVED事件。
5. rdma_ack_cm_event:确认事件。
6. rdma_create_qp:为通信分配一个QP。
7. rdma_resolve_route:确定到达远程地址的路由。
8. rdma_get_cm_event:等待RDMA_CM_EVENT_ROUTE_RESOLVED事件。
9. rdma_ack_cm_event:确认事件。
10. rdma_connect:连接到远程服务器。
11. rdma_get_cm_event:等待RDMA_CM_EVENT_ESTABLISHED事件。
12. rdma_ack_cm_event:确认事件。
13. 在连接上执行数据传输。
14. rdma_disconnect:撤销连接。
15. rdma_get_cm_event:等待RDMA_CM_EVENT_DISCONNECTED事件。
16. rdma_ack_cm_event:确认事件。
17. rdma_destroy_qp:销毁QP。
18. rdma_destroy_id:释放rdma_cm_id。
19. rdma_destroy_event_channel:释放事件通道。

用于在节点之间建立不可靠数据报(UD)通信的过程几乎相同。但是,QPs之间不会形成实际的连接,因此不需要断开连接。

虽然此示例显示客户端发起断开连接,但连接的任一方都可以发起断开连接。

服务器操作:

此部分提供了通信的被动端(或服务器端)的基本操作概述。一般的连接流程如下:

1. rdma_create_event_channel:创建接收事件的通道。
2. rdma_create_id:分配一个rdma_cm_id,类似于socket。
3. rdma_bind_addr:将本地端口号设置为监听的端口号。
4. rdma_listen:开始监听连接请求。
5. rdma_get_cm_event:等待带有新的rdma_cm_id的RDMA_CM_EVENT_CONNECT_REQUEST事件。
6. rdma_create_qp:在新的rdma_cm_id上为通信分配一个QP。
7. rdma_accept:接受连接请求。
8. rdma_ack_cm_event:确认事件。
9. rdma_get_cm_event:等待RDMA_CM_EVENT_ESTABLISHED事件。
10. rdma_ack_cm_event:确认事件。
11. 在连接上执行数据传输。
12. rdma_get_cm_event:等待RDMA_CM_EVENT_DISCONNECTED事件。
13. rdma_ack_cm_event:确认事件。
14. rdma_disconnect:撤销连接。
15. rdma_destroy_qp:销毁QP。
16. rdma_destroy_id:释放已连接的rdma_cm_id。
17. rdma_destroy_id:释放监听的rdma_cm_id。
18. rdma_destroy_event_channel:释放事件通道。

返回值:成功返回0,错误返回-1。如果函数以异步方式运行,则返回值为0表示成功启动操作。操作仍然可能以错误完成;用户应该检查相关事件的状态。如果返回值为-1,则errno将包含有关失败原因的其他信息。

先前版本的库对于与ENOMEM、ENODEV、ENODATA、EINVAL和EADDRNOTAVAIL代码有关的某些情况会返回-errno并且不设置errno。希望检查这些代码并与先前版本的库兼容的应用程序必须在返回代码小于-1时手动将errno设置为返回代码的负值。

代码示例

RDMA编程链接管理库 librdmacm 源码:rdma-core/librdmacm/examples at master · linux-rdma/rdma-core (github.com)

在:rdma-core/librdmacm/examples

服务端:rdma_server.c

客户端:rdma_client.c

mellaonx驱动源码中也提供了rdma-core源目录码:MLNX_OFED_LINUX-5.8-1.1.2.1-rhel9.0-ext/src/MLNX_OFED_SRC-5.8-1.1.2.1/SRPMS

rdma-core-58mlnx43-1.58112.src.rpm

rpm -ivh  rdma-core-58mlnx43-1.58112.src.rpm 安装完成后

源码解压到:/root/rpmbuild/SOURCES/

编译

$ bash build.sh

输出在:build/bin build/lib

build/bin 目录包含示例程序,build/lib 目录包含共享库。构建配置是“原地”运行所有程序的,因此无法安装。

注意:目前不易从构建目录运行插件,插件仅从系统路径加载

编译之前环境可能需要安装一些依赖,如:

CentOS 7:

$ yum install epel-release

$ yum install cmake3 ninja-build pandoc

详情见README.md

编译出来的内容:

 rdma_xclient.c 和 rdma_client.c 的区别

rdma_xclient.c  客户端只发,接收端只收

rdma_client.c    双边相互收发

这里有一个理解难点

就是执行rdma_get_cm_event之后的输出resp 是从哪里来的?

其实就是用户态和内核态的交流,户态和内核态主要是通过write()系统调用来对/dev/infiniband/uverbsN字符设备文件进行操作从而实现交流信息的。

最近的协议栈也支持了ioctl()系统调用,通过ioctl把cmd命令发到内核的,内核的rdma cm模块会根据cmd做相应处理

rdma_get_cm_event 就是通过ioctl把cmd命令发到内核的,内核的rdma cm模块会根据cmd做相应处理,通过resp返回结果。

用户态和内核态如何交流

前置知识

用户态和内核态如何交流

控制路径上,用户态和内核态主要是通过write()系统调用来对/dev/infiniband/uverbsN字符设备文件进行操作的,

从而实现交流信息的。最近的协议栈也支持了ioctl()系统调用,

通过ioctl把cmd命令发到内核的,内核的rdma cm模块会根据cmd做相应处理

ABI

ABI(Application Binary Interface)是应用程序间的二进制接口,本文中RDMA软件栈架构图中的Userspace和Kernel之间的uverbs接口就是一种ABI。ABI定义了运行时的程序之间交流的格式,比如参数以什么形式传递(分别写到指定的寄存器/使用栈)、以什么格式传递以及返回值放到哪里等等。

uverbs API规定了用户态和内核态之间的命令消息cmd的格式和返回消息resp的格式,大致是下图这个意思:

我们在“RDMA之Verbs”一文中介绍过用户态库和内核驱动,它们各自都按照自己的节奏发布版本,用户态和内核态之间交互,涉及到很多命令的传递,而不同版本之前的交互格式是有差异的。RDMA软件栈通过设计uverbs ABI接口来保证不同版本的用户态和内核态之间的兼容性,即某个版本的用户态库,可以直接运行在各种版本的内核上。

我们还是拿Create QP的动作来举例,软件栈中是这样ibv_create_qp()的定义cmd和resp的:

可以看到cmd分为三个部分:

  • 命令码:告诉内核态当前陷入内核态想要执行的操作
  • 公共域段:所有厂商的创建QP动作都需要从用户态传递到内核态的参数
  • 驱动自定义域段:各个厂商自定义的需要传递到内核的参数

 

resp分为两个部分:

公共域段:所有厂商在内核创建完QP之后,需要返回给用户态的参数

驱动自定义域段:各个厂商的自定义返回参数

上面的格式都是由uverbs ABI接口定义的,具体来说整套用户态和内核的交互机制都是由内核的ib_uverbs.ko和用户态的libibverbs.so相配合实现的。

实际上除了各个厂商的驱动开发者,RDMA应用程序开发者以及普通用户不必用关心ABI的实现,只需要关心API就可以了。

原文链接:https://blog.csdn.net/bandaoyu/article/details/113125473

rdma-core 编译出来的工具

 使用 RDMA verbs API,较为底层,需要手动管理连接和操作;使用 RDMA CM API,更高层,封装了一些操作,使得代码更简洁易读。

用法:

usage: rdma_xserver

        [-p port_number]

        [-c communication type]

            r - RC: reliable-connected (default)

            x - XRC: extended-reliable-connected

usage: rdma_xclient

        [-s server]

        [-p port_number]

        [-c communication type]

            r - RC: reliable-connected (default)

            x - XRC: extended-reliable-connected

服务端:

rdma_xserver -p 8888

客户端:

rdma_xclient -s 10.252.8.1 -p 8888

usage: rdma_server

        [-s server_address]

        [-p port_number]

usage: rdma_xclient

        [-s server]

        [-p port_number]

        [-c communication type]

            r - RC: reliable-connected (default)

            x - XRC: extended-reliable-connected

服务端:

rdma_server -s 10.252.8.1 -p 8888

客户端:

rdma_client -s 10.252.8.1 -p 8888

在编译出来的bin下还有:

[root@localhost bin]# ls

check_lft_balance.pl  ibaddr               iblinkinfo     ibrouters   ibv_asyncwatch    ibv_xsrq_pingpong  rdma_server   sminfo      udpong

cmtime                ibcacheedit          ibnetdiscover  ibsendtrap  ibv_devices       mckey              rdma_xclient  smpdump     umad_compile_test

dump_fts              ibccconfig           ibnodes        ibstat      ibv_devinfo       mcm_rereg_test     rdma_xserver  smpquery    umad_reg2

dump_lfts.sh          ibccquery            ibping         ibstatus    ibv_rc_pingpong   perfquery          riostream     srp_daemon  umad_register2

dump_mfts.sh          ibfindnodesusing.pl  ibportstate    ibswitches  ibv_srq_pingpong  rcopy              rping         testleaks   umad_sa_mcm_rereg_test

ibacm                 ibhosts              ibqueryerrors  ibsysstat   ibv_uc_pingpong   rdma_client        rstream       ucmatose    vendstat

ib_acme               ibidsverify.pl       ibroute        ibtracert   ibv_ud_pingpong   rdma_rename        saquery       udaddy

他们的用法可以使用:man xxx 查询 如:man rdma_client

udaddy  “udp”的测试

如果系统上没有安装doc手册,则可以访问: Index of /linux/man-pages/man1     在页面搜索相关的命令,查看其用法

cmtime

确定客户端和服务器应用程序之间的RDMA CM连接建立和拆除中各个“步骤”的最小和最大时间定时的“步骤”包括:

创建id、绑定地址、解析地址、解析路由、创建qp、连接、断开连接和销毁。

例子:

服务端

cmtime -p 888

客户端:

cmtime -p 888 -s 10.252.8.1

-s server_address 服务器系统监听连接的网络名称或IP地址。所使用的名称或地址必须经过RDMA设备路由。客户端需

指定。

-b bind_address

要绑定到的本地网络地址。

-c connections

客户端与服务器之间建立的连接数。(默认100)

-p port_number

服务器的端口号。

-r retries

解析地址或路由时的重试次数。(默认2)

-t timeout_ms

解析地址或路由时的超时时间,以毫秒(ms)为单位。(默认2000 - 2秒)

ucmatose

使用librdmacm在两个节点之间建立一组可靠的RDMA连接,可选择在节点之间传输数据,然后断开连接。

 

用法:

ucmatose [-s server_address] [-b bind_address]
                 [-f address_format] [-P port_space]
                 [-c connections] [-C message_count] [-S message_size] [-a ack_timeout]
      
ucmatose -s server_address [-b bind_address]
                 [-f address_format] [-P port_space]
                 [-c connections] [-C message_count] [-S message_size] [-t tos] [-a ack_timeout]

例子:

服务端:

ucmatose -b 10.252.8.1

客户端:

ucmatose  -s 10.252.8.1

ucmatose -b 10.252.64.25 -c 10

ucmatose -s 10.252.64.25 -c 10

rping

建立可靠的RDMA连接,使用librdmacm在两个节点之间。可选择在节点之间执行RDMA传输,然后断开连接。

mckey

使用librdmacm在节点之间建立一组RDMA多播通信路径,可选择将数据包传输给接收节点,然后拆除通信。

 

 

ib_acme ib_acme是用于IB ACM的测试和配置utility

ibv_rc_pingpong 通过可靠连接(RC)传输,在InfiniBand上运行一个简单的乒乓测试。

\ibv_uc_pingpong\ibv_ud_pingpong

ibv_srq_pingpong 通过可靠的连接(RC)传输,使用多个队列对(QPs)和一个共享的接收队列(SRQ),运行一个简单的InfiniBand ping-pong测试。

ibv_xsrq_pingpong:InfiniBand上通过扩展可靠连接(XRC)传输服务运行一个简单的乒乓测试,使用共享接收队列(SRQ)。

riostream

使用RDMA协议(rsocket)进行流式传输,以连接和交换客户端和服务器应用程序之间的数据。

rstream

使用基于RDMA的流协议(rsocket)来连接客户端和服务器应用程序之间的数据交换。

udpong

使用不可靠的数据报流通过RDMA协议(rsocket)在客户端和服务器应用程序之间建立连接并交换数据。

RDMA的工具:

ibv_asyncwatch  将转发到用户空间的 RDMA 设备的异步事件显示出来。

ibv_asyncwatch -d mlx5_bond_0

vendstat

使用特定厂商的 MAD(管理数据包)来访问超出 IB 规范的厂商特定功能。目前,支持 Mellanox InfiniSwitch-III(IS3)和 InfiniSwitch-IV(IS4)。

  • srp_daemon(ib_srp.ko)
  • iwpmd(针对 iwarp 内核提供程序)
  • ibacm(用于 InfiniBand 通信管理助手)
  • efa.ko
  • iw_cxgb4.ko
  • hfi1.ko
  • hns-roce.ko
  • i40iw.ko
  • ib_qib.ko
  • mlx4_ib.ko
  • mlx5_ib.ko
  • ib_mthca.ko
  • ocrdma.ko
  • qedr.ko
  • rdma_rxe.ko
  • siw.ko
  • vmw_pvrdma.ko
  • /dev/infiniband/uverbsX(libibverbs)
  • /dev/infiniband/rdma_cm(librdmacm)
  • /dev/infiniband/umadX(libibumad)
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: RDMA(Remote Direct Memory Access)是一种数据传输技术,它允许在网络中直接访问远程主机的内存,而无需经过CPU的干预。RDMA的原理和技术实现主要包括以下几个方面。 首先,RDMA利用物理网卡的功能来实现直接内存访问。传统的网络数据传输方式中,数据需要从发送端通过CPU拷贝到发送端网卡的发送缓冲区,然后发送到接收端,再通过接收端网卡进入接收缓冲区,最后再通过CPU从接收缓冲区拷贝到接收端的内存中。而RDMA技术通过使网卡可以直接访问主机内存,省去了CPU的拷贝过程,从而大大提高了数据传输的效率。 其次,RDMA还借助于信号量和排队机制来实现数据传输的效率和可靠性。每个发送和接收操作都有一个独立的发送或接收队列,通过引入排队机制,可以并行处理多个传输请求,减少了传输的延迟。而信号量机制则用于控制发送和接收操作的顺序和进度,保证数据传输的可靠性和正确性。 此外,RDMA还采用了零拷贝和数据仲裁技术,进一步提高了数据传输的效率。零拷贝技术指的是在数据传输中直接传递内存地址而不是数据本身,减少了数据的复制和移动,提高了传输速度。而数据仲裁技术则用于解决并发访问共享内存时的冲突问题,保证数据传输的正确性。 总结起来,RDMA通过直接访问远程主机内存、利用信号量和排队机制、采用零拷贝和数据仲裁技术等手段,实现了高效的数据传输。它在高性能计算、数据中心和云计算等领域具有广泛的应用前景。 ### 回答2: RDMA(Remote Direct Memory Access)是一种高性能的网络通信技术,其原理是通过绕过操作系统内核,直接在网络适配器和内存之间传输数据。传统的网络通信方式中,数据需要在发送和接收端之间经过多次从用户空间到内核空间的拷贝操作,增加了延迟和CPU开销。而RDMA技术的出现在一定程度上解决了这个问题。 RDMA的实现需要支持RDMA的网卡和适配器,以及RDMA协议栈。RDMA协议栈通常由三个主要组件组成:传输层、网络层和传输服务层。其中传输层主要负责数据的可靠传输,如RDMA传输协议DCTP(Datagram Congestion Control Protocol);网络层负责路由和寻址,包括IP、IB(InfiniBand)等;传输服务层则提供上层应用程序使用的API。而RDMA的核心操作则是RDMA read和RDMA write,用于实现对远程内存的直接读写访问。 在RDMA原理分析和技术实现的PDF中,通常会介绍RDMA的基本概念、工作原理和通信过程等内容。首先会讲解RDMA的基本原理和优势,解释RDMA如何绕过内核,直接访问内存。接着会详细介绍RDMA的传输层、网络层和传输服务层的组成和功能。同时也会介绍DCTP协议的工作原理和优化策略,如流控制、拥塞控制等。 此外,PDF中还会介绍如何使用RDMA技术实现高性能的应用程序通信。这部分会重点介绍RDMA的编程模型和API,如Verbs API等,以及如何利用RDMA技术优化数据传输的方法。此外,还会介绍RDMA技术在不同领域的应用案例,如分布式存储、机器学习等。 综上所述,RDMA的原理分析和技术实现PDF会详细介绍RDMA的工作原理、协议栈和通信过程,以及如何使用RDMA技术实现高性能的应用程序通信。通过阅读该PDF,读者可以深入了解RDMA技术,并应用于实际的系统开发中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值