1use crate::addr::VsockAddr;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7#[repr(u16)]
8pub enum VsockOp {
9 Invalid = 0,
11 Request = 1,
13 Response = 2,
15 Rst = 3,
17 Shutdown = 4,
19 Rw = 5,
21 CreditUpdate = 6,
23 CreditRequest = 7,
25}
26
27impl VsockOp {
28 #[must_use]
30 pub const fn from_u16(val: u16) -> Option<Self> {
31 match val {
32 0 => Some(Self::Invalid),
33 1 => Some(Self::Request),
34 2 => Some(Self::Response),
35 3 => Some(Self::Rst),
36 4 => Some(Self::Shutdown),
37 5 => Some(Self::Rw),
38 6 => Some(Self::CreditUpdate),
39 7 => Some(Self::CreditRequest),
40 _ => None,
41 }
42 }
43}
44
45#[derive(Debug, Clone, Copy)]
47#[repr(C, packed)]
48pub struct VsockHeader {
49 pub src_cid: u64,
51 pub dst_cid: u64,
53 pub src_port: u32,
55 pub dst_port: u32,
57 pub len: u32,
59 pub socket_type: u16,
61 pub op: u16,
63 pub flags: u32,
65 pub buf_alloc: u32,
67 pub fwd_cnt: u32,
69}
70
71impl VsockHeader {
72 pub const SIZE: usize = 44;
79
80 #[must_use]
82 pub const fn new(src: VsockAddr, dst: VsockAddr, op: VsockOp) -> Self {
83 Self {
84 src_cid: src.cid,
85 dst_cid: dst.cid,
86 src_port: src.port,
87 dst_port: dst.port,
88 len: 0,
89 socket_type: 1, op: op as u16,
91 flags: 0,
92 buf_alloc: 64 * 1024,
93 fwd_cnt: 0,
94 }
95 }
96
97 #[must_use]
99 pub const fn operation(&self) -> Option<VsockOp> {
100 VsockOp::from_u16(self.op)
101 }
102
103 #[must_use]
107 pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
108 if bytes.len() < Self::SIZE {
109 return None;
110 }
111 Some(Self {
112 src_cid: u64::from_le_bytes([
113 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
114 ]),
115 dst_cid: u64::from_le_bytes([
116 bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14],
117 bytes[15],
118 ]),
119 src_port: u32::from_le_bytes([bytes[16], bytes[17], bytes[18], bytes[19]]),
120 dst_port: u32::from_le_bytes([bytes[20], bytes[21], bytes[22], bytes[23]]),
121 len: u32::from_le_bytes([bytes[24], bytes[25], bytes[26], bytes[27]]),
122 socket_type: u16::from_le_bytes([bytes[28], bytes[29]]),
123 op: u16::from_le_bytes([bytes[30], bytes[31]]),
124 flags: u32::from_le_bytes([bytes[32], bytes[33], bytes[34], bytes[35]]),
125 buf_alloc: u32::from_le_bytes([bytes[36], bytes[37], bytes[38], bytes[39]]),
126 fwd_cnt: u32::from_le_bytes([bytes[40], bytes[41], bytes[42], bytes[43]]),
127 })
128 }
129
130 #[must_use]
132 pub fn to_bytes(&self) -> [u8; Self::SIZE] {
133 let mut buf = [0u8; Self::SIZE];
134 let src_cid = self.src_cid;
136 let dst_cid = self.dst_cid;
137 let src_port = self.src_port;
138 let dst_port = self.dst_port;
139 let len = self.len;
140 let socket_type = self.socket_type;
141 let op = self.op;
142 let flags = self.flags;
143 let buf_alloc = self.buf_alloc;
144 let fwd_cnt = self.fwd_cnt;
145
146 buf[0..8].copy_from_slice(&src_cid.to_le_bytes());
147 buf[8..16].copy_from_slice(&dst_cid.to_le_bytes());
148 buf[16..20].copy_from_slice(&src_port.to_le_bytes());
149 buf[20..24].copy_from_slice(&dst_port.to_le_bytes());
150 buf[24..28].copy_from_slice(&len.to_le_bytes());
151 buf[28..30].copy_from_slice(&socket_type.to_le_bytes());
152 buf[30..32].copy_from_slice(&op.to_le_bytes());
153 buf[32..36].copy_from_slice(&flags.to_le_bytes());
154 buf[36..40].copy_from_slice(&buf_alloc.to_le_bytes());
155 buf[40..44].copy_from_slice(&fwd_cnt.to_le_bytes());
156 buf
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163
164 #[test]
165 fn test_vsock_op_from_u16() {
166 assert_eq!(VsockOp::from_u16(0), Some(VsockOp::Invalid));
167 assert_eq!(VsockOp::from_u16(1), Some(VsockOp::Request));
168 assert_eq!(VsockOp::from_u16(5), Some(VsockOp::Rw));
169 assert_eq!(VsockOp::from_u16(100), None);
170 }
171
172 #[test]
173 fn test_vsock_header() {
174 let src = VsockAddr::new(3, 1000);
175 let dst = VsockAddr::new(2, 80);
176 let header = VsockHeader::new(src, dst, VsockOp::Request);
177
178 let src_cid = header.src_cid;
179 let dst_cid = header.dst_cid;
180 let src_port = header.src_port;
181 let dst_port = header.dst_port;
182
183 assert_eq!(src_cid, 3);
184 assert_eq!(dst_cid, 2);
185 assert_eq!(src_port, 1000);
186 assert_eq!(dst_port, 80);
187 assert_eq!(header.operation(), Some(VsockOp::Request));
188 }
189
190 #[test]
191 fn test_vsock_header_size() {
192 assert_eq!(VsockHeader::SIZE, 44);
193 }
194
195 #[test]
196 fn test_vsock_header_roundtrip() {
197 let src = VsockAddr::new(3, 1000);
198 let dst = VsockAddr::new(2, 80);
199 let original = VsockHeader::new(src, dst, VsockOp::Request);
200
201 let bytes = original.to_bytes();
202 assert_eq!(bytes.len(), VsockHeader::SIZE);
203
204 let parsed = VsockHeader::from_bytes(&bytes).unwrap();
205 let p_src_cid = parsed.src_cid;
206 let p_dst_cid = parsed.dst_cid;
207 let p_src_port = parsed.src_port;
208 let p_dst_port = parsed.dst_port;
209 let p_socket_type = parsed.socket_type;
210 assert_eq!(p_src_cid, 3);
211 assert_eq!(p_dst_cid, 2);
212 assert_eq!(p_src_port, 1000);
213 assert_eq!(p_dst_port, 80);
214 assert_eq!(parsed.operation(), Some(VsockOp::Request));
215 assert_eq!(p_socket_type, 1); }
217
218 #[test]
219 fn test_vsock_header_from_bytes_too_short() {
220 let short = [0u8; 20];
221 assert!(VsockHeader::from_bytes(&short).is_none());
222 }
223
224 #[test]
225 fn test_vsock_header_to_bytes_all_fields() {
226 let mut header = VsockHeader::new(
227 VsockAddr::new(0xAABB, 0x1234),
228 VsockAddr::new(0xCCDD, 0x5678),
229 VsockOp::Rw,
230 );
231 header.len = 256;
232 header.flags = 0x42;
233 header.buf_alloc = 32768;
234 header.fwd_cnt = 100;
235
236 let bytes = header.to_bytes();
237 let parsed = VsockHeader::from_bytes(&bytes).unwrap();
238
239 let p_src_cid = parsed.src_cid;
240 let p_dst_cid = parsed.dst_cid;
241 let p_src_port = parsed.src_port;
242 let p_dst_port = parsed.dst_port;
243 let p_len = parsed.len;
244 let p_op = parsed.op;
245 let p_flags = parsed.flags;
246 let p_buf_alloc = parsed.buf_alloc;
247 let p_fwd_cnt = parsed.fwd_cnt;
248 assert_eq!(p_src_cid, 0xAABB);
249 assert_eq!(p_dst_cid, 0xCCDD);
250 assert_eq!(p_src_port, 0x1234);
251 assert_eq!(p_dst_port, 0x5678);
252 assert_eq!(p_len, 256);
253 assert_eq!(p_op, VsockOp::Rw as u16);
254 assert_eq!(p_flags, 0x42);
255 assert_eq!(p_buf_alloc, 32768);
256 assert_eq!(p_fwd_cnt, 100);
257 }
258
259 #[test]
260 fn test_vsock_header_size_is_44() {
261 assert_eq!(VsockHeader::SIZE, 44);
262 let hdr = VsockHeader::new(
263 VsockAddr::host(50000),
264 VsockAddr::new(3, 1024),
265 VsockOp::Request,
266 );
267 let bytes = hdr.to_bytes();
268 assert_eq!(bytes.len(), 44);
269
270 let parsed = VsockHeader::from_bytes(&bytes).unwrap();
271 assert_eq!({ parsed.src_cid }, 2);
272 assert_eq!({ parsed.dst_cid }, 3);
273 assert_eq!({ parsed.src_port }, 50000);
274 assert_eq!({ parsed.dst_port }, 1024);
275 assert_eq!({ parsed.op }, VsockOp::Request as u16);
276 assert_eq!({ parsed.socket_type }, 1);
277 assert_eq!({ parsed.buf_alloc }, 64 * 1024);
278 }
279}