在虚拟机环境中,将普通网卡配置为 SoftRoCE 设备可以帮助你在没有实际硬件 RDMA 设备的情况下测试和体验 RDMA 功能。SoftRoCE 是 RoCE(RDMA over Converged Ethernet)协议的一个软件实现。
基础知识参考博文:
一文带你了解什么是RDMA
RDMA 高性能架构基本原理与设计方案
RDMA之RoCE & Soft-RoCE_software roce
如何使用rdma-core来实现RDMA操作
一、在虚拟机上把普通网卡配置成softroce设备
1.1 安装所需软件包
首先,确保你的系统上已安装必要的软件包。你需要安装 rdma-core
和 rdma
工具包。
详细可参考:
如何使用rdma-core来实现RDMA操作
在基于 Debian 的系统上(如 Ubuntu):
sudo apt-get update
sudo apt-get install rdma-core rdma
在基于 Red Hat 的系统上(如 CentOS):
sudo yum install rdma-core rdma
1.2 加载 SoftRoCE 模块
cat /boot/config-$(uname -r) | grep RXE
后面显示m或者y为成功
如果该选项值为n或者搜索不到RXE,那么很遗憾你可能需要重新编译内核。编译内核时需要使能以下几个选项:
CONFIG_INET
CONFIG_PCI
CONFIG_INFINIBAND
CONFIG_INFINIBAND_VIRT_DMA
至于具体的重新编译内核的方法,读者可以先自行查找,以后我也会在另外的文章详细的讲解。
如果版本跟我不一致的话,那么可以尝试安装一下以下几个软件包:
sudo apt-get install libibverbs1 ibverbs-utils librdmacm1 libibumad3 ibverbs-providers rdma-core
如果想看一下软件包里都包括哪些内容,那么可以使用dpkg命令查看包内容,比如:
dpkg -L libibverbs1
可以看到版本是28.0(截至3月28日,rdma-core的最新版本是v34.0):
安装完上述软件之后,可以执行ibv_devices看看有没有报错:
这是个基于verbs接口编写的小程序,用来获取并打印出当前系统中的RDMA设备列表(现在当然是空的,因为我们还没有添加Soft-RoCE设备)。
iproute2是用来替代net-tools软件包的,是一组开源的网络工具集合,比如用更强大ip命令替换了以前常用的ifconfig。我们需要其中的rdma工具来对RXE进行配置。一般的操作系统都已经包含了,安装也很简单:
sudo apt-get install iproute2
perftest是一个基于Verbs接口开发的开源RDMA性能测试工具,可以对支持RDMA技术的节点进行带宽和时延测试。相比于rdma-core自带的示例程序 ,功能更加强大,当然也更复杂。使用如下命令安装:
sudo apt-get install perftest
1.3 将网卡配置为 SoftRoCE 设备,配置RXE网卡
首先我们需要加载内核驱动,modprobe会自动加载依赖的其他驱动。
modprobe rdma_rxe
假设你要将名为 eth0
的网卡配置为 SoftRoCE 设备。可以使用 rdma link add
命令:
sudo rdma link add rxe0 type rxe netdev eth0
rxe0
:SoftRoCE 设备的名称,可以根据需要命名。eth0
:要配置为 SoftRoCE 的网络接口名称,替换为你实际的网络接口名称。
接着我们用rdma工具查看是否添加成功:
rdma link
效果如下:
如果显示不出来以上效果,说明添加失败或者没有添加
sudo rdma link add rxe_0 type rxe netdev ens33Unknown link command ‘add‘.(完美解决)
如果无法使用 rdma link
命令,可以尝试手动配置 SoftRoCE 设备。
sudo modprobe rdma_rxe
sudo rxe_cfg add ens33 sudo rxe_cfg start
这些命令将手动加载RDMA RXE模块并启动RXE设备配置工具。
接着我们用rdma工具查看是否添加成功:
rdma link
也可以跑下ibv_devices程序,可以看到已经在设备列表里了
ibv_devices
效果如下:
ibv_devinfo -d rxe0
效果如下:
看到这里,那就恭喜你,你的设备部署成功了
这里就可以成功运行rdma-core中的示例代码了
二、常用工具和示例代码:
此时rdma-core/build/bin中的示例代码我们就可以使用了
2.1 rping
rping
是一个用于测试两个 RDMA(Remote Direct Memory Access)节点之间连通性的示例程序。它属于 RDMA 连接管理库 librdmacm
,并包含在 librdmacm-utils
中。rping
工具可以用于发送 RDMA 流量,支持所有的 RDMA 驱动协议,包括 InfiniBand、RoCE 和 iWARP。
1. rping 的用途:
rping
工具主要用于:
- 测试两个 RDMA 节点之间的连通性。
- 发送和接收 RDMA 流量,验证 RDMA 设备的功能性。
- 支持不同的 RDMA 协议(InfiniBand、RoCE 和 iWARP),用于不同的网络架构。
2. 客户端模式:
在客户端(client)运行 rping
:
rping -c -a 《服务器ip》 10 -v -S 30
1. -c:客户端模式。指定 rping 以客户端模式运行。
2. -a 《服务器ip》:指定服务器的 IP 地址是 《服务器ip》。客户端将尝试连接到这个地址的 RDMA 服务器。
3. -C 10:指定进行 10 次 ping 操作。客户端将发送 10 个 RDMA ping 请求。
4. -v:详细模式。启用详细输出模式,显示更多的调试信息。
5. -S 30:指定发送的消息大小为 30 字节。
这个输出显示每个 ping 请求和响应的详细信息,以及最终的平均往返时间(RTT)。
1. ping data: rdma-ping-0: ABCDEFGHIJKLMNOP: 第一个 ping 请求发送的数据内容是 ABCDEFGHIJKLMNOP,这是一个 16 字节的字符串(假设默认情况下 rping 发送的消息大小为 16 字节)。
2. ping data: rdma-ping-1: BCDEFGHIJKLMNOPQ: 第二个 ping 请求发送的数据内容是 BCDEFGHIJKLMNOPQ,这是在第一个字符串基础上右移一位的结果。
3. ping data: rdma-ping-2: CDEFGHIJKLMNOPQR: 第三个 ping 请求发送的数据内容是 CDEFGHIJKLMNOPQR,这是在第二个字符串基础上右移一位的结果。
4. 依此类推: 每个后续请求的数据内容都是在前一个字符串基础上右移一位。
rping
使用了一个简单的模式来生成每个 ping 请求的数据内容,方便在测试时辨别和校验。这个模式是每次发送的数据内容在前一个请求数据内容的基础上右移一位。这样可以确保每个请求的数据内容是唯一的,并且容易跟踪和调试。
运行这个命令的前提是:
1. 目标 IP 地址 《服务器ip》上有一个 RDMA 服务器在监听。
2. RDMA 设备和相关驱动已经正确安装和配置。
3. 网络配置允许 RDMA 连接。
3. 服务器模式:
在客户端(server)运行 rping
:
rping -s -v -P
-s:服务器模式 此选项将 rping 命令配置为服务器模式。在这种模式下,rping 将等待来自客户端的连接请求。
-v:详细模式 启用详细输出模式。这将使 rping 输出更多的调试和状态信息,有助于了解测试的具体过程和状态。
-P:持续接收模式 在服务器端,-P 选项指定 rping 不退出并持续运行,即使连接已经关闭。这适用于需要长时间进行 RDMA 性能测试或调试的场景,服务器在每次连接结束后继续等待新的客户端连接。
1. server ping data: rdma-ping-0: ABCDEFGHIJKLMNOP 这是服务器端接收到的第一个 ping 数据包的内容,数据为 ABCDEFGHIJKLMNOP。
2. server ping data: rdma-ping-1: BCDEFGHIJKLMNOPQ 这是服务器端接收到的第二个 ping 数据包的内容,数据为 BCDEFGHIJKLMNOPQ。
3. 依此类推: 后续的 ping 数据包内容依次为 CDEFGHIJKLMNOPQR、DEFGHIJKLMNOPQRS 等,每个数据包的内容都在前一个基础上右移一位。
rping -s -v -P
将 rping
配置为一个详细模式的服务器,可以持续等待多个客户端连接。
结合客户端命令 rping -c
,可以进行 RDMA 连接的性能测试和调试。
2.2 ibv_devinfo
功能:显示本地 InfiniBand 设备的信息,包括设备名称、固件版本、端口数和端口状态等。
用法:直接运行 ibv_devinfo
。
示例:
ibv_devinfo
1. HCA(Host Channel Adapter)信息
(1)hca_id: rxe0 解释:HCA 设备的标识符。在这个例子中,设备标识符是 rxe0。
(2)transport: InfiniBand (0) 解释:传输类型。在这个例子中,传输类型是 InfiniBand。 (3)fw_ver: 0.0.0 解释:固件版本。在这个例子中,固件版本是 0.0.0。
(4)node_guid: 020c:29ff:fe8c:368a 解释:节点 GUID(全局唯一标识符),用于唯一标识这个 HCA 节点。
(5)sys_image_guid: 020c:29ff:fe8c:368a 解释:系统映像 GUID,通常与 node_guid 相同,用于标识系统映像。
(6)vendor_id: 0x0000 解释:供应商 ID,这里是 0x0000,表示未指定或通用供应商。
(7)vendor_part_id: 0 解释:供应商部件 ID,这里是 0,表示未指定或通用部件。
(8)hw_ver: 0x0 解释:硬件版本,这里是 0x0,表示未指定或通用硬件版本。
(9)phys_port_cnt: 1 解释:物理端口数量。在这个例子中,HCA 有一个物理端口。
2. 端口信息
port: 1
:端口 1 的详细信息
state
:PORT_ACTIVE (4)
- 解释:端口状态,这里是
PORT_ACTIVE
,表示端口处于活动状态。数字(4)
是状态的内部代码。
max_mtu
:4096 (5)
- 解释:端口支持的最大 MTU(最大传输单元),这里是
4096
字节。数字(5)
是 MTU 的内部代码。
active_mtu
:1024 (3)
- 解释:端口当前活动的 MTU,这里是
1024
字节。数字(3)
是 MTU 的内部代码。
sm_lid
:0
- 解释:子网管理器(Subnet Manager)LID(本地标识符),这里是
0
,表示没有指定子网管理器。
port_lid
:0
- 解释:端口的 LID,这里是
0
,表示没有指定 LID。
port_lmc
:0x00
- 解释:端口的 LMC(链路多播计数器),这里是
0x00
,表示没有设置多播。
link_layer
:Ethernet
- 解释:链路层类型,这里是 Ethernet,表示该端口使用以太网链路层。
2.3 ibv_devices
功能:列出系统上所有可用的 InfiniBand 设备。
用法:直接运行 ibv_devices。
示例:
ibv_devices
device:设备名称为rxe0
020c29fffe8c368a:节点 GUID为 020c29fffe8c368a
rxe0
是一个 SoftRoCE(Software RDMA over Converged Ethernet)设备,它允许在标准以太网硬件上实现 RDMA 功能。这个设备使得 RDMA 应用程序可以在没有专用 RDMA 硬件的情况下,通过现有的以太网网络运行和测试。
2.4 ibv_rc_pingpong
功能:使用可靠连接(RC)模式进行 ping-pong 测试,测量 RDMA 读写操作的延迟和带宽。
用法:
服务器端:
ibv_rc_pingpong
本地地址信息:
- LID (Local Identifier):
0x0000
表示在 InfiniBand 网络中该节点的本地标识符。0x0000
通常表示未配置或默认的 LID。- QPN (Queue Pair Number):
0x000011
是队列对编号,用于标识 RDMA 连接中的特定队列对。- PSN (Packet Sequence Number):
0xa80f45
是数据包序列号,用于追踪发送数据包的顺序。- GID (Global Identifier):
::
是一个全零地址,表示未指定的全球标识符。
错误信息:
- Failed to modify QP to RTR: 无法将队列对(QP)状态修改为 RTR(Ready to Receive,准备接收)。
- Couldn't connect to remote QP: 无法连接到远程队列对(QP)。
客户端:
ibv_rc_pingpong <server_ip>
本地地址信息:
- LID (Local Identifier):
0x0000
表示在 InfiniBand 网络中该节点的本地标识符。0x0000
通常表示未配置或默认的 LID。- QPN (Queue Pair Number):
0x000011
是队列对编号,用于标识 RDMA 连接中的特定队列对。- PSN (Packet Sequence Number):
0x08c292
是数据包序列号,用于追踪发送数据包的顺序。- GID (Global Identifier):
::
是一个全零地址,表示未指定的全球标识符。
客户端读/写状态 :
- Client read/write: Success: 客户端读写操作成功。
- Couldn't read/write remote address: 无法读取或写入远程地址,这可能是由于远程地址配置错误或连接出现问题。