1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
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(Clone, Debug, PartialEq, Eq)]
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);
}
}
|