• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::*;
2 
3 /// IEEE 802.1Q VLAN Tagging Header
4 #[derive(Clone, Debug, Eq, PartialEq, Default)]
5 pub struct SingleVlanHeader {
6     /// A 3 bit number which refers to the IEEE 802.1p class of service and maps to the frame priority level.
7     pub pcp: VlanPcp,
8     /// Indicate that the frame may be dropped under the presence of congestion.
9     pub drop_eligible_indicator: bool,
10     /// 12 bits vland identifier.
11     pub vlan_id: VlanId,
12     /// "Tag protocol identifier": Type id of content after this header. Refer to the "EtherType" for a list of possible supported values.
13     pub ether_type: EtherType,
14 }
15 
16 impl SingleVlanHeader {
17     /// Serialized size of an VLAN header in bytes/octets.
18     pub const LEN: usize = 4;
19 
20     #[deprecated(since = "0.14.0", note = "Use `SingleVlanHeader::LEN` instead")]
21     pub const SERIALIZED_SIZE: usize = SingleVlanHeader::LEN;
22 
23     /// Read an SingleVlanHeader from a slice and return the header & unused parts of the slice.
24     #[deprecated(since = "0.10.1", note = "Use SingleVlanHeader::from_slice instead.")]
25     #[inline]
read_from_slice(slice: &[u8]) -> Result<(SingleVlanHeader, &[u8]), err::LenError>26     pub fn read_from_slice(slice: &[u8]) -> Result<(SingleVlanHeader, &[u8]), err::LenError> {
27         SingleVlanHeader::from_slice(slice)
28     }
29 
30     /// Read an SingleVlanHeader from a slice and return the header & unused parts of the slice.
31     #[inline]
from_slice(slice: &[u8]) -> Result<(SingleVlanHeader, &[u8]), err::LenError>32     pub fn from_slice(slice: &[u8]) -> Result<(SingleVlanHeader, &[u8]), err::LenError> {
33         Ok((
34             SingleVlanHeaderSlice::from_slice(slice)?.to_header(),
35             &slice[SingleVlanHeader::LEN..],
36         ))
37     }
38 
39     /// Read an SingleVlanHeader from a static sized byte array.
40     #[inline]
from_bytes(bytes: [u8; 4]) -> SingleVlanHeader41     pub fn from_bytes(bytes: [u8; 4]) -> SingleVlanHeader {
42         SingleVlanHeader {
43             pcp: unsafe {
44                 // SAFETY: Safe as bitmasks guarantee that value does not exceed
45                 //         0b0000_0111.
46                 VlanPcp::new_unchecked((bytes[0] >> 5) & 0b0000_0111u8)
47             },
48             drop_eligible_indicator: 0 != (bytes[0] & 0b0001_0000u8),
49             vlan_id: unsafe {
50                 // SAFETY: Safe as bitmasks guarantee that value does not exceed
51                 //         0b0000_1111_1111_1111.
52                 VlanId::new_unchecked(u16::from_be_bytes([bytes[0] & 0b0000_1111u8, bytes[1]]))
53             },
54             ether_type: EtherType(u16::from_be_bytes([bytes[2], bytes[3]])),
55         }
56     }
57 
58     /// Read a IEEE 802.1Q VLAN tagging header
59     #[cfg(feature = "std")]
60     #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
read<T: std::io::Read + std::io::Seek + Sized>( reader: &mut T, ) -> Result<SingleVlanHeader, std::io::Error>61     pub fn read<T: std::io::Read + std::io::Seek + Sized>(
62         reader: &mut T,
63     ) -> Result<SingleVlanHeader, std::io::Error> {
64         let buffer = {
65             let mut buffer: [u8; SingleVlanHeader::LEN] = [0; SingleVlanHeader::LEN];
66             reader.read_exact(&mut buffer)?;
67             buffer
68         };
69 
70         Ok(
71             // SAFETY: Safe as the buffer has the exact size of an vlan header.
72             unsafe { SingleVlanHeaderSlice::from_slice_unchecked(&buffer) }.to_header(),
73         )
74     }
75 
76     /// Write the IEEE 802.1Q VLAN tagging header
77     #[inline]
78     #[cfg(feature = "std")]
79     #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error>80     pub fn write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error> {
81         writer.write_all(&self.to_bytes())
82     }
83 
84     /// Length of the serialized header in bytes.
85     #[inline]
header_len(&self) -> usize86     pub fn header_len(&self) -> usize {
87         4
88     }
89 
90     /// Returns the serialized form of the header or an value error in case
91     /// the header values are outside of range.
92     #[inline]
to_bytes(&self) -> [u8; 4]93     pub fn to_bytes(&self) -> [u8; 4] {
94         let id_be = self.vlan_id.value().to_be_bytes();
95         let eth_type_be = self.ether_type.0.to_be_bytes();
96         [
97             (if self.drop_eligible_indicator {
98                 id_be[0] | 0x10
99             } else {
100                 id_be[0]
101             } | (self.pcp.value() << 5)),
102             id_be[1],
103             eth_type_be[0],
104             eth_type_be[1],
105         ]
106     }
107 }
108 
109 #[cfg(test)]
110 mod test {
111     use crate::{test_gens::*, *};
112     use alloc::{format, vec::Vec};
113     use proptest::prelude::*;
114     use std::io::{Cursor, ErrorKind};
115 
116     #[test]
constants()117     fn constants() {
118         assert_eq!(4, SingleVlanHeader::LEN);
119     }
120 
121     proptest! {
122         #[test]
123         fn from_slice(
124             input in vlan_single_any(),
125             dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
126         ) {
127             // serialize
128             let mut buffer: Vec<u8> = Vec::with_capacity(input.header_len() + dummy_data.len());
129             input.write(&mut buffer).unwrap();
130             buffer.extend(&dummy_data[..]);
131 
132             // normal
133             {
134                 let (result, rest) = SingleVlanHeader::from_slice(&buffer).unwrap();
135                 assert_eq!(result, input);
136                 assert_eq!(rest, &buffer[4..]);
137             }
138             #[allow(deprecated)]
139             {
140                 let (result, rest) = SingleVlanHeader::read_from_slice(&buffer).unwrap();
141                 assert_eq!(result, input);
142                 assert_eq!(rest, &buffer[4..]);
143             }
144 
145             // slice length to small
146             for len in 0..4 {
147                 assert_eq!(
148                     SingleVlanHeader::from_slice(&buffer[..len])
149                         .unwrap_err(),
150                     err::LenError{
151                         required_len: 4,
152                         len: len,
153                         len_source: LenSource::Slice,
154                         layer:  err::Layer::VlanHeader,
155                         layer_start_offset: 0,
156                     }
157                 );
158             }
159         }
160     }
161 
162     proptest! {
163         #[test]
164         fn from_bytes(input in vlan_single_any()) {
165             let actual = SingleVlanHeader::from_bytes(
166                 input.to_bytes()
167             );
168             assert_eq!(actual, input);
169         }
170     }
171 
172     proptest! {
173         #[test]
174         fn read(
175             input in vlan_single_any(),
176             dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
177         ) {
178             // serialize
179             let mut buffer: Vec<u8> = Vec::with_capacity(input.header_len() + dummy_data.len());
180             input.write(&mut buffer).unwrap();
181             buffer.extend(&dummy_data[..]);
182 
183             // normal
184             {
185                 let mut cursor = Cursor::new(&buffer);
186                 let result = SingleVlanHeader::read(&mut cursor).unwrap();
187                 assert_eq!(result, input);
188                 assert_eq!(4, cursor.position());
189             }
190 
191             // unexpexted eof
192             for len in 0..4 {
193                 let mut cursor = Cursor::new(&buffer[0..len]);
194                 assert_eq!(
195                     SingleVlanHeader::read(&mut cursor)
196                     .unwrap_err()
197                     .kind(),
198                     ErrorKind::UnexpectedEof
199                 );
200             }
201         }
202     }
203 
204     proptest! {
205         #[test]
206         fn write_and_to_bytes(input in vlan_single_any()) {
207             // normal write
208             {
209                 let mut buffer: Vec<u8> = Vec::with_capacity(input.header_len());
210                 input.write(&mut buffer).unwrap();
211                 assert_eq!(&buffer[..], &input.to_bytes());
212                 {
213                     let id_be = input.vlan_id.value().to_be_bytes();
214                     let eth_type_be = input.ether_type.0.to_be_bytes();
215                     assert_eq!(
216                         input.to_bytes(),
217                         [
218                             (
219                                 id_be[0] | if input.drop_eligible_indicator {
220                                     0x10
221                                 } else {
222                                     0
223                                 } | (input.pcp.value() << 5)
224                             ),
225                             id_be[1],
226                             eth_type_be[0],
227                             eth_type_be[1]
228                         ]
229                     );
230                 }
231             }
232 
233             // unexpected eof
234             for len in 0..4 {
235                 let mut buffer = [0u8;4];
236                 let mut cursor = Cursor::new(&mut buffer[..len]);
237                 assert!(input.write(&mut cursor).is_err());
238             }
239         }
240     }
241 
242     proptest! {
243         #[test]
244         fn header_len(input in vlan_single_any()) {
245             assert_eq!(4, input.header_len());
246         }
247     }
248 
249     #[test]
default()250     fn default() {
251         let actual: SingleVlanHeader = Default::default();
252         assert_eq!(0, actual.pcp.value());
253         assert_eq!(false, actual.drop_eligible_indicator);
254         assert_eq!(0, actual.vlan_id.value());
255         assert_eq!(0, actual.ether_type.0);
256     }
257 
258     proptest! {
259         #[test]
260         fn clone_eq(input in vlan_single_any()) {
261             assert_eq!(input, input.clone());
262         }
263     }
264 
265     proptest! {
266         #[test]
267         fn dbg(input in vlan_single_any()) {
268             assert_eq!(
269                 &format!(
270                     "SingleVlanHeader {{ pcp: {:?}, drop_eligible_indicator: {}, vlan_id: {:?}, ether_type: {:?} }}",
271                     input.pcp,
272                     input.drop_eligible_indicator,
273                     input.vlan_id,
274                     input.ether_type,
275                 ),
276                 &format!("{:?}", input)
277             );
278         }
279     }
280 }
281