Giter VIP home page Giter VIP logo

rust-ibverbs's Introduction

ibverbs

Crates.io Documentation codecov Dependency status

Rust API wrapping the ibverbs Remote Direct Memory Access (RDMA) library.

libibverbs is a library that allows userspace processes to use RDMA "verbs" to perform high-throughput, low-latency network operations for both Infiniband (according to the Infiniband specifications) and iWarp (iWARP verbs specifications). It handles the control path of creating, modifying, querying and destroying resources such as Protection Domains, Completion Queues, Queue-Pairs, Shared Receive Queues, Address Handles, and Memory Regions. It also handles sending and receiving data posted to QPs and SRQs, and getting completions from CQs using polling and completions events.

A good place to start is to look at the programs in examples/, and the upstream C examples. You can test RDMA programs on modern Linux kernels even without specialized RDMA hardware by using SoftRoCE.

For the detail-oriented

The control path is implemented through system calls to the uverbs kernel module, which further calls the low-level HW driver. The data path is implemented through calls made to low-level HW library which, in most cases, interacts directly with the HW provides kernel and network stack bypass (saving context/mode switches) along with zero copy and an asynchronous I/O model.

iWARP ethernet NICs support RDMA over hardware-offloaded TCP/IP, while InfiniBand is a general high-throughput, low-latency networking technology. InfiniBand host channel adapters (HCAs) and iWARP NICs commonly support direct hardware access from userspace (kernel bypass), and libibverbs supports this when available.

For more information on RDMA verbs, see the InfiniBand Architecture Specification vol. 1, especially chapter 11, and the RDMA Consortium's RDMA Protocol Verbs Specification. See also the upstream libibverbs/verbs.h file for the original C definitions, as well as the manpages for the ibv_* methods.

Library dependency

libibverbs is usually available as a free-standing library package. It used to be self-contained, but has recently been adopted into rdma-core. cargo will automatically build the necessary library files and place them in vendor/rdma-core/build/lib. If a system-wide installation is not available, those library files can be used instead by copying them to /usr/lib, or by adding that path to the dynamic linking search path.

Thread safety

All interfaces are Sync and Send since the underlying ibverbs API is thread safe.

Documentation

Much of the documentation of this crate borrows heavily from the excellent posts over at RDMAmojo. If you are going to be working a lot with ibverbs, chances are you will want to head over there. In particular, this overview post may be a good place to start.

rust-ibverbs's People

Contributors

0x61nas avatar bionicles avatar chapeupreto avatar dependabot[bot] avatar gipsyh avatar iwahbe avatar jmchacon avatar jonhoo avatar joshka avatar kuenishi avatar mathiaspius avatar mrkatebzadeh avatar planeta avatar rdelfin avatar rtkay123 avatar simenb avatar tudyx avatar wasabi375 avatar ytvwld avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rust-ibverbs's Issues

Some question for the meaning of designing 3 lifetime of cq, pd and qp

I'm writing some IBStream like below

pub struct IBStream<'a> {
    qp: Arc<ibverbs::QueuePair<'a>>,
    cq: Arc<ibverbs::CompletionQueue<'a>>,
    mr: ibverbs::MemoryRegion<RdmaPrimitive>,
    pd: Arc<ibverbs::ProtectionDomain<'a>>,
    ctx: Arc<ibverbs::Context>,
}

and if I want to write the new func:

    pub fn new<'b, A: ToSocketAddrs>(addr: A) -> Result<IBStream<'b>, IBError> {
        let ctx = Self::setup_ctx()?;
        let ctxr: & _ = &ctx;
        let cq = Self::setup_cq(ctxr)?;
        let pd = Self::setup_pd(&ctx.clone())?;
        let qp = Self::setup_qp(&cq.clone(), &pd.clone(), &ctx.clone())?;

        let mr = pd.allocate::<RdmaPrimitive>(2).unwrap();
        Ok(IBStream {
            qp,
            cq,
            mr,
            pd,
            ctx,
        })
    }

The lifetime of ctx is in accordance with the whole struct and could not specify any lifetime hint to make it happen. But if I roll back to this version and remove the lifetime, the code compiled nice and sound. If I have to keep using the latest version, I have to take the ctx out of IBStream.

RFC: Integration testing

I really appreciate this library but there is one thing which concerns me: integration testing.

I'm looking for feedback on the desired approach here (or alternatives if you think of any).

To be clear, I don't really feel that unit testing is especially problematic in this case: bindgen takes care of
validating the bindings and upstream rdma-core is already well tested in its own right. That said, there are a number of really handy convenience methods and data structures which I would like to help test.

I iterated through several options for integration testing here and I have basically concluded "it is going to be hard."
Still, that doesn't mean I shouldn't try.

Options

  1. Vagrant virtual machines + SoftRoCE: workable but a bit heavy.
    This will require significant tooling work and is likely to be really problematic if ya want to continue to use a
    tool like TravisCI.

  2. Docker container + SoftRoCE: workable, not super portable, challenging for CI.
    In the name of experimentation, I cooked up a debian-bullseye container which builds the project, sets up a
    SoftRoCE interface, and runs a few integration tests. The problem is that RDMA is, at its heart, a hardware offload.
    Even with SoftRoCE you are just emulating a hardware offload. As long as you are using the host's Kernel (as would
    be the case for most container technologies) then the container is really only buying you a consistent development
    environment; not a consistent deployment environment. For example, if the CI system hasn't loaded the SoftRoCE
    module (rxe) then the container won't work anyway. Packaging the SoftRoCE kernel module with the container is
    useless due to ABI compatibility problems with differing kernel versions. You might be able to somehow overlay mount
    /lib/modules/ from the host and use DKMS to build and load the SoftRoCE module on a per kernel basis but this seems
    like a huge pain. At the very least this will be very difficult to make reliable and portable.

    In my experience the best way to ensure tests never get written is to make them a huge pain to write and maintain.

    Oh, one more problem: RDMA devices are not (by default) network namespaced. Even when I enable RDMA namespacing, I
    can't seem to get SoftRoCE devices to move namespaces. Thus my dream of setting up something like mininet for RoCE
    doesn't seem viable currently.

  3. Bash script sets up SoftRoCE device, assume developer has taken care of the kernel config: not ideal but I think it
    is the best available choice at the moment.

    I have already composed a simple bash script which sets up a single SoftRoCE device. This isn't really portable
    either and it requires that the developer already have rdma-core installed (it requires iproute2 and the rdma
    command). I don't know how CI would react to this configuration.

Thoughts?

EINVAL error on PreparedQueuePair build

Hello,

I'm trying out the library for a project, for now doing some tests using Soft-RoCE on a pair of Ubuntu20.10 VMs.

I cloned the repo and ran the example, and I inconsistently encounter the following error:
panicked at 'called Result::unwrap() on an Err value: Os { code: 22, kind: InvalidInput, message: "Invalid argument" }', ibverbs/examples/loopback.rs:16:10.

The code that gives the issue is
let qp_builder = pd.create_qp(&cq, &cq, ibverbs::ibv_qp_type::IBV_QPT_RC).build().unwrap();,
in particular the call in .build() to ibv_create_qp. I've run it through the debugger and have not been able to spot any differences between successful and unsuccessful runs.

I would say it happens about 50% of the time, and for the rest the code runs fine. Even more strangely, I tried moving the Protection Domain memory allocation code above the queue pair builder and found that it fixed the issue, but I have no idea why:

let mut mr = pd.allocate::<u64>(2).unwrap();
mr[1] = 0x42;

let qp_builder = pd.create_qp(&cq, &cq, ibverbs::ibv_qp_type::IBV_QPT_RC).build().unwrap();

System details:

I'm using this Vagrant VM image and the rdma_rxe driver for Soft-RoCE, which I load using sudo modload rdma_rxe before adding a soft-roce device: sudo rdma link add rxe_0 type rxe netdev eth1. I've tested the setup using ib_send_bw, which works.

Any idea what could be causing the problem?

Does not seem to support cross-compilation

I came across your bindings and decided to give them a whirl - I was almost going to create my own!

However, I can't get them to build. I'm using Mac OS X, with a local linux / musl toolchain (installed via brew install filosottile/musl-cross/musl-cross). Its works well, and I used it to cross-build nvml, bearssl, DPDK, libfabric and others... however, the build.rs doesn't seem to respect --target from cargo, and so consequently fails. (I'm not entirely sure that's the case, though).

I realise it's early days for this binding, so it's probably something that's not on the radar yet, and might be something you don't want to cope with.

Compilation failure

Hello,

when I try to compile rust-ibverbs, I get an error with the following error message during compilation of the rdma-core package.

Scanning dependencies of target sminfo
Scanning dependencies of target saquery
Scanning dependencies of target ibtracert
Scanning dependencies of target ibcacheedit
Scanning dependencies of target testleaks
In file included from /home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/build/include/ccan/minmax.h:7,
                 from /home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/librdmacm/cma.h:48,
                 from /home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/librdmacm/acm.c:43:
/home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/librdmacm/acm.c: In function 'ucma_ib_init':
Scanning dependencies of target perfquery
/home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/build/include/ccan/build_assert.h:23:26: error: size of unnamed array is negative
   23 |  do { (void) sizeof(char [1 - 2*!(cond)]); } while(0)
      |                          ^
/home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/librdmacm/acm.c:105:3: note: in expansion of macro 'BUILD_ASSERT'
  105 |   BUILD_ASSERT(sizeof(IBACM_SERVER_PATH) <=
      |   ^~~~~~~~~~~~
Scanning dependencies of target ibsysstat
Scanning dependencies of target ibccquery
Scanning dependencies of target ibqueryerrors
Scanning dependencies of target dump_fts
Scanning dependencies of target smpquery
Scanning dependencies of target ibportstate
Scanning dependencies of target ibstat
Scanning dependencies of target smpdump
Scanning dependencies of target ibnetdiscover
Scanning dependencies of target ibping
Scanning dependencies of target ibccconfig
Scanning dependencies of target ibroute
Scanning dependencies of target iblinkinfo
Scanning dependencies of target ibaddr
In file included from /home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/build/include/ccan/minmax.h:7,
                 from /home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/ibacm/linux/osd.h:48,
                 from /home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/ibacm/src/acm.c:38:
/home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/ibacm/src/acm.c: In function 'acm_listen':
/home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/build/include/ccan/build_assert.h:23:26: error: size of unnamed array is negative
   23 |  do { (void) sizeof(char [1 - 2*!(cond)]); } while(0)
      |                          ^
/home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/ibacm/src/acm.c:629:3: note: in expansion of macro 'BUILD_ASSERT'
  629 |   BUILD_ASSERT(sizeof(IBACM_IBACME_SERVER_PATH) <=
      |   ^~~~~~~~~~~~
In file included from /home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/build/include/ccan/minmax.h:7,
                 from /home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/ibacm/linux/osd.h:48,
                 from /home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/ibacm/src/libacm.c:33:
/home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/ibacm/src/libacm.c: In function 'ib_acm_connect_unix':
Scanning dependencies of target vendstat
/home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/build/include/ccan/build_assert.h:23:26: error: size of unnamed array is negative
   23 |  do { (void) sizeof(char [1 - 2*!(cond)]); } while(0)
      |                          ^
/home/mplaneta/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/ibacm/src/libacm.c:107:3: note: in expansion of macro 'BUILD_ASSERT'
  107 |   BUILD_ASSERT(sizeof(IBACM_IBACME_SERVER_PATH) <=
      |   ^~~~~~~~~~~~
make[2]: *** [librdmacm/CMakeFiles/rdmacm.dir/build.make:82: librdmacm/CMakeFiles/rdmacm.dir/acm.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:2512: librdmacm/CMakeFiles/rdmacm.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
make[2]: *** [ibacm/CMakeFiles/ib_acme.dir/build.make:95: ibacm/CMakeFiles/ib_acme.dir/src/libacm.c.o] Error 1

The issue happens it this line:

  BUILD_ASSERT(sizeof(IBACM_SERVER_PATH) <=
                             sizeof(addr.unx.sun_path));

inside ~/.cargo/registry/src/github.com-1ecc6299db9ec823/ibverbs-sys-0.1.0/vendor/rdma-core/librdmacm/acm.c

The reason is that IBACM_SERVER_PATH generated during configure step is too long (>108 chars). And it is too long, because it is
<build directory>/var/run/ibacm.sock.

PreparedQueuePair Issue

// on host 1
let pqp: PreparedQueuePair = ...;
let host1end = pqp.endpoint();
host2.send(host1end);
let host2end = host2.recv();
let qp = pqp.handshake(host2end);

// on host 2
let pqp: PreparedQueuePair = ...;
let host2end = pqp.endpoint();
host1.send(host2end);
let host1end = host1.recv();
let qp = pqp.handshake(host1end);

According to my understanding, host 1 and host2 are bound to a process respectively. What work are done in the above, send and recv respectively, and how to use host2.send and recv on the process of host 1

[RFC] GUID byte-order

Hello,

ibv_get_device_guid returns GUID in "network byte order" [1], which means big endian.

On another hand, the Rust counterpart returns u64, which I expect to be in the host byte order, which is little endian on my system. I would suggest to convert the result of the C version into host order. What would be your thoughts?

  1. https://linux.die.net/man/3/ibv_get_device_guid

Project status

@jonhoo @daniel-noland wondering what plans you had for this crate. Are you planning to maintain this over time or is any company looking at sustaining the project?

[request] rdmacm crate

A similar wrapper crate for librdmacm (RDMA connection manager) would be nice as it greatly simplifies the connection setup for small applications. Being also handled by rdma-core it fits well under the same umbrella as ibverbs.

RDMA Core update

Would it be possible to pull in a newer version of rdma-core? The commit is pinned at 3yrs ago and I think since then some new verbs have been introduced. I'm looking to get support for read+write. They're apparently faster then Receive/Send because they don't notify the remote end.

Mismatch between bindgen output and ffi.rs

Hi Jon,

I'm trying to compile this on one of our IB machines and it looks like there's some mismatch between the bindgen bindings and ffi.rs: rustc output follows. I'd gladly help tracking this down / fixing it but some pointers (if you have any) would be extremely useful (I've never used bindgen).

Thanks!

(Oh and congrats/good luck with the submission.)

   Compiling ibverbs v0.3.0 (file:///home/andreal/Src/rust-ibverbs)
error[E0412]: cannot find type `ibv_send_wr__bindgen_ty_3` in this scope
   --> src/ffi.rs:364:18
    |
364 | impl Default for ibv_send_wr__bindgen_ty_3 {
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `ibv_send_wr__bindgen_ty_1`?

error[E0422]: cannot find struct, variant or union type `ibv_send_wr__bindgen_ty_3` in this scope
   --> src/ffi.rs:366:9
    |
366 |         ibv_send_wr__bindgen_ty_3 {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `ibv_send_wr__bindgen_ty_1`?

error[E0063]: missing field `xrc_domain` in initializer of `ffi::ibv_qp_init_attr`
   --> src/lib.rs:697:24
    |
697 |         let mut attr = ffi::ibv_qp_init_attr {
    |                        ^^^^^^^^^^^^^^^^^^^^^ missing `xrc_domain`

error[E0560]: struct `ffi::ibv_send_wr` has no field named `qp_type`
    --> src/lib.rs:1106:13
     |
1106 |             qp_type: Default::default(),
     |             ^^^^^^^^ `ffi::ibv_send_wr` does not have this field
     |
     = note: available fields are: `wr_id`, `next`, `sg_list`, `num_sge`, `opcode` ... and 4 others

error[E0560]: struct `ffi::ibv_send_wr__bindgen_ty_2` has no field named `xrc`
   --> src/ffi.rs:358:13
    |
358 |             xrc: Default::default(),
    |             ^^^^ `ffi::ibv_send_wr__bindgen_ty_2` does not have this field
    |
    = note: available fields are: `qp_type`, `xrc_remote_srq_num`, `bindgen_union_field`

error[E0560]: struct `ffi::ibv_qp_attr` has no field named `rate_limit`
   --> src/ffi.rs:402:13
    |
402 |             rate_limit: 0,
    |             ^^^^^^^^^^^ `ffi::ibv_qp_attr` does not have this field
    |
    = note: available fields are: `qp_state`, `cur_qp_state`, `path_mtu`, `path_mig_state`, `qkey` ... and 20 others

error[E0599]: no variant named `IBV_WC_LOCAL_INV` found for type `ffi::ibv_wc_opcode` in the current scope
    --> src/ffi.rs:411:21
     |
411  |             opcode: ibv_wc_opcode::IBV_WC_LOCAL_INV,
     |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ variant not found in `ffi::ibv_wc_opcode`
     |
    ::: /home/andreal/Src/rust-ibverbs/target/debug/build/ibverbs-9097a2a478619ab2/out/bindings.rs:1566:1
     |
1566 | pub enum ibv_wc_opcode {
     | ---------------------- variant `IBV_WC_LOCAL_INV` not found here

error: aborting due to 7 previous errors

error: Could not compile `ibverbs`.

To learn more, run the command again with --verbose.

Avoid CQ drop failures

I was running into an issue related to the Drop implementation for CompletionQueue objects. I am unsure if there is a good way to handle it, or if an API improvement can be made to avoid panic. Example:

fn main() {
    let ctx = ibverbs::devices()
        .unwrap()
        .iter()
        .next()
        .expect("no rdma device available")
        .open()
        .unwrap();

    let cq = ctx.create_cq(16, 0).unwrap();
    let pd = ctx.alloc_pd().unwrap();

    let _qp_builder = pd
        .create_qp(&cq, &cq, ibverbs::ibv_qp_type::IBV_QPT_RC)
        .build()
        .unwrap();

    // something bad happens, perhaps returning Err(...)

   
}  // CompletionQueue::Drop -> panic!

A common example of "something bad happens" is an application fails to send the serialized QueuePairEndpoint. In this case, I would like the function to return gracefully and everything resume operation. However, here the Drop of CompletionQueue will panic, I believe because the queue pair is still associated with it.

Is there any existing way to make the above drop happen gracefully?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.