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