• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::*;
2 use core::slice::from_raw_parts;
3 
4 ///A slice containing a single vlan header of a network package.
5 #[derive(Clone, Debug, Eq, PartialEq)]
6 pub struct SingleVlanHeaderSlice<'a> {
7     slice: &'a [u8],
8 }
9 
10 impl<'a> SingleVlanHeaderSlice<'a> {
11     ///Creates a vlan header slice from a slice.
12     #[inline]
from_slice(slice: &'a [u8]) -> Result<SingleVlanHeaderSlice<'a>, err::LenError>13     pub fn from_slice(slice: &'a [u8]) -> Result<SingleVlanHeaderSlice<'a>, err::LenError> {
14         //check length
15         if slice.len() < SingleVlanHeader::LEN {
16             return Err(err::LenError {
17                 required_len: SingleVlanHeader::LEN,
18                 len: slice.len(),
19                 len_source: LenSource::Slice,
20                 layer: err::Layer::VlanHeader,
21                 layer_start_offset: 0,
22             });
23         }
24 
25         //all done
26         Ok(SingleVlanHeaderSlice::<'a> {
27             // SAFETY:
28             // Safe as the slice length is checked beforehand to have
29             // at least the length of SingleVlanHeader::LEN (4)
30             slice: unsafe { from_raw_parts(slice.as_ptr(), SingleVlanHeader::LEN) },
31         })
32     }
33 
34     /// Converts the given slice into a vlan header slice WITHOUT any
35     /// checks to ensure that the data present is an vlan header or that the
36     /// slice length is matching the header length.
37     ///
38     /// If you are not sure what this means, use [`SingleVlanHeaderSlice::from_slice`]
39     /// instead.
40     ///
41     /// # Safety
42     ///
43     /// The caller must ensured that the given slice has the length of
44     /// [`SingleVlanHeader::LEN`]
45     #[inline]
from_slice_unchecked(slice: &[u8]) -> SingleVlanHeaderSlice46     pub(crate) unsafe fn from_slice_unchecked(slice: &[u8]) -> SingleVlanHeaderSlice {
47         SingleVlanHeaderSlice { slice }
48     }
49 
50     /// Returns the slice containing the single vlan header
51     #[inline]
slice(&self) -> &'a [u8]52     pub fn slice(&self) -> &'a [u8] {
53         self.slice
54     }
55 
56     /// Read the "priority_code_point" field from the slice. This is a 3 bit number which refers to the IEEE 802.1p class of service and maps to the frame priority level.
57     #[inline]
priority_code_point(&self) -> VlanPcp58     pub fn priority_code_point(&self) -> VlanPcp {
59         unsafe {
60             // SAFETY: Safe as slice len checked in constructor to be at least 4 &
61             // the bitmask guarantees values does not exceed 0b0000_0111.
62             VlanPcp::new_unchecked((*self.slice.get_unchecked(0) >> 5) & 0b0000_0111)
63         }
64     }
65 
66     /// Read the "drop_eligible_indicator" flag from the slice. Indicates that the frame may be dropped under the presence of congestion.
67     #[inline]
drop_eligible_indicator(&self) -> bool68     pub fn drop_eligible_indicator(&self) -> bool {
69         // SAFETY:
70         // Slice len checked in constructor to be at least 4.
71         unsafe { 0 != (*self.slice.get_unchecked(0) & 0x10) }
72     }
73 
74     /// Reads the 12 bits "vland identifier" field from the slice.
75     #[inline]
vlan_identifier(&self) -> VlanId76     pub fn vlan_identifier(&self) -> VlanId {
77         // SAFETY:
78         // Slice len checked in constructor to be at least 4 &
79         // value and the value is guaranteed not to exceed
80         // 0b0000_1111_1111_1111 as the upper bits have been
81         // bitmasked out.
82         unsafe {
83             VlanId::new_unchecked(u16::from_be_bytes([
84                 *self.slice.get_unchecked(0) & 0b0000_1111,
85                 *self.slice.get_unchecked(1),
86             ]))
87         }
88     }
89 
90     /// Read the "Tag protocol identifier" field from the slice. Refer to the "EtherType" for a list of possible supported values.
91     #[inline]
ether_type(&self) -> EtherType92     pub fn ether_type(&self) -> EtherType {
93         // SAFETY:
94         // Slice len checked in constructor to be at least 4.
95         EtherType(unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(2)) })
96     }
97 
98     /// Decode all the fields and copy the results to a SingleVlanHeader struct
99     #[inline]
to_header(&self) -> SingleVlanHeader100     pub fn to_header(&self) -> SingleVlanHeader {
101         SingleVlanHeader {
102             pcp: self.priority_code_point(),
103             drop_eligible_indicator: self.drop_eligible_indicator(),
104             vlan_id: self.vlan_identifier(),
105             ether_type: self.ether_type(),
106         }
107     }
108 }
109 
110 #[cfg(test)]
111 mod test {
112     use crate::{test_gens::*, *};
113     use alloc::{format, vec::Vec};
114     use proptest::prelude::*;
115 
116     proptest! {
117         #[test]
118         fn from_slice(
119             input in vlan_single_any(),
120             dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
121         ) {
122             // serialize
123             let mut buffer: Vec<u8> = Vec::with_capacity(input.header_len() + dummy_data.len());
124             input.write(&mut buffer).unwrap();
125             buffer.extend(&dummy_data[..]);
126 
127             // normal
128             {
129                 let slice = SingleVlanHeaderSlice::from_slice(&buffer).unwrap();
130                 assert_eq!(slice.slice(), &buffer[..4]);
131             }
132 
133             // slice length to small
134             for len in 0..4 {
135                 assert_eq!(
136                     SingleVlanHeaderSlice::from_slice(&buffer[..len])
137                         .unwrap_err(),
138                     err::LenError{
139                         required_len: 4,
140                         len: len,
141                         len_source: LenSource::Slice,
142                         layer:  err::Layer::VlanHeader,
143                         layer_start_offset: 0,
144                     }
145                 );
146             }
147         }
148     }
149 
150     proptest! {
151         #[test]
152         fn getters(input in vlan_single_any()) {
153             let bytes = input.to_bytes();
154             let slice = SingleVlanHeaderSlice::from_slice(&bytes).unwrap();
155 
156             assert_eq!(input.pcp, slice.priority_code_point());
157             assert_eq!(input.drop_eligible_indicator, slice.drop_eligible_indicator());
158             assert_eq!(input.vlan_id, slice.vlan_identifier());
159             assert_eq!(input.ether_type, slice.ether_type());
160         }
161     }
162 
163     proptest! {
164         #[test]
165         fn to_header(input in vlan_single_any()) {
166             let bytes = input.to_bytes();
167             let slice = SingleVlanHeaderSlice::from_slice(&bytes).unwrap();
168             assert_eq!(input, slice.to_header());
169         }
170     }
171 
172     proptest! {
173         #[test]
174         fn clone_eq(input in vlan_single_any()) {
175             let bytes = input.to_bytes();
176             let slice = SingleVlanHeaderSlice::from_slice(&bytes).unwrap();
177             assert_eq!(slice, slice.clone());
178         }
179     }
180 
181     proptest! {
182         #[test]
183         fn dbg(input in vlan_single_any()) {
184             let bytes = input.to_bytes();
185             let slice = SingleVlanHeaderSlice::from_slice(&bytes).unwrap();
186             assert_eq!(
187                 &format!(
188                     "SingleVlanHeaderSlice {{ slice: {:?} }}",
189                     slice.slice(),
190                 ),
191                 &format!("{:?}", slice)
192             );
193         }
194     }
195 }
196