1use anyhow::{Context, Result, bail};
14
15pub const STATUS_OK: u8 = 0;
16pub const STATUS_ERR: u8 = 1;
17pub const MODE_TCP: u8 = 0;
19pub const MODE_VERBS: u8 = 1;
22
23#[derive(Clone, Debug, PartialEq, Eq)]
28pub struct VerbsServerParams {
29 pub qpn: u32,
30 pub psn: u32,
31 pub gid: [u8; 16],
32 pub layers: Vec<(u64, u32)>,
34}
35
36#[derive(Clone, Copy, Debug, PartialEq, Eq)]
38pub struct VerbsClientParams {
39 pub qpn: u32,
40 pub psn: u32,
41 pub gid: [u8; 16],
42}
43
44#[derive(Clone, Copy, Debug, PartialEq, Eq)]
47pub struct CacheServerParams {
48 pub qpn: u32,
49 pub psn: u32,
50 pub gid: [u8; 16],
51 pub base_addr: u64,
52 pub rkey: u32,
53}
54
55pub trait RemoteQp {
58 fn qp_identity(&self) -> (u32, u32, [u8; 16]);
59}
60
61impl RemoteQp for VerbsServerParams {
62 fn qp_identity(&self) -> (u32, u32, [u8; 16]) {
63 (self.qpn, self.psn, self.gid)
64 }
65}
66
67impl RemoteQp for CacheServerParams {
68 fn qp_identity(&self) -> (u32, u32, [u8; 16]) {
69 (self.qpn, self.psn, self.gid)
70 }
71}
72
73impl VerbsServerParams {
74 pub fn write_to<W: std::io::Write>(&self, w: &mut W) -> Result<()> {
76 w.write_all(&self.qpn.to_le_bytes())?;
77 w.write_all(&self.psn.to_le_bytes())?;
78 w.write_all(&self.gid)?;
79 w.write_all(&(self.layers.len() as u32).to_le_bytes())?;
80 for (base, rkey) in &self.layers {
81 w.write_all(&base.to_le_bytes())?;
82 w.write_all(&rkey.to_le_bytes())?;
83 }
84 Ok(())
85 }
86
87 pub fn read_from<R: std::io::Read>(r: &mut R) -> Result<Self> {
88 let qpn = read_u32(r)?;
89 let psn = read_u32(r)?;
90 let mut gid = [0u8; 16];
91 r.read_exact(&mut gid).context("read server gid")?;
92 let n = read_u32(r)? as usize;
93 if n == 0 || n > 4096 {
94 bail!("implausible verbs layer count: {n}");
95 }
96 let mut layers = Vec::with_capacity(n);
97 for _ in 0..n {
98 let mut b8 = [0u8; 8];
99 r.read_exact(&mut b8).context("read mr base")?;
100 let base = u64::from_le_bytes(b8);
101 let rkey = read_u32(r)?;
102 layers.push((base, rkey));
103 }
104 Ok(Self {
105 qpn,
106 psn,
107 gid,
108 layers,
109 })
110 }
111}
112
113impl VerbsClientParams {
114 pub fn write_to<W: std::io::Write>(&self, w: &mut W) -> Result<()> {
116 w.write_all(&self.qpn.to_le_bytes())?;
117 w.write_all(&self.psn.to_le_bytes())?;
118 w.write_all(&self.gid)?;
119 Ok(())
120 }
121
122 pub fn read_from<R: std::io::Read>(r: &mut R) -> Result<Self> {
123 let qpn = read_u32(r)?;
124 let psn = read_u32(r)?;
125 let mut gid = [0u8; 16];
126 r.read_exact(&mut gid).context("read client gid")?;
127 Ok(Self { qpn, psn, gid })
128 }
129}
130
131impl CacheServerParams {
132 pub fn write_to<W: std::io::Write>(&self, w: &mut W) -> Result<()> {
134 w.write_all(&self.qpn.to_le_bytes())?;
135 w.write_all(&self.psn.to_le_bytes())?;
136 w.write_all(&self.gid)?;
137 w.write_all(&self.base_addr.to_le_bytes())?;
138 w.write_all(&self.rkey.to_le_bytes())?;
139 Ok(())
140 }
141
142 pub fn read_from<R: std::io::Read>(r: &mut R) -> Result<Self> {
143 let mut b4 = [0u8; 4];
144 let mut b8 = [0u8; 8];
145 let mut gid = [0u8; 16];
146 r.read_exact(&mut b4).context("kv qpn")?;
147 let qpn = u32::from_le_bytes(b4);
148 r.read_exact(&mut b4).context("kv psn")?;
149 let psn = u32::from_le_bytes(b4);
150 r.read_exact(&mut gid).context("kv gid")?;
151 r.read_exact(&mut b8).context("kv base")?;
152 let base_addr = u64::from_le_bytes(b8);
153 r.read_exact(&mut b4).context("kv rkey")?;
154 let rkey = u32::from_le_bytes(b4);
155 Ok(Self {
156 qpn,
157 psn,
158 gid,
159 base_addr,
160 rkey,
161 })
162 }
163}
164
165fn read_u32<R: std::io::Read>(r: &mut R) -> Result<u32> {
166 let mut b = [0u8; 4];
167 r.read_exact(&mut b).context("read u32")?;
168 Ok(u32::from_le_bytes(b))
169}
170
171pub fn write_server_rails<W: std::io::Write>(w: &mut W, rails: &[VerbsServerParams]) -> Result<()> {
174 if rails.is_empty() || rails.len() > 8 {
175 bail!("implausible server rail count: {}", rails.len());
176 }
177 w.write_all(&[rails.len() as u8])?;
178 for sp in rails {
179 sp.write_to(w)?;
180 }
181 Ok(())
182}
183
184pub fn read_server_rails<R: std::io::Read>(
187 r: &mut R,
188 want: usize,
189) -> Result<Vec<VerbsServerParams>> {
190 let mut b1 = [0u8; 1];
191 r.read_exact(&mut b1).context("read server rail count")?;
192 let n = b1[0] as usize;
193 if n == 0 || n > 8 {
194 bail!("implausible server rail count: {n}");
195 }
196 if n != want {
197 bail!("server framed {n} rails but client negotiated {want}");
198 }
199 let mut rails = Vec::with_capacity(n);
200 for _ in 0..n {
201 rails.push(VerbsServerParams::read_from(r)?);
202 }
203 Ok(rails)
204}