#memory-region #async-api #rdma #networking #connection #abstraction #event-listener

async-rdma

RDMA ibvers 库的 Rust 异步封装

5 个版本 (破坏性更新)

0.5.0 2023年2月1日
0.4.0 2022年9月7日
0.3.0 2022年7月5日
0.2.0 2022年4月18日
0.1.0 2022年2月19日

#407 in 异步

每月下载量 31 次

自定义许可证

405KB
7K SLoC

async-rdma

一个用于编写具有高级抽象和异步 API 的 RDMA 应用程序的框架。

Join the chat at https://gitter.im/datenlord/async-rdma Crates.io Docs GPL licensed Build Status

它提供了一些主要组件

  • 例如 RdmaBuilder 的用于与 rdma 端点建立连接的工具。

  • 包括 readwritesendreceive 的高级 API 用于端点之间的数据传输。

  • 包括 alloc_local_mrrequest_remote_mrsend_mrreceive_local_mrreceive_remote_mr 的高级 API 用于 rdma 内存区域管理。

  • 包括在 API 背后工作的 agentevent_listener 框架,用于内存区域管理和执行类似 post_sendpoll 的 rdma 请求。

ChangeLog 文件中包含了每个版本变更的简要总结。

环境配置

本节面向想要尝试此库的 RDMA 初学者。

如果您已经配置了 RDMA,则可以跳过此部分。

接下来,我们将配置 Ubuntu20.04 虚拟机上的 RDMA 环境。如果您使用的是其他操作系统发行版,请搜索并替换相应的命令。

1. 检查当前内核是否支持 RXE

运行以下命令,如果CONFIG_RDMA_RXE = ym,则当前操作系统支持RXE。如果不支持,则需要搜索如何重新编译内核以支持RDMA。

cat /boot/config-$(uname -r) | grep RXE

2. 安装依赖项

sudo apt install -y libibverbs1 ibverbs-utils librdmacm1 libibumad3 ibverbs-providers rdma-core libibverbs-dev iproute2 perftest build-essential net-tools git librdmacm-dev rdmacm-utils cmake libprotobuf-dev protobuf-compiler clang curl

3. 配置RDMA netdev

(1) 加载内核驱动

modprobe rdma_rxe

(2) 用户模式RDMA netdev配置。

sudo rdma link add rxe_0 type rxe netdev ens33

rxe_0是RDMA设备名,您可以将其命名为任何您想要的名称。ens33是网络设备的名称。网络设备的名称可能因每个虚拟机而异,我们可以通过运行命令"ifconfig"来查看它。

(3) 检查RDMA设备状态

运行以下命令并检查状态是否为ACTIVE

rdma link

(4) 测试它

Ib_send_bw是用于测试RDMA SEND操作带宽的程序。

在终端中运行以下命令。

ib_send_bw -d rxe_0

然后在另一个终端中运行以下命令。

ib_send_bw -d rxe_0 localhost

4. 安装Rust

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source $HOME/.cargo/env

5. 尝试一个示例

git clone https://github.com/datenlord/async-rdma.git
cd async-rdma
cargo run --example rpc

示例

一个简单的示例:客户端请求远程内存区域,并通过rdma write将数据放入此远程内存区域。最后,客户端send_mr以使服务器了解此内存区域。服务器receive_local_mr,然后从该mr获取数据。

use async_rdma::{LocalMrReadAccess, LocalMrWriteAccess, RdmaBuilder};
use portpicker::pick_unused_port;
use std::{
    alloc::Layout,
    io::{self, Write},
    net::{Ipv4Addr, SocketAddrV4},
    time::Duration,
};

async fn client(addr: SocketAddrV4) -> io::Result<()> {
    let layout = Layout::new::<[u8; 8]>();
    let rdma = RdmaBuilder::default().connect(addr).await?;
    // alloc 8 bytes remote memory
    let mut rmr = rdma.request_remote_mr(layout).await?;
    // alloc 8 bytes local memory
    let mut lmr = rdma.alloc_local_mr(layout)?;
    // write data into lmr
    let _num = lmr.as_mut_slice().write(&[1_u8; 8])?;
    // write the second half of the data in lmr to the rmr
    rdma.write(&lmr.get(4..8).unwrap(), &mut rmr.get_mut(4..8).unwrap())
        .await?;
    // send rmr's meta data to the remote end
    rdma.send_remote_mr(rmr).await?;
    Ok(())
}

#[tokio::main]
async fn server(addr: SocketAddrV4) -> io::Result<()> {
    let rdma = RdmaBuilder::default().listen(addr).await?;
    // receive mr's meta data from client
    let lmr = rdma.receive_local_mr().await?;
    let data = *lmr.as_slice();
    println!("Data written by the client using RDMA WRITE: {:?}", data);
    assert_eq!(data, [[0_u8; 4], [1_u8; 4]].concat());
    Ok(())
}

#[tokio::main]
async fn main() {
    let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), pick_unused_port().unwrap());
    std::thread::spawn(move || server(addr));
    tokio::time::sleep(Duration::new(1, 0)).await;
    client(addr)
        .await
        .map_err(|err| println!("{}", err))
        .unwrap();
}

获取帮助

首先,看看您的答案是否可以在找到的API文档设计文档中找到。如果答案不在这里,请打开一个问题并详细描述您的问题。

  • rdma-sys:RDMA基本库的Rust绑定:libibverbs-dev和librdmacm-dev。

依赖项

~10–25MB
~319K SLoC