1pub const RDMA_WRITE: u32 = 1;
16pub const RDMA_READ: u32 = 0;
18
19#[derive(Clone, Copy, Debug, PartialEq, Eq)]
21pub struct RdmaMeta {
22 pub op: u32,
24 pub qpn: u32,
26 pub laddr: u64,
28 pub raddr: u64,
30 pub len: u32,
32}
33
34impl RdmaMeta {
35 pub fn pack(&self) -> [u64; 4] {
37 let mut w = [0u128; 2];
38 let mut put = |lo: u32, bits: u32, v: u64| {
39 let v = u128::from(v) & ((1u128 << bits) - 1);
40 let (i, s) = ((lo / 128) as usize, lo % 128);
41 w[i] |= v << s;
42 if s + bits > 128 {
43 w[i + 1] |= v >> (128 - s);
44 }
45 };
46 put(0, 3, u64::from(self.op));
47 put(3, 24, u64::from(self.qpn));
48 put(27, 48, self.laddr);
49 put(75, 48, self.raddr);
50 put(123, 32, u64::from(self.len));
51 [w[0] as u64, (w[0] >> 64) as u64, w[1] as u64, (w[1] >> 64) as u64]
52 }
53
54 pub fn unpack(lanes: [u64; 4]) -> RdmaMeta {
56 let w = [u128::from(lanes[0]) | (u128::from(lanes[1]) << 64), u128::from(lanes[2]) | (u128::from(lanes[3]) << 64)];
57 let get = |lo: u32, bits: u32| -> u64 {
58 let (i, s) = ((lo / 128) as usize, lo % 128);
59 let mut v = w[i] >> s;
60 if s + bits > 128 {
61 v |= w[i + 1] << (128 - s);
62 }
63 (v & ((1u128 << bits) - 1)) as u64
64 };
65 RdmaMeta { op: get(0, 3) as u32, qpn: get(3, 24) as u32, laddr: get(27, 48), raddr: get(75, 48), len: get(123, 32) as u32 }
66 }
67}
68
69pub fn decision(k: u32, m: u32) -> u64 {
72 (u64::from(k) << 32) | u64::from(m)
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
81 fn meta_round_trips_at_upstream_bit_positions() {
82 let m = RdmaMeta { op: 1, qpn: 7, laddr: 0, raddr: 0x1234_5678_9a, len: 64 };
83 let p = m.pack();
84 assert_eq!(p[0] & 7, 1);
85 assert_eq!((p[0] >> 3) & 0xff_ffff, 7);
86 assert_eq!((p[1] >> 11) & 0xffff_ffff_ffff, 0x1234_5678_9a);
88 assert_eq!(((p[1] >> 59) | (p[2] << 5)) & 0xffff_ffff, 64);
90 assert_eq!(RdmaMeta::unpack(p), m);
91 }
92}