xenet_packet/
vlan.rs

1//! A VLAN packet abstraction.
2
3use crate::ethernet::EtherType;
4use crate::PrimitiveValues;
5
6use alloc::vec::Vec;
7
8use xenet_macro::packet;
9use xenet_macro_helper::types::*;
10
11/// Represents an IEEE 802.1p class of a service.
12/// <https://en.wikipedia.org/wiki/IEEE_P802.1p>
13#[repr(u8)]
14#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
15pub enum ClassOfService {
16    /// Background
17    BK = 1,
18    /// Best Effort
19    BE = 0,
20    /// Excellent Effort
21    EE = 2,
22    /// Critical Applications
23    CA = 3,
24    /// Video, < 100 ms latency
25    VI = 4,
26    /// Voice, < 10 ms latency
27    VO = 5,
28    /// Internetwork Control
29    IC = 6,
30    /// Network Control
31    NC = 7,
32    /// Unknown class of service
33    Unknown(u3),
34}
35
36impl ClassOfService {
37    /// Constructs a new ClassOfServiceEnum from u3.
38    pub fn new(value: u3) -> ClassOfService {
39        match value {
40            1 => ClassOfService::BK,
41            0 => ClassOfService::BE,
42            2 => ClassOfService::EE,
43            3 => ClassOfService::CA,
44            4 => ClassOfService::VI,
45            5 => ClassOfService::VO,
46            6 => ClassOfService::IC,
47            7 => ClassOfService::NC,
48            _ => ClassOfService::Unknown(value),
49        }
50    }
51}
52
53impl PrimitiveValues for ClassOfService {
54    type T = (u3,);
55    fn to_primitive_values(&self) -> (u3,) {
56        match *self {
57            ClassOfService::BK => (1,),
58            ClassOfService::BE => (0,),
59            ClassOfService::EE => (2,),
60            ClassOfService::CA => (3,),
61            ClassOfService::VI => (4,),
62            ClassOfService::VO => (5,),
63            ClassOfService::IC => (6,),
64            ClassOfService::NC => (7,),
65            ClassOfService::Unknown(n) => (n,),
66        }
67    }
68}
69
70/// Represents a VLAN-tagged packet.
71#[packet]
72pub struct Vlan {
73    #[construct_with(u3)]
74    pub priority_code_point: ClassOfService,
75    pub drop_eligible_indicator: u1,
76    pub vlan_identifier: u12be,
77    #[construct_with(u16be)]
78    pub ethertype: EtherType,
79    #[payload]
80    pub payload: Vec<u8>,
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86    use crate::ethernet::EtherType;
87
88    #[test]
89    fn vlan_packet_test() {
90        let mut packet = [0u8; 4];
91        {
92            let mut vlan_header = MutableVlanPacket::new(&mut packet[..]).unwrap();
93            vlan_header.set_priority_code_point(ClassOfService::BE);
94            assert_eq!(vlan_header.get_priority_code_point(), ClassOfService::BE);
95
96            vlan_header.set_drop_eligible_indicator(0);
97            assert_eq!(vlan_header.get_drop_eligible_indicator(), 0);
98
99            vlan_header.set_ethertype(EtherType::Ipv4);
100            assert_eq!(vlan_header.get_ethertype(), EtherType::Ipv4);
101
102            vlan_header.set_vlan_identifier(0x100);
103            assert_eq!(vlan_header.get_vlan_identifier(), 0x100);
104        }
105
106        let ref_packet = [
107            0x01, // PCP, DEI, and first nibble of VID
108            0x00, // Remainder of VID
109            0x08, // First byte of ethertype
110            0x00,
111        ]; // Second byte of ethertype
112        assert_eq!(&ref_packet[..], &packet[..]);
113    }
114}