Skip to main content

rdma_io/
wc.rs

1//! Work Completion types.
2
3use rdma_io_sys::ibverbs::*;
4
5/// A work completion entry.
6///
7/// Thin wrapper around `ibv_wc` with typed accessors.
8#[repr(transparent)]
9#[derive(Clone, Copy, Default)]
10pub struct WorkCompletion {
11    pub(crate) inner: ibv_wc,
12}
13
14impl WorkCompletion {
15    /// The WR id that was completed.
16    pub fn wr_id(&self) -> u64 {
17        self.inner.wr_id
18    }
19
20    /// Raw status value.
21    pub fn status_raw(&self) -> u32 {
22        self.inner.status
23    }
24
25    /// Whether this completion is successful.
26    pub fn is_success(&self) -> bool {
27        self.inner.status == IBV_WC_SUCCESS
28    }
29
30    /// Typed status.
31    pub fn status(&self) -> WcStatus {
32        WcStatus::from_raw(self.inner.status)
33    }
34
35    /// Typed opcode.
36    pub fn opcode(&self) -> WcOpcode {
37        WcOpcode::from_raw(self.inner.opcode)
38    }
39
40    /// Vendor-specific error code.
41    pub fn vendor_err(&self) -> u32 {
42        self.inner.vendor_err
43    }
44
45    /// Number of bytes transferred (for recv completions).
46    pub fn byte_len(&self) -> u32 {
47        self.inner.byte_len
48    }
49
50    /// QP number that generated this completion.
51    pub fn qp_num(&self) -> u32 {
52        self.inner.qp_num
53    }
54
55    /// Source QP number (for recv completions on UD QPs).
56    pub fn src_qp(&self) -> u32 {
57        self.inner.src_qp
58    }
59
60    /// WC flags.
61    pub fn wc_flags(&self) -> u32 {
62        self.inner.wc_flags
63    }
64
65    /// Immediate data (valid if `wc_flags` has `IBV_WC_WITH_IMM`).
66    pub fn imm_data(&self) -> u32 {
67        unsafe { self.inner.ibv_wc__anon_0.imm_data }
68    }
69
70    /// Raw `ibv_wc` reference.
71    pub fn as_raw(&self) -> &ibv_wc {
72        &self.inner
73    }
74}
75
76impl std::fmt::Debug for WorkCompletion {
77    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78        f.debug_struct("WorkCompletion")
79            .field("wr_id", &self.wr_id())
80            .field("status", &self.status())
81            .field("opcode", &self.opcode())
82            .field("byte_len", &self.byte_len())
83            .field("qp_num", &self.qp_num())
84            .finish()
85    }
86}
87
88/// Work completion status codes.
89#[derive(Debug, Clone, Copy, PartialEq, Eq)]
90pub enum WcStatus {
91    Success,
92    LocLenErr,
93    LocQpOpErr,
94    LocEecOpErr,
95    LocProtErr,
96    WrFlushErr,
97    MwBindErr,
98    BadRespErr,
99    LocAccessErr,
100    RemInvReqErr,
101    RemAccessErr,
102    RemOpErr,
103    RetryExcErr,
104    RnrRetryExcErr,
105    LocRddViolErr,
106    RemAbortErr,
107    InvEecnErr,
108    InvEecStateErr,
109    FatalErr,
110    RespTimeoutErr,
111    GeneralErr,
112    TmErr,
113    TmRndvIncomplete,
114    Unknown(u32),
115}
116
117impl WcStatus {
118    /// Convert from raw `ibv_wc_status` value.
119    pub fn from_raw(v: u32) -> Self {
120        match v {
121            IBV_WC_SUCCESS => Self::Success,
122            IBV_WC_LOC_LEN_ERR => Self::LocLenErr,
123            IBV_WC_LOC_QP_OP_ERR => Self::LocQpOpErr,
124            IBV_WC_LOC_EEC_OP_ERR => Self::LocEecOpErr,
125            IBV_WC_LOC_PROT_ERR => Self::LocProtErr,
126            IBV_WC_WR_FLUSH_ERR => Self::WrFlushErr,
127            IBV_WC_MW_BIND_ERR => Self::MwBindErr,
128            IBV_WC_BAD_RESP_ERR => Self::BadRespErr,
129            IBV_WC_LOC_ACCESS_ERR => Self::LocAccessErr,
130            IBV_WC_REM_INV_REQ_ERR => Self::RemInvReqErr,
131            IBV_WC_REM_ACCESS_ERR => Self::RemAccessErr,
132            IBV_WC_REM_OP_ERR => Self::RemOpErr,
133            IBV_WC_RETRY_EXC_ERR => Self::RetryExcErr,
134            IBV_WC_RNR_RETRY_EXC_ERR => Self::RnrRetryExcErr,
135            IBV_WC_LOC_RDD_VIOL_ERR => Self::LocRddViolErr,
136            IBV_WC_REM_ABORT_ERR => Self::RemAbortErr,
137            IBV_WC_INV_EECN_ERR => Self::InvEecnErr,
138            IBV_WC_INV_EEC_STATE_ERR => Self::InvEecStateErr,
139            IBV_WC_FATAL_ERR => Self::FatalErr,
140            IBV_WC_RESP_TIMEOUT_ERR => Self::RespTimeoutErr,
141            IBV_WC_GENERAL_ERR => Self::GeneralErr,
142            IBV_WC_TM_ERR => Self::TmErr,
143            IBV_WC_TM_RNDV_INCOMPLETE => Self::TmRndvIncomplete,
144            other => Self::Unknown(other),
145        }
146    }
147}
148
149/// Work completion opcode.
150#[derive(Debug, Clone, Copy, PartialEq, Eq)]
151pub enum WcOpcode {
152    Send,
153    RdmaWrite,
154    RdmaRead,
155    CompSwap,
156    FetchAdd,
157    BindMw,
158    LocalInv,
159    Tso,
160    Flush,
161    AtomicWrite,
162    Recv,
163    RecvRdmaWithImm,
164    TmAdd,
165    TmDel,
166    TmSync,
167    TmRecv,
168    TmNoTag,
169    Unknown(u32),
170}
171
172impl WcOpcode {
173    /// Convert from raw `ibv_wc_opcode` value.
174    pub fn from_raw(v: u32) -> Self {
175        match v {
176            IBV_WC_SEND => Self::Send,
177            IBV_WC_RDMA_WRITE => Self::RdmaWrite,
178            IBV_WC_RDMA_READ => Self::RdmaRead,
179            IBV_WC_COMP_SWAP => Self::CompSwap,
180            IBV_WC_FETCH_ADD => Self::FetchAdd,
181            IBV_WC_BIND_MW => Self::BindMw,
182            IBV_WC_LOCAL_INV => Self::LocalInv,
183            IBV_WC_TSO => Self::Tso,
184            IBV_WC_FLUSH => Self::Flush,
185            IBV_WC_ATOMIC_WRITE => Self::AtomicWrite,
186            IBV_WC_RECV => Self::Recv,
187            IBV_WC_RECV_RDMA_WITH_IMM => Self::RecvRdmaWithImm,
188            IBV_WC_TM_ADD => Self::TmAdd,
189            IBV_WC_TM_DEL => Self::TmDel,
190            IBV_WC_TM_SYNC => Self::TmSync,
191            IBV_WC_TM_RECV => Self::TmRecv,
192            IBV_WC_TM_NO_TAG => Self::TmNoTag,
193            other => Self::Unknown(other),
194        }
195    }
196}