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