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