use crate::protocol::codec::Decode; use crate::protocol::ethernet::EthType; use nom::bits; use nom::error::Error; use nom::sequence; use nom::IResult; /****************************************************************************** * Struct ******************************************************************************/ #[derive(Debug, PartialEq)] pub struct VLANHeader { // A 3 bit number which refers to the IEEE 802.1p class of service and maps to the frame priority level. pub priority_code_point: u8, // Indicate that the frame may be dropped under the presence of congestion. pub drop_eligible_indicator: bool, // 12 bits vland identifier. pub vlan_identifier: u16, // "Tag protocol identifier": Type id of content after this header. Refer to the "EthType" for a list of possible supported values. pub ether_type: EthType, } /****************************************************************************** * API ******************************************************************************/ fn bit_decode(input: &[u8]) -> IResult<&[u8], (u8, u8, u16)> { bits::bits::<_, _, Error<_>, _, _>(sequence::tuple(( bits::streaming::take(3u8), bits::streaming::take(1u8), bits::streaming::take(12u8), )))(input) } impl Decode for VLANHeader { type Iterm = VLANHeader; fn decode(input: &[u8]) -> IResult<&[u8], VLANHeader> { let (input, (priority_code_point, drop_eligible_indicator, vlan_identifier)) = bit_decode(input)?; let (input, ether_type) = EthType::decode(input)?; Ok(( input, VLANHeader { priority_code_point, drop_eligible_indicator: drop_eligible_indicator == 1, vlan_identifier, ether_type, }, )) } } /****************************************************************************** * TEST ******************************************************************************/ #[cfg(test)] mod tests { use super::VLANHeader; use crate::protocol::codec::Decode; use crate::protocol::ethernet::EthType; const LAST_SLICE: &'static [u8] = &[0xff]; #[test] fn vlan_header_decode() { /* * 802.1Q Virtual LAN, PRI: 0, DEI: 0, ID: 32 * 000. .... .... .... = Priority: Best Effort (default) (0) * ...0 .... .... .... = DEI: Ineligible * .... 0000 0010 0000 = ID: 32 * Type: IPv4 (0x0800) */ let bytes = [0x00, 0x20, 0x08, 0x00, 0xff /* Payload */]; let expectation = VLANHeader { priority_code_point: 0, drop_eligible_indicator: false, vlan_identifier: 32, ether_type: EthType::IPv4, }; assert_eq!(VLANHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); // example let result = VLANHeader::decode(&bytes); match result { Ok((payload, header)) => { println!("OK: {:?}, payload: {}", header, payload.len()); } Err(e) => { println!("ERR: {:?}", e); } } // assert_eq!(1, 0); } }