• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::{err::*, *};
2 
3 /// Slice containing a VLAN header & payload.
4 #[derive(Clone, Eq, PartialEq)]
5 pub struct SingleVlanSlice<'a> {
6     pub(crate) slice: &'a [u8],
7 }
8 
9 impl<'a> SingleVlanSlice<'a> {
10     /// Try creating a [`SingleVlanSlice`] from a slice containing the
11     /// VLAN header & payload.
from_slice(slice: &'a [u8]) -> Result<SingleVlanSlice<'a>, LenError>12     pub fn from_slice(slice: &'a [u8]) -> Result<SingleVlanSlice<'a>, LenError> {
13         // check length
14         if slice.len() < SingleVlanHeader::LEN {
15             return Err(err::LenError {
16                 required_len: SingleVlanHeader::LEN,
17                 len: slice.len(),
18                 len_source: LenSource::Slice,
19                 layer: err::Layer::VlanHeader,
20                 layer_start_offset: 0,
21             });
22         }
23 
24         Ok(SingleVlanSlice { slice })
25     }
26 
27     /// Returns the slice containing the VLAN header and payload.
28     #[inline]
slice(&self) -> &'a [u8]29     pub fn slice(&self) -> &'a [u8] {
30         self.slice
31     }
32 
33     /// Read the "priority_code_point" field of the VLAN header.
34     ///
35     /// This is a 3 bit number which refers to the IEEE 802.1p class
36     /// of service and maps to the frame priority level.
37     #[inline]
priority_code_point(&self) -> VlanPcp38     pub fn priority_code_point(&self) -> VlanPcp {
39         unsafe {
40             // SAFETY: Safe as slice len checked in constructor to be at least 4 &
41             // the bitmask guarantees values does not exceed 0b0000_0111.
42             VlanPcp::new_unchecked((*self.slice.get_unchecked(0) >> 5) & 0b0000_0111)
43         }
44     }
45 
46     /// Read the "drop_eligible_indicator" flag of the VLAN header.
47     ///
48     /// Indicates that the frame may be dropped under the presence
49     /// of congestion.
50     #[inline]
drop_eligible_indicator(&self) -> bool51     pub fn drop_eligible_indicator(&self) -> bool {
52         // SAFETY:
53         // Slice len checked in constructor to be at least 4.
54         unsafe { 0 != (*self.slice.get_unchecked(0) & 0x10) }
55     }
56 
57     /// Reads the 12 bits "vland identifier" field from the VLAN header.
58     #[inline]
vlan_identifier(&self) -> VlanId59     pub fn vlan_identifier(&self) -> VlanId {
60         // SAFETY:
61         // Slice len checked in constructor to be at least 4 &
62         // value and the value is guranteed not to exceed
63         // 0b0000_1111_1111_1111 as the upper bits have been
64         // bitmasked out.
65         unsafe {
66             VlanId::new_unchecked(u16::from_be_bytes([
67                 *self.slice.get_unchecked(0) & 0b0000_1111,
68                 *self.slice.get_unchecked(1),
69             ]))
70         }
71     }
72 
73     /// Read the "Tag protocol identifier" field from the VLAN header.
74     ///
75     /// Refer to the "EtherType" for a list of possible supported values.
76     #[inline]
ether_type(&self) -> EtherType77     pub fn ether_type(&self) -> EtherType {
78         // SAFETY:
79         // Slice len checked in constructor to be at least 4.
80         EtherType(unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(2)) })
81     }
82 
83     /// Decode all the fields and copy the results to a SingleVlanHeader struct
84     #[inline]
to_header(&self) -> SingleVlanHeader85     pub fn to_header(&self) -> SingleVlanHeader {
86         SingleVlanHeader {
87             pcp: self.priority_code_point(),
88             drop_eligible_indicator: self.drop_eligible_indicator(),
89             vlan_id: self.vlan_identifier(),
90             ether_type: self.ether_type(),
91         }
92     }
93 
94     /// Slice containing the Ethernet 2 header.
header_slice(&self) -> &[u8]95     pub fn header_slice(&self) -> &[u8] {
96         unsafe {
97             // SAFETY:
98             // Safe as the contructor checks that the slice has
99             // at least the length of SingleVlanHeader::LEN (4).
100             core::slice::from_raw_parts(self.slice.as_ptr(), SingleVlanHeader::LEN)
101         }
102     }
103 
104     /// Returns the slice containing the VLAN payload & ether type
105     /// identifying it's content type.
106     #[inline]
payload(&self) -> EtherPayloadSlice<'a>107     pub fn payload(&self) -> EtherPayloadSlice<'a> {
108         EtherPayloadSlice {
109             ether_type: self.ether_type(),
110             payload: self.payload_slice(),
111         }
112     }
113 
114     /// Returns the slice containing the VLAN payload.
115     #[inline]
payload_slice(&self) -> &'a [u8]116     pub fn payload_slice(&self) -> &'a [u8] {
117         unsafe {
118             // SAFETY:
119             // Safe as the contructor checks that the slice has
120             // at least the length of SingleVlanHeader::LEN (4).
121             core::slice::from_raw_parts(
122                 self.slice.as_ptr().add(SingleVlanHeader::LEN),
123                 self.slice.len() - SingleVlanHeader::LEN,
124             )
125         }
126     }
127 
128     /// Length of the VLAN header in bytes (equal to
129     /// [`crate::SingleVlanHeader::LEN`]).
130     #[inline]
header_len(&self) -> usize131     pub const fn header_len(&self) -> usize {
132         SingleVlanHeader::LEN
133     }
134 }
135 
136 impl core::fmt::Debug for SingleVlanSlice<'_> {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result137     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
138         f.debug_struct("SingleVlanSlice")
139             .field("header", &self.to_header())
140             .field("payload", &self.payload())
141             .finish()
142     }
143 }
144 
145 #[cfg(test)]
146 mod test {
147     use super::*;
148     use crate::test_gens::*;
149     use alloc::{format, vec::Vec};
150     use proptest::prelude::*;
151 
152     proptest! {
153         #[test]
154         fn debug_clone_eq(
155             vlan in vlan_single_any()
156         ) {
157             let payload: [u8;8] = [1,2,3,4,5,6,7,8];
158             let mut data = Vec::with_capacity(
159                 vlan.header_len() +
160                 payload.len()
161             );
162             data.extend_from_slice(&vlan.to_bytes());
163             data.extend_from_slice(&payload);
164 
165             // decode packet
166             let slice = SingleVlanSlice::from_slice(&data).unwrap();
167 
168             // check debug output
169             prop_assert_eq!(
170                 format!("{:?}", slice),
171                 format!(
172                     "SingleVlanSlice {{ header: {:?}, payload: {:?} }}",
173                     slice.to_header(),
174                     slice.payload(),
175                 )
176             );
177             prop_assert_eq!(slice.clone(), slice);
178         }
179     }
180 
181     proptest! {
182         #[test]
183         fn getters(vlan in vlan_single_any()) {
184             let payload: [u8;8] = [1,2,3,4,5,6,7,8];
185             let mut data = Vec::with_capacity(
186                 vlan.header_len() +
187                 payload.len()
188             );
189             data.extend_from_slice(&vlan.to_bytes());
190             data.extend_from_slice(&payload);
191 
192             let slice = SingleVlanSlice::from_slice(&data).unwrap();
193             assert_eq!(&data, slice.slice());
194             assert_eq!(vlan.pcp, slice.priority_code_point());
195             assert_eq!(vlan.drop_eligible_indicator, slice.drop_eligible_indicator());
196             assert_eq!(vlan.vlan_id, slice.vlan_identifier());
197             assert_eq!(vlan.ether_type, slice.ether_type());
198             assert_eq!(vlan, slice.to_header());
199             assert_eq!(&data[..SingleVlanHeader::LEN], slice.header_slice());
200 
201             assert_eq!(
202                 EtherPayloadSlice {
203                     ether_type: vlan.ether_type,
204                     payload: &data[SingleVlanHeader::LEN..],
205                 },
206                 slice.payload()
207             );
208             assert_eq!(&data[SingleVlanHeader::LEN..], slice.payload_slice());
209             assert_eq!(SingleVlanHeader::LEN, slice.header_len());
210         }
211     }
212 
213     proptest! {
214         #[test]
215         fn from_slice(vlan in vlan_single_any()) {
216 
217             let payload: [u8;10] = [1,2,3,4,5,6,7,8,9,10];
218             let data = {
219                 let mut data = Vec::with_capacity(
220                     vlan.header_len() +
221                     payload.len()
222                 );
223                 data.extend_from_slice(&vlan.to_bytes());
224                 data.extend_from_slice(&payload);
225                 data
226             };
227 
228             // normal decode
229             {
230                 let slice = SingleVlanSlice::from_slice(&data).unwrap();
231                 assert_eq!(slice.to_header(), vlan);
232                 assert_eq!(slice.payload_slice(), &payload);
233             }
234 
235             // length error
236             for len in 0..SingleVlanHeader::LEN {
237                 assert_eq!(
238                     SingleVlanSlice::from_slice(&data[..len]).unwrap_err(),
239                     LenError{
240                         required_len: SingleVlanHeader::LEN,
241                         len,
242                         len_source: LenSource::Slice,
243                         layer: Layer::VlanHeader,
244                         layer_start_offset: 0
245                     }
246                 );
247             }
248         }
249     }
250 }
251