1use std::sync::Arc;
4
5use rdma_io_sys::ibverbs::*;
6
7use crate::Result;
8use crate::cq::CompletionQueue;
9use crate::device::Context;
10use crate::error::from_ptr;
11use crate::mr::{AccessFlags, MemoryRegion, OwnedMemoryRegion};
12use crate::qp::{QpInitAttr, QueuePair};
13
14pub struct ProtectionDomain {
18 pub(crate) inner: *mut ibv_pd,
19 pub(crate) ctx: Arc<Context>,
20}
21
22unsafe impl Send for ProtectionDomain {}
24unsafe impl Sync for ProtectionDomain {}
25
26impl Drop for ProtectionDomain {
27 fn drop(&mut self) {
28 let ret = unsafe { ibv_dealloc_pd(self.inner) };
29 if ret != 0 {
30 tracing::error!(
31 "ibv_dealloc_pd failed: {}",
32 std::io::Error::from_raw_os_error(-ret)
33 );
34 }
35 }
36}
37
38impl ProtectionDomain {
39 pub fn new(ctx: Arc<Context>) -> Result<Arc<Self>> {
41 let pd = from_ptr(unsafe { ibv_alloc_pd(ctx.inner) })?;
42 Ok(Arc::new(Self { inner: pd, ctx }))
43 }
44
45 pub unsafe fn from_raw(pd: *mut ibv_pd, ctx: Arc<Context>) -> Arc<Self> {
51 Arc::new(Self { inner: pd, ctx })
52 }
53
54 pub fn reg_mr<'a>(
58 self: &Arc<Self>,
59 buf: &'a mut [u8],
60 access: AccessFlags,
61 ) -> Result<MemoryRegion<'a>> {
62 let mr = from_ptr(unsafe {
63 ibv_reg_mr(
64 self.inner,
65 buf.as_mut_ptr().cast(),
66 buf.len() as u64,
67 access.bits() as i32,
68 )
69 })?;
70 Ok(MemoryRegion {
71 inner: mr,
72 _pd: Arc::clone(self),
73 _lifetime: std::marker::PhantomData,
74 })
75 }
76
77 pub fn reg_mr_owned(
81 self: &Arc<Self>,
82 buf: Vec<u8>,
83 access: AccessFlags,
84 ) -> Result<OwnedMemoryRegion> {
85 let mut buf = buf.into_boxed_slice();
86 let mr = from_ptr(unsafe {
87 ibv_reg_mr(
88 self.inner,
89 buf.as_mut_ptr().cast(),
90 buf.len() as u64,
91 access.bits() as i32,
92 )
93 })?;
94 Ok(OwnedMemoryRegion {
95 inner: mr,
96 _pd: Arc::clone(self),
97 _buf: buf,
98 })
99 }
100
101 pub fn create_qp(
103 self: &Arc<Self>,
104 send_cq: &Arc<CompletionQueue>,
105 recv_cq: &Arc<CompletionQueue>,
106 init_attr: &QpInitAttr,
107 ) -> Result<QueuePair> {
108 let mut raw_attr = ibv_qp_init_attr {
109 send_cq: send_cq.inner,
110 recv_cq: recv_cq.inner,
111 cap: ibv_qp_cap {
112 max_send_wr: init_attr.max_send_wr,
113 max_recv_wr: init_attr.max_recv_wr,
114 max_send_sge: init_attr.max_send_sge,
115 max_recv_sge: init_attr.max_recv_sge,
116 max_inline_data: init_attr.max_inline_data,
117 },
118 qp_type: init_attr.qp_type.as_raw(),
119 sq_sig_all: i32::from(init_attr.sq_sig_all),
120 ..Default::default()
121 };
122 let qp = from_ptr(unsafe { ibv_create_qp(self.inner, &mut raw_attr) })?;
123 Ok(QueuePair {
124 inner: qp,
125 _pd: Arc::clone(self),
126 _send_cq: Arc::clone(send_cq),
127 _recv_cq: Arc::clone(recv_cq),
128 })
129 }
130
131 pub fn as_raw(&self) -> *mut ibv_pd {
133 self.inner
134 }
135
136 pub fn context(&self) -> &Arc<Context> {
138 &self.ctx
139 }
140}
141
142impl Context {
143 pub fn alloc_pd(self: &Arc<Self>) -> Result<Arc<ProtectionDomain>> {
145 ProtectionDomain::new(Arc::clone(self))
146 }
147}