一.编译
1.下载内核源码并编译RXE内核模块
vim /etc/apt/sources.list
sudo apt update
sudo apt-get install dpkg-dev
进入内核源码网站下载:三个安装包
linux (6.12.95-1) - snapshot.debian.org
linux_6.12.95‑1.dsc
linux_6.12.95.orig.tar.xz
linux_6.12.95‑1.debian.tar.xz
dpkg‑source -x linux_6.12.95‑1.dsc
进入/home/zhuwei/6.12.95.1/linux-6.12.95/drivers/infiniband/sw/rxe
make -C /lib/modules/$(uname -r)/build M=$(pwd) CONFIG_RDMA_RXE=m modules
insmod ./rdma_rxe.ko
上图没有加载依赖包。
modprobe ./rdma_rxe.ko //自动加载依赖包,加载成功
2.编译用户态softRoce
git clone https://github.com/linux-rdma/rdma-core.git
安装编译依赖工具:
apt install -y build-essential cmake pkg-config git libnl-3-dev libnl-route-3-dev libudev-dev libsystemd-dev
apt install python3-dev
apt install python3-cytho*
cd /home/zhuwei/user_linux_softRoce/rdma-core
./build.sh
或者
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/rdma-core -DCMAKE_BUILD_TYPE=Debug -DENABLE_STATIC=OFF -DNO_MAN_PAGES=ON
make
make install
echo "/usr/local/rdma-core/lib" > /etc/ld.so.conf.d/rdma-core-local.conf
ldconfig
export PATH=/usr/local/rdma-core/bin:/usr/local/rdma-core/sbin:$PATH
echo 'export PATH=/usr/local/rdma-core/bin:/usr/local/rdma-core/sbin:$PATH' >> ~/.bashrc
source ~/.bashrc
二.环境部署
在服务器上安装两张虚拟网卡,在虚拟网卡上各自绑定RDMA网卡,配置地址自发自收。
modprobe ./rdma_rxe.ko
modprobe veth //veth = Virtual Ethernet Pair,虚拟以太网成对设备,内核模块名:veth。
ip link add my_vir_eth0 type veth peer name my_vir_eth1 //创建两个直连的虚拟网卡
ip addr add 192.168.100.10/24 dev my_vir_eth0
ip addr add 192.168.100.11/24 dev my_vir_eth1
ip link set my_vir_eth0 up
ip link set my_vir_eth1 up
创建rdma 网卡并分别绑定在虚拟网卡上(以下两条命令一起复制执行,不然会报错,网络多命名空间问题)
rdma link add rdma_rxe0 type rxe netdev my_vir_eth0
rdma link add rdma_rxe1 type rxe netdev my_vir_eth1
rdma link show
ibv_devinfo
# 删除rxe设备
rdma link delete rdma_rxe0
rdma link delete rdma_rxe1
# 删除veth pair,删一端就全部消失
ip link delete my_vir_eth0
//使用命名空间版本:
ip netns add ns0
ip netns add ns1
ip link set my_vir_eth0 netns ns0
ip link set my_vir_eth1 netns ns1
ip netns exec ns0 ip addr add 192.168.100.10/24 dev my_vir_eth0
ip netns exec ns0 ip link set my_vir_eth0 up
ip netns exec ns1 ip addr add 192.168.100.11/24 dev my_vir_eth1
ip netns exec ns1 ip link set my_vir_eth1 up
ip netns exec ns0 ip a
ip netns exec ns1 ip a
rdma link list
# ns0 启动ib_write_bw服务端(CM模式)
ip netns exec ns0 ib_write_bw -d rxe0 -R --report_gbits
# ns1客户端连接
ip netns exec ns1 ib_write_bw -d rxe1 -R 192.168.100.10 --report_gbits
三.调试
使用原生态工具ping包
ibv_rc_pingpong -d rdma_rxe1 -g 0 -n 10000 //服务端
ibv_rc_pingpong -d rdma_rxe0 -g 0 -n 10000 192.168.100.11 //客户端
ibstat查看ib网卡,由于ROCE二层走的是以太,所以没有lid(即不用纯IB的opensm协议)
四.源码学习
1.基本框架
2.支持热插拔
注册rdma-core的内核netlink机制,即core/nldev.c,用户有动态绑定设备即走这个流程。
rxe_newlink回调rxe,rxe再去rxe_net_add注册core新设备。
rdma/core这种机制是如何实现的?待补充
3.用户态libibverbs.so的基本框架
即rdma-core-softRoce\rdma-core\libibverbs代码。
3.1基本数据结构
由于涉及到ib_device,所以用户态libibverbs肯定是需要厂商参与修改代码的,每个网卡厂商都需要提供libibverbs相关内容。在rdma-core-softRoce\rdma-core\providers中,这里softroce使用rte实现代码:
rte.c:
源文件中还实现其他细节:以创建CQ为例:rxe_create_cq-->ibv_cmd_create_cq->execute_ioctl-->内核。即rte.c是libibverbs.so和内核交互的接口。
3.2.执行perftest的ib_write_bw后台用户态到底发生了什么?
perftest翻译命令行后,做查找dev(命令绑定的RDMA网卡信息):
ibv_get_device_list调用即为libibverbs.so中init.c中的函数扫描/sys/class/infiniband_verbs中的所有rdma网卡device,扫描后在libibverbs.so家里一个device-list。(此步骤无内核交互)
接着perftest调用ibv_open_device
ibv_open_device调用libibvers.so中的verbs_open_device(另外还创建一个字符驱动)
继续调用到libibverbs.so中的rxe_alloc_context,即rte.c中:
rte.c中挂了很多ibv_context中的ops供用户态最终调用
综上,用户态调用libibverbs.so中封装的函数,---->rte.c----ioctl--->内核verbs--内核rdma-core->内核rxe_verbs.c。