leodos_protocols/datalink/spp/
encapsulation.rs1use zerocopy::FromBytes;
26use zerocopy::Immutable;
27use zerocopy::IntoBytes;
28use zerocopy::KnownLayout;
29use zerocopy::Unaligned;
30use zerocopy::byteorder::network_endian::U16;
31
32use crate::utils::get_bits_u16;
33use crate::utils::set_bits_u16;
34
35#[repr(C)]
37#[derive(FromBytes, IntoBytes, KnownLayout, Unaligned, Immutable, Debug, Copy, Clone)]
38pub struct EncapsulationHeader {
39 fields: U16,
42}
43
44#[rustfmt::skip]
46pub mod bitmask {
47 pub const PVN_MASK: u16 = 0b_1110_0000_0000_0000;
49 pub const PROTOCOL_ID_MASK: u16 = 0b_0001_1110_0000_0000;
51 pub const LEN_OF_LEN_MASK: u16 = 0b_0000_0001_1000_0000;
53 pub const USER_DEF_MASK: u16 = 0b_0000_0000_0111_1000;
55 pub const PID_EXT_MASK: u16 = 0b_0000_0000_0000_0111_u16 << 1;
57 pub const CCSDS_DEF_MASK: u16 = 0b_0000_0000_0000_0001;
59}
60
61use bitmask::*;
62
63#[derive(Debug, Copy, Clone, Eq, PartialEq)]
65#[repr(u8)]
66pub enum ProtocolId {
67 Idle = 0b0000,
69 Ipe = 0b0001,
71 CcsdsDefined = 0b0010,
73 UserDefined = 0b0111,
75 Ipv4 = 0b1000,
77 Ipv6 = 0b1001,
79}
80
81#[derive(Debug, Copy, Clone, Eq, PartialEq, thiserror::Error)]
83pub enum Error {
84 #[error("buffer too short: required {required} bytes, provided {provided} bytes")]
86 BufferTooShort {
87 required: usize,
89 provided: usize,
91 },
92 #[error("invalid Packet Version Number: expected 0b111, got {0:#05b}")]
94 InvalidPvn(u8),
95}
96
97pub const ENCAP_PVN: u8 = 0b111;
99
100impl EncapsulationHeader {
101 pub const MIN_SIZE: usize = 2;
103
104 pub fn pvn(&self) -> u8 {
106 get_bits_u16(self.fields, PVN_MASK) as u8
107 }
108 pub fn set_pvn(&mut self, pvn: u8) {
110 set_bits_u16(&mut self.fields, PVN_MASK, pvn as u16);
111 }
112
113 pub fn protocol_id(&self) -> u8 {
115 get_bits_u16(self.fields, PROTOCOL_ID_MASK) as u8
116 }
117 pub fn set_protocol_id(&mut self, pid: u8) {
119 set_bits_u16(&mut self.fields, PROTOCOL_ID_MASK, pid as u16);
120 }
121
122 pub fn len_of_len(&self) -> u8 {
130 get_bits_u16(self.fields, LEN_OF_LEN_MASK) as u8
131 }
132 pub fn set_len_of_len(&mut self, lol: u8) {
134 set_bits_u16(&mut self.fields, LEN_OF_LEN_MASK, lol as u16);
135 }
136
137 pub fn user_defined(&self) -> u8 {
139 get_bits_u16(self.fields, USER_DEF_MASK) as u8
140 }
141 pub fn set_user_defined(&mut self, ud: u8) {
143 set_bits_u16(&mut self.fields, USER_DEF_MASK, ud as u16);
144 }
145
146 pub fn protocol_id_extension(&self) -> u8 {
148 get_bits_u16(self.fields, PID_EXT_MASK) as u8
149 }
150 pub fn set_protocol_id_extension(&mut self, ext: u8) {
152 set_bits_u16(&mut self.fields, PID_EXT_MASK, ext as u16);
153 }
154
155 pub fn ccsds_defined(&self) -> bool {
157 get_bits_u16(self.fields, CCSDS_DEF_MASK) != 0
158 }
159 pub fn set_ccsds_defined(&mut self, val: bool) {
161 set_bits_u16(&mut self.fields, CCSDS_DEF_MASK, u16::from(val));
162 }
163
164 pub fn packet_length_bytes(&self) -> usize {
166 match self.len_of_len() {
167 0b00 => 0,
168 0b01 => 1,
169 0b10 => 2,
170 _ => 4,
171 }
172 }
173
174 pub fn total_header_size(&self) -> usize {
176 Self::MIN_SIZE + self.packet_length_bytes()
177 }
178
179 pub fn parse(bytes: &[u8]) -> Result<&Self, Error> {
181 if bytes.len() < Self::MIN_SIZE {
182 return Err(Error::BufferTooShort {
183 required: Self::MIN_SIZE,
184 provided: bytes.len(),
185 });
186 }
187 let (hdr, _) = Self::ref_from_prefix(bytes).unwrap();
188 if hdr.pvn() != ENCAP_PVN {
189 return Err(Error::InvalidPvn(hdr.pvn()));
190 }
191 Ok(hdr)
192 }
193}
194
195pub fn read_packet_length(len_of_len: u8, bytes: &[u8]) -> Result<Option<u32>, Error> {
201 match len_of_len {
202 0b00 => Ok(None),
203 0b01 => {
204 if bytes.is_empty() {
205 return Err(Error::BufferTooShort {
206 required: 1,
207 provided: 0,
208 });
209 }
210 Ok(Some(bytes[0] as u32))
211 }
212 0b10 => {
213 if bytes.len() < 2 {
214 return Err(Error::BufferTooShort {
215 required: 2,
216 provided: bytes.len(),
217 });
218 }
219 Ok(Some(u16::from_be_bytes([bytes[0], bytes[1]]) as u32))
220 }
221 _ => {
222 if bytes.len() < 4 {
223 return Err(Error::BufferTooShort {
224 required: 4,
225 provided: bytes.len(),
226 });
227 }
228 Ok(Some(u32::from_be_bytes([
229 bytes[0], bytes[1], bytes[2], bytes[3],
230 ])))
231 }
232 }
233}
234
235pub fn write_packet_length(len_of_len: u8, length: u32, bytes: &mut [u8]) -> Result<usize, Error> {
239 match len_of_len {
240 0b00 => Ok(0),
241 0b01 => {
242 if bytes.is_empty() {
243 return Err(Error::BufferTooShort {
244 required: 1,
245 provided: 0,
246 });
247 }
248 bytes[0] = length as u8;
249 Ok(1)
250 }
251 0b10 => {
252 if bytes.len() < 2 {
253 return Err(Error::BufferTooShort {
254 required: 2,
255 provided: bytes.len(),
256 });
257 }
258 let b = (length as u16).to_be_bytes();
259 bytes[0] = b[0];
260 bytes[1] = b[1];
261 Ok(2)
262 }
263 _ => {
264 if bytes.len() < 4 {
265 return Err(Error::BufferTooShort {
266 required: 4,
267 provided: bytes.len(),
268 });
269 }
270 let b = length.to_be_bytes();
271 bytes[..4].copy_from_slice(&b);
272 Ok(4)
273 }
274 }
275}
276
277#[cfg(test)]
278mod tests {
279 use super::*;
280
281 #[test]
282 fn header_pvn_is_111() {
283 let mut buf = [0u8; 2];
284 let hdr = EncapsulationHeader::mut_from_bytes(&mut buf).unwrap();
285 hdr.set_pvn(ENCAP_PVN);
286 assert_eq!(hdr.pvn(), 0b111);
287 assert_eq!(buf[0] & 0xE0, 0xE0);
289 }
290
291 #[test]
292 fn protocol_id_roundtrip() {
293 let mut buf = [0u8; 2];
294 let hdr = EncapsulationHeader::mut_from_bytes(&mut buf).unwrap();
295 hdr.set_pvn(ENCAP_PVN);
296 hdr.set_protocol_id(ProtocolId::Ipv4 as u8);
297 assert_eq!(hdr.protocol_id(), ProtocolId::Ipv4 as u8);
298 }
299
300 #[test]
301 fn len_of_len_values() {
302 for lol in 0..=3u8 {
303 let mut buf = [0u8; 2];
304 let hdr = EncapsulationHeader::mut_from_bytes(&mut buf).unwrap();
305 hdr.set_pvn(ENCAP_PVN);
306 hdr.set_len_of_len(lol);
307 assert_eq!(hdr.len_of_len(), lol);
308 let expected_bytes = match lol {
309 0 => 0,
310 1 => 1,
311 2 => 2,
312 _ => 4,
313 };
314 assert_eq!(hdr.packet_length_bytes(), expected_bytes);
315 }
316 }
317
318 #[test]
319 fn user_defined_field() {
320 let mut buf = [0u8; 2];
321 let hdr = EncapsulationHeader::mut_from_bytes(&mut buf).unwrap();
322 hdr.set_pvn(ENCAP_PVN);
323 hdr.set_user_defined(0x0F);
324 assert_eq!(hdr.user_defined(), 0x0F);
325 }
326
327 #[test]
328 fn parse_validates_pvn() {
329 let buf = [0u8; 2]; let err = EncapsulationHeader::parse(&buf);
331 assert!(matches!(err, Err(Error::InvalidPvn(0))));
332 }
333
334 #[test]
335 fn parse_valid() {
336 let mut buf = [0u8; 2];
337 let hdr = EncapsulationHeader::mut_from_bytes(&mut buf).unwrap();
338 hdr.set_pvn(ENCAP_PVN);
339 hdr.set_protocol_id(ProtocolId::Ipv6 as u8);
340 hdr.set_len_of_len(0b10);
341
342 let parsed = EncapsulationHeader::parse(&buf).unwrap();
343 assert_eq!(parsed.pvn(), ENCAP_PVN);
344 assert_eq!(parsed.protocol_id(), ProtocolId::Ipv6 as u8);
345 assert_eq!(parsed.len_of_len(), 0b10);
346 }
347
348 #[test]
349 fn read_write_packet_length_1byte() {
350 let mut buf = [0u8; 4];
351 let n = write_packet_length(0b01, 200, &mut buf).unwrap();
352 assert_eq!(n, 1);
353 let len = read_packet_length(0b01, &buf).unwrap();
354 assert_eq!(len, Some(200));
355 }
356
357 #[test]
358 fn read_write_packet_length_2byte() {
359 let mut buf = [0u8; 4];
360 let n = write_packet_length(0b10, 50000, &mut buf).unwrap();
361 assert_eq!(n, 2);
362 let len = read_packet_length(0b10, &buf).unwrap();
363 assert_eq!(len, Some(50000));
364 }
365
366 #[test]
367 fn read_write_packet_length_4byte() {
368 let mut buf = [0u8; 4];
369 let n = write_packet_length(0b11, 1_000_000, &mut buf).unwrap();
370 assert_eq!(n, 4);
371 let len = read_packet_length(0b11, &buf).unwrap();
372 assert_eq!(len, Some(1_000_000));
373 }
374
375 #[test]
376 fn packet_length_zero_means_none() {
377 let buf = [0u8; 4];
378 let len = read_packet_length(0b00, &buf).unwrap();
379 assert_eq!(len, None);
380 }
381
382 #[test]
383 fn total_header_size() {
384 let mut buf = [0u8; 2];
385 let hdr = EncapsulationHeader::mut_from_bytes(&mut buf).unwrap();
386
387 hdr.set_len_of_len(0b00);
388 assert_eq!(hdr.total_header_size(), 2);
389
390 hdr.set_len_of_len(0b01);
391 assert_eq!(hdr.total_header_size(), 3);
392
393 hdr.set_len_of_len(0b10);
394 assert_eq!(hdr.total_header_size(), 4);
395
396 hdr.set_len_of_len(0b11);
397 assert_eq!(hdr.total_header_size(), 6);
398 }
399}