monarch_rdma/backend/ibverbs/
mlx_queue_pair.rs1use std::io::Error;
12use std::result::Result;
13
14use super::IbvBuffer;
15use super::domain::IbvDomain;
16use super::domain::IbvDomainImpl;
17use super::primitives::GidScope;
18use super::primitives::GidType;
19use super::primitives::IbvConfig;
20use super::primitives::IbvCq;
21use super::primitives::IbvQp;
22use super::primitives::IbvQpInfo;
23use super::primitives::IbvWc;
24use super::queue_pair::IbvQueuePair;
25use super::queue_pair::PollCompletionError;
26use super::queue_pair::PollTarget;
27use super::queue_pair::RCQueuePair;
28use super::queue_pair::WorkRequestError;
29
30#[derive(Debug)]
37pub struct MlxQueuePair(RCQueuePair);
38
39impl MlxQueuePair {
40 pub(super) unsafe fn create_ibv_qp<I: IbvDomainImpl>(
50 domain: &IbvDomain<I>,
51 config: &IbvConfig,
52 ) -> Result<IbvQp, anyhow::Error> {
53 let context = domain.context().as_ptr();
54 let pd = domain.as_ptr();
55 if pd.is_null() {
56 anyhow::bail!("cannot create an MlxQueuePair on a null protection domain");
57 }
58
59 let send_cq = unsafe { IbvCq::create(domain.context().clone(), config.cq_entries) }?;
65 let recv_cq = unsafe { IbvCq::create(domain.context().clone(), config.cq_entries) }?;
67
68 let mut init_attr = rdmaxcel_sys::ibv_qp_init_attr_ex {
72 send_cq: send_cq.as_ptr(),
73 recv_cq: recv_cq.as_ptr(),
74 cap: rdmaxcel_sys::ibv_qp_cap {
75 max_send_wr: config.max_send_wr,
76 max_recv_wr: config.max_recv_wr,
77 max_send_sge: config.max_send_sge,
78 max_recv_sge: config.max_recv_sge,
79 max_inline_data: 0,
80 },
81 qp_type: rdmaxcel_sys::ibv_qp_type::IBV_QPT_RC,
82 sq_sig_all: 0,
83 pd,
84 comp_mask: rdmaxcel_sys::IBV_QP_INIT_ATTR_PD
85 | rdmaxcel_sys::IBV_QP_INIT_ATTR_SEND_OPS_FLAGS,
86 send_ops_flags: (rdmaxcel_sys::IBV_QP_EX_WITH_RDMA_WRITE
87 | rdmaxcel_sys::IBV_QP_EX_WITH_RDMA_READ
88 | rdmaxcel_sys::IBV_QP_EX_WITH_SEND) as u64,
89 ..Default::default()
90 };
91 let mut mlx5dv_attr = rdmaxcel_sys::mlx5dv_qp_init_attr {
92 comp_mask: rdmaxcel_sys::MLX5DV_QP_INIT_ATTR_MASK_SEND_OPS_FLAGS as u64,
93 send_ops_flags: (rdmaxcel_sys::MLX5DV_QP_EX_WITH_MKEY_CONFIGURE
94 | rdmaxcel_sys::MLX5DV_QP_EX_WITH_MR_LIST) as u64,
95 ..Default::default()
96 };
97 let qp =
103 unsafe { rdmaxcel_sys::mlx5dv_create_qp(context, &mut init_attr, &mut mlx5dv_attr) };
104 if qp.is_null() {
105 anyhow::bail!(
107 "failed to create mlx5dv queue pair (QP): {}",
108 Error::last_os_error()
109 );
110 }
111 Ok(unsafe { IbvQp::from_raw(qp, send_cq, recv_cq, domain.pd().clone()) })
115 }
116}
117
118impl IbvQueuePair for MlxQueuePair {
119 unsafe fn new<I: IbvDomainImpl<QueuePair = Self>>(
120 domain: &IbvDomain<I>,
121 config: IbvConfig,
122 ) -> Result<Self, anyhow::Error> {
123 tracing::debug!("creating an MlxQueuePair from config {}", config);
124 let gid = domain.device_info().select_gid(
125 config.port_num,
126 Some(GidScope::Global),
127 Some(GidType::RoCEv2),
128 )?;
129 let qp = unsafe { Self::create_ibv_qp(domain, &config) }?;
132 let access_flags = domain.access_flags();
133 Ok(MlxQueuePair(unsafe {
136 RCQueuePair::from_qp(qp, config, gid, access_flags)
137 }))
138 }
139
140 fn connect(&mut self, info: &IbvQpInfo) -> Result<(), anyhow::Error> {
141 self.0.connect(info)
142 }
143
144 fn get_qp_info(&mut self) -> Result<IbvQpInfo, anyhow::Error> {
145 self.0.get_qp_info()
146 }
147
148 fn state(&mut self) -> Result<u32, anyhow::Error> {
149 self.0.state()
150 }
151
152 fn put(
153 &mut self,
154 remote_dst: IbvBuffer,
155 local_src: IbvBuffer,
156 ) -> Result<Vec<u64>, anyhow::Error> {
157 self.0.put(remote_dst, local_src)
158 }
159
160 fn get(
161 &mut self,
162 local_dst: IbvBuffer,
163 remote_src: IbvBuffer,
164 ) -> Result<Vec<u64>, anyhow::Error> {
165 self.0.get(local_dst, remote_src)
166 }
167
168 fn poll_completion(
169 &mut self,
170 target: PollTarget,
171 ) -> Result<Option<Result<IbvWc, WorkRequestError>>, PollCompletionError> {
172 self.0.poll_completion(target)
173 }
174}