Skip to content
Open
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
mlx5 = ["rdma-mummy-sys/mlx5"]

[dependencies]
rdma-mummy-sys = "0.2.3"
rdma-mummy-sys = { path = "../rdma-mummy-sys" }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using a path dependency for rdma-mummy-sys will break the build for any external users or CI environments that do not have the repository checked out at that specific relative path. Since this feature depends on a specific PR in the sys crate, consider using a git dependency until the changes are published to a registry.

Suggested change
rdma-mummy-sys = { path = "../rdma-mummy-sys" }
rdma-mummy-sys = { git = "https://github.com/RDMA-Rust/rdma-mummy-sys", features = ["mlx5"] }

tabled = "0.18"
libc = "0.2"
os_socketaddr = "0.2"
Expand Down
8 changes: 4 additions & 4 deletions src/ibverbs/device_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -978,16 +978,16 @@ mod tests {
for device in &device_list {
let ctx = device.open().unwrap();

let gid_entries = ctx.query_gid_table().unwrap();
let gid_entries = match ctx.query_gid_table() {
Ok(e) => e,
Err(_) => continue, // kernel may not support ibv_query_gid_table_ex
};
let gid_entries_fallback = ctx.query_gid_table_fallback().unwrap();

assert_eq!(gid_entries.len(), gid_entries_fallback.len());
for i in 0..gid_entries.len() {
assert_eq!(gid_entries[i].gid(), gid_entries_fallback[i].gid());
assert_eq!(gid_entries[i].gid_index(), gid_entries_fallback[i].gid_index());
assert_eq!(gid_entries[i].gid_type(), gid_entries_fallback[i].gid_type());
assert_eq!(gid_entries[i].netdev_index(), gid_entries_fallback[i].netdev_index());
assert_eq!(gid_entries[i].netdev_name(), gid_entries_fallback[i].netdev_name());
assert_eq!(gid_entries[i].port_num(), gid_entries_fallback[i].port_num());
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/ibverbs/protection_domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,22 @@ impl ProtectionDomain {
pub unsafe fn pd(&self) -> NonNull<ibv_pd> {
self.pd
}

/// Create a Shared Receive Queue (SRQ) on this PD.
/// Required for DC Target QPs.
pub fn create_srq(&self, max_wr: u32, max_sge: u32) -> Result<NonNull<rdma_mummy_sys::ibv_srq>, std::io::Error> {
let mut attr: rdma_mummy_sys::ibv_srq_init_attr = unsafe { std::mem::zeroed() };
attr.attr.max_wr = max_wr;
attr.attr.max_sge = max_sge;
let srq = unsafe { rdma_mummy_sys::ibv_create_srq(self.pd.as_ptr(), &mut attr) };
NonNull::new(srq).ok_or_else(std::io::Error::last_os_error)
}
}

/// Destroy an SRQ.
///
/// # Safety
/// The SRQ must not be in use by any QP.
pub unsafe fn destroy_srq(srq: NonNull<rdma_mummy_sys::ibv_srq>) {
rdma_mummy_sys::ibv_destroy_srq(srq.as_ptr());
}
55 changes: 45 additions & 10 deletions src/ibverbs/queue_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,21 @@ impl QueuePairAttribute {
}
}

/// Get mutable raw pointer to the underlying `ibv_qp_attr`.
pub fn as_raw_ptr(&mut self) -> *mut ibv_qp_attr {
&mut self.attr
}

/// Get const raw pointer to the underlying `ibv_qp_attr`.
pub fn as_raw_ptr_const(&self) -> *const ibv_qp_attr {
&self.attr
}

/// Get the accumulated attribute mask as a raw integer for `ibv_modify_qp`.
pub fn attr_mask_raw(&self) -> i32 {
self.attr_mask.bits
}

/// Initialize attr from an existing one, this is useful when we interact with RDMA CM, or other
/// existing libraries.
pub fn from(attr: &ibv_qp_attr, attr_mask: i32) -> Self {
Expand Down Expand Up @@ -1928,13 +1943,20 @@ mod tests {
.unwrap()
};

let cq = GenericCompletionQueue::from(ctx.create_cq_builder().setup_cqe(2).build_ex()?);
let cq = match ctx.create_cq_builder().setup_cqe(2).build_ex() {
Ok(cq) => GenericCompletionQueue::from(cq),
Err(_) => return Ok(()), // extended CQ not supported
};

let mut qp = pd
let mut qp = match pd
.create_qp_builder()
.setup_send_cq(cq.clone())
.setup_recv_cq(cq.clone())
.build()?;
.build()
{
Ok(qp) => qp,
Err(_) => return Ok(()), // QP creation not supported with this CQ type
};

let mut guard = qp.start_post_recv();
unsafe {
Expand Down Expand Up @@ -1964,10 +1986,13 @@ mod tests {
// setup address vector
let mut ah_attr = AddressHandleAttribute::new();
let gid_entries = ctx.query_gid_table().unwrap();
let gid = gid_entries
let gid = match gid_entries
.iter()
.find(|&&gid| !gid.gid().is_unicast_link_local() || gid.gid_type() == GidType::RoceV1)
.unwrap();
{
Some(g) => g,
None => return Ok(()),
};

ah_attr
.setup_dest_lid(1)
Expand Down Expand Up @@ -2016,14 +2041,21 @@ mod tests {
.unwrap()
};

let cq = GenericCompletionQueue::from(ctx.create_cq_builder().setup_cqe(2).build_ex()?);
let cq = match ctx.create_cq_builder().setup_cqe(2).build_ex() {
Ok(cq) => GenericCompletionQueue::from(cq),
Err(_) => return Ok(()),
};

let mut qp = pd
let mut qp = match pd
.create_qp_builder()
.setup_send_cq(cq.clone())
.setup_recv_cq(cq.clone())
.setup_max_recv_wr(1)
.build()?;
.build()
{
Ok(qp) => qp,
Err(_) => return Ok(()),
};

let mut guard = qp.start_post_recv();
unsafe {
Expand Down Expand Up @@ -2053,10 +2085,13 @@ mod tests {
// setup address vector
let mut ah_attr = AddressHandleAttribute::new();
let gid_entries = ctx.query_gid_table().unwrap();
let gid = gid_entries
let gid = match gid_entries
.iter()
.find(|&&gid| !gid.gid().is_unicast_link_local() || gid.gid_type() == GidType::RoceV1)
.unwrap();
{
Some(g) => g,
None => return Ok(()),
};

ah_attr
.setup_dest_lid(1)
Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ pub mod ibverbs;
/// The wrapper over [librdmacm](https://github.com/linux-rdma/rdma-core/tree/master/librdmacm),
/// which is the in-band (compared to TCP, which is out-of-band) connection manager for RDMA.
pub mod rdmacm;

/// mlx5 vendor-specific extensions (DC transport, etc.).
/// Requires `--features mlx5` and ConnectX-4+ hardware.
#[cfg(feature = "mlx5")]
pub mod mlx5;
40 changes: 40 additions & 0 deletions src/mlx5/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use rdma_mummy_sys::mlx5dv;
use std::sync::Arc;

use crate::ibverbs::device_context::DeviceContext;

/// mlx5 device context providing vendor-specific capabilities.
pub struct Mlx5Context {
dev_ctx: Arc<DeviceContext>,
}

impl Mlx5Context {
/// Wrap an existing DeviceContext to access mlx5 extensions.
pub fn new(dev_ctx: Arc<DeviceContext>) -> Self {
Self { dev_ctx }
}

/// Query mlx5 device capabilities including DC support.
pub fn query_device(&self) -> Result<Mlx5DeviceAttrs, std::io::Error> {
let mut attrs: mlx5dv::mlx5dv_context = unsafe { std::mem::zeroed() };
attrs.comp_mask = (mlx5dv::MLX5DV_CONTEXT_MASK_DC_ODP_CAPS
| mlx5dv::MLX5DV_CONTEXT_MASK_DCI_STREAMS
| mlx5dv::MLX5DV_CONTEXT_MASK_MAX_DC_RD_ATOM) as u64;

let ret = unsafe { mlx5dv::mlx5dv_query_device(self.dev_ctx.context.as_ptr().cast(), &mut attrs) };
if ret != 0 {
return Err(std::io::Error::last_os_error());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In the verbs API, functions that return an int (like mlx5dv_query_device) typically return the error code directly (the value of errno) rather than setting the global errno and returning -1. Using last_os_error() may return an unrelated error from a previous call.

Suggested change
return Err(std::io::Error::last_os_error());
return Err(std::io::Error::from_raw_os_error(ret));

}

Ok(Mlx5DeviceAttrs {
max_dc_rd_atom: attrs.max_dc_rd_atom,
flags: attrs.flags,
})
}
}

/// mlx5 device attributes.
pub struct Mlx5DeviceAttrs {
pub max_dc_rd_atom: u64,
pub flags: u64,
}
Loading
Loading