#![cfg(mlnx4)]
use std::ptr::NonNull;
use std::sync::Arc;
use std::{fmt, io, mem};
use thiserror::Error;
use crate::bindings::*;
use crate::rdma::{context::Context, cq::Cq, pd::Pd, qp::QpEndpoint, srq::Srq};
use crate::utils::interop::*;
pub use self::builder::*;
mod builder;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub(crate) struct IbvExpDct(Option<NonNull<ibv_exp_dct>>);
impl IbvExpDct {
pub unsafe fn destroy(self) -> io::Result<()> {
let ret = ibv_exp_destroy_dct(self.as_ptr());
from_c_ret(ret)
}
}
impl_ibv_wrapper_traits!(ibv_exp_dct, IbvExpDct);
#[derive(Debug, Error)]
pub enum DctCreationError {
#[error("I/O error from ibverbs")]
IoError(#[from] io::Error),
#[error("queried DCKey {0} is different from the default")]
DifferentDcKey(u64),
#[error("DCT is not in active state")]
NotActive,
}
struct DctInner {
ctx: Context,
dct: IbvExpDct,
num: u32,
init_attr: DctInitAttr,
}
impl Drop for DctInner {
fn drop(&mut self) {
unsafe { self.dct.destroy() }.expect("cannot destroy DCT on drop");
}
}
pub struct Dct {
dct: IbvExpDct,
inner: Arc<DctInner>,
}
impl fmt::Debug for Dct {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_fmt(format_args!(
"Dct<{:p}, num={}>",
self.as_raw(),
self.dct_num()
))
}
}
impl Dct {
pub(crate) fn init_attr(&self) -> &DctInitAttr {
&self.inner.init_attr
}
pub(crate) fn new(ctx: &Context, builder: DctBuilder) -> Result<Self, DctCreationError> {
let init_attr = builder.unwrap()?;
let dct = {
let mut init_attr = init_attr.to_init_attr();
unsafe { ibv_exp_create_dct(ctx.as_raw(), &mut init_attr) }
};
let dct = NonNull::new(dct).ok_or_else(io::Error::last_os_error)?;
let dct = IbvExpDct::from(dct);
{
let mut attr = unsafe { mem::zeroed::<ibv_exp_dct_attr>() };
let ret = unsafe { ibv_exp_query_dct(dct.as_ptr(), &mut attr) };
from_c_ret(ret)?;
if attr.dc_key != Self::GLOBAL_DC_KEY {
return Err(DctCreationError::DifferentDcKey(attr.dc_key));
}
if attr.state != IBV_EXP_DCT_STATE_ACTIVE {
return Err(DctCreationError::NotActive);
}
}
let num = unsafe { (*dct.as_ptr()).dct_num };
let dct = Dct {
inner: Arc::new(DctInner {
ctx: ctx.clone(),
dct,
num,
init_attr,
}),
dct,
};
Ok(dct)
}
}
impl Dct {
pub const GLOBAL_DC_KEY: u64 = 0x1919810;
pub fn builder<'a>() -> DctBuilder<'a> {
Default::default()
}
#[inline]
pub fn as_raw(&self) -> *mut ibv_exp_dct {
self.dct.as_ptr()
}
pub fn context(&self) -> &Context {
&self.inner.ctx
}
pub fn pd(&self) -> &Pd {
&self.inner.init_attr.pd
}
pub fn dct_num(&self) -> u32 {
self.inner.num
}
pub fn srq(&self) -> &Srq {
&self.inner.init_attr.srq
}
pub fn cq(&self) -> &Cq {
&self.inner.init_attr.cq
}
pub fn endpoint(&self) -> QpEndpoint {
QpEndpoint::of_dct(self)
}
}