nex_packet/
vlan.rs

1//! A VLAN (802.1Q) packet abstraction.
2//!
3use crate::{
4    ethernet::EtherType,
5    packet::{MutablePacket, Packet},
6};
7use bytes::{Buf, BufMut, Bytes, BytesMut};
8use nex_core::bitfield::{u1, u12be};
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11
12/// VLAN Header length in bytes
13pub const VLAN_HEADER_LEN: usize = 4;
14
15/// Class of Service (IEEE 802.1p Priority Code Point)
16#[repr(u8)]
17#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
18#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
19pub enum ClassOfService {
20    // Background
21    BK = 1,
22    // Best Effort
23    BE = 0,
24    // Excellent Effort
25    EE = 2,
26    // Critical Applications
27    CA = 3,
28    // Video
29    VI = 4,
30    // Voice
31    VO = 5,
32    // Internetwork Control
33    IC = 6,
34    // Network Control
35    NC = 7,
36    /// Unknown Class of Service
37    Unknown(u8),
38}
39
40impl ClassOfService {
41    pub fn new(val: u8) -> Self {
42        match val {
43            0 => ClassOfService::BE,
44            1 => ClassOfService::BK,
45            2 => ClassOfService::EE,
46            3 => ClassOfService::CA,
47            4 => ClassOfService::VI,
48            5 => ClassOfService::VO,
49            6 => ClassOfService::IC,
50            7 => ClassOfService::NC,
51            other => ClassOfService::Unknown(other),
52        }
53    }
54
55    pub fn value(&self) -> u8 {
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(v) => v,
66        }
67    }
68}
69
70/// VLAN header structure
71#[derive(Clone, Debug, PartialEq, Eq)]
72#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
73pub struct VlanHeader {
74    pub priority_code_point: ClassOfService,
75    pub drop_eligible_id: u1,
76    pub vlan_id: u12be,
77    pub ethertype: EtherType,
78}
79
80/// VLAN packet
81#[derive(Clone, Debug, PartialEq, Eq)]
82pub struct VlanPacket {
83    pub header: VlanHeader,
84    pub payload: Bytes,
85}
86
87impl Packet for VlanPacket {
88    type Header = VlanHeader;
89
90    fn from_buf(mut bytes: &[u8]) -> Option<Self> {
91        if bytes.len() < VLAN_HEADER_LEN {
92            return None;
93        }
94
95        // VLAN TCI
96        let tci = bytes.get_u16();
97        let raw_pcp = ((tci >> 13) & 0b111) as u8;
98        println!("DEBUG: tci=0x{:04x}, raw_pcp={}", tci, raw_pcp);
99        let pcp = ClassOfService::new(((tci >> 13) & 0b111) as u8);
100        let drop_eligible_id = ((tci >> 12) & 0b1) as u1;
101        let vlan_id = (tci & 0x0FFF) as u12be;
102
103        // EtherType
104        let ethertype = EtherType::new(bytes.get_u16());
105
106        // Payload
107        Some(VlanPacket {
108            header: VlanHeader {
109                priority_code_point: pcp,
110                drop_eligible_id,
111                vlan_id,
112                ethertype,
113            },
114            payload: Bytes::copy_from_slice(bytes),
115        })
116    }
117    fn from_bytes(mut bytes: Bytes) -> Option<Self> {
118        Self::from_buf(&mut bytes)
119    }
120
121    fn to_bytes(&self) -> Bytes {
122        let mut buf = BytesMut::with_capacity(VLAN_HEADER_LEN + self.payload.len());
123
124        let pcp_bits = (self.header.priority_code_point.value() as u16 & 0b111) << 13;
125        let dei_bits = (self.header.drop_eligible_id as u16 & 0b1) << 12;
126        let vlan_bits = self.header.vlan_id as u16 & 0x0FFF;
127
128        let tci = pcp_bits | dei_bits | vlan_bits;
129
130        buf.put_u16(tci);
131        buf.put_u16(self.header.ethertype.value());
132        buf.extend_from_slice(&self.payload);
133
134        buf.freeze()
135    }
136
137    fn header(&self) -> Bytes {
138        let mut buf = BytesMut::with_capacity(VLAN_HEADER_LEN);
139
140        let mut first = (self.header.priority_code_point.value() & 0b111) << 5;
141        first |= (self.header.drop_eligible_id & 0b1) << 4;
142        first |= ((self.header.vlan_id >> 8) & 0b0000_1111) as u8;
143
144        let second = (self.header.vlan_id & 0xFF) as u8;
145
146        buf.put_u8(first);
147        buf.put_u8(second);
148        buf.put_u16(self.header.ethertype.value());
149
150        buf.freeze()
151    }
152
153    fn payload(&self) -> Bytes {
154        self.payload.clone()
155    }
156
157    fn header_len(&self) -> usize {
158        VLAN_HEADER_LEN
159    }
160
161    fn payload_len(&self) -> usize {
162        self.payload.len()
163    }
164
165    fn total_len(&self) -> usize {
166        self.header_len() + self.payload_len()
167    }
168
169    fn into_parts(self) -> (Self::Header, Bytes) {
170        (self.header, self.payload)
171    }
172}
173
174/// Represents a mutable VLAN packet.
175pub struct MutableVlanPacket<'a> {
176    buffer: &'a mut [u8],
177}
178
179impl<'a> MutablePacket<'a> for MutableVlanPacket<'a> {
180    type Packet = VlanPacket;
181
182    fn new(buffer: &'a mut [u8]) -> Option<Self> {
183        if buffer.len() < VLAN_HEADER_LEN {
184            None
185        } else {
186            Some(Self { buffer })
187        }
188    }
189
190    fn packet(&self) -> &[u8] {
191        &*self.buffer
192    }
193
194    fn packet_mut(&mut self) -> &mut [u8] {
195        &mut *self.buffer
196    }
197
198    fn header(&self) -> &[u8] {
199        &self.packet()[..VLAN_HEADER_LEN]
200    }
201
202    fn header_mut(&mut self) -> &mut [u8] {
203        let (header, _) = (&mut *self.buffer).split_at_mut(VLAN_HEADER_LEN);
204        header
205    }
206
207    fn payload(&self) -> &[u8] {
208        &self.packet()[VLAN_HEADER_LEN..]
209    }
210
211    fn payload_mut(&mut self) -> &mut [u8] {
212        let (_, payload) = (&mut *self.buffer).split_at_mut(VLAN_HEADER_LEN);
213        payload
214    }
215}
216
217impl<'a> MutableVlanPacket<'a> {
218    pub fn new_unchecked(buffer: &'a mut [u8]) -> Self {
219        Self { buffer }
220    }
221
222    fn raw(&self) -> &[u8] {
223        &*self.buffer
224    }
225
226    fn raw_mut(&mut self) -> &mut [u8] {
227        &mut *self.buffer
228    }
229
230    pub fn get_priority_code_point(&self) -> ClassOfService {
231        let first = self.raw()[0];
232        ClassOfService::new(first >> 5)
233    }
234
235    pub fn set_priority_code_point(&mut self, class: ClassOfService) {
236        let buf = self.raw_mut();
237        buf[0] = (buf[0] & 0x1F) | ((class.value() & 0x07) << 5);
238    }
239
240    pub fn get_drop_eligible_id(&self) -> u1 {
241        ((self.raw()[0] >> 4) & 0x01) as u1
242    }
243
244    pub fn set_drop_eligible_id(&mut self, dei: u1) {
245        let buf = self.raw_mut();
246        buf[0] = (buf[0] & !(1 << 4)) | (((dei & 0x1) as u8) << 4);
247    }
248
249    pub fn get_vlan_id(&self) -> u16 {
250        let first = self.raw()[0] as u16 & 0x0F;
251        let second = self.raw()[1] as u16;
252        (first << 8) | second
253    }
254
255    pub fn set_vlan_id(&mut self, id: u16) {
256        let buf = self.raw_mut();
257        buf[0] = (buf[0] & 0xF0) | ((id >> 8) as u8 & 0x0F);
258        buf[1] = id as u8;
259    }
260
261    pub fn get_ethertype(&self) -> EtherType {
262        EtherType::new(u16::from_be_bytes([self.raw()[2], self.raw()[3]]))
263    }
264
265    pub fn set_ethertype(&mut self, ty: EtherType) {
266        self.raw_mut()[2..4].copy_from_slice(&ty.value().to_be_bytes());
267    }
268}
269
270#[cfg(test)]
271mod tests {
272    use super::*;
273
274    #[test]
275    fn test_vlan_parse() {
276        let raw = Bytes::from_static(&[
277            0x20, 0x00, // TCI: pcp=1 (BK), dei=0, vid=0
278            0x08, 0x00, // EtherType: IPv4
279            b'x', b'y', b'z',
280        ]);
281
282        let packet = VlanPacket::from_bytes(raw.clone()).unwrap();
283
284        assert_eq!(packet.header.priority_code_point, ClassOfService::BK);
285        assert_eq!(packet.header.drop_eligible_id, 0);
286        assert_eq!(packet.header.vlan_id, 0x000);
287        assert_eq!(packet.header.ethertype, EtherType::Ipv4);
288        assert_eq!(packet.payload, Bytes::from_static(b"xyz"));
289        assert_eq!(packet.to_bytes(), raw);
290    }
291
292    #[test]
293    fn test_vlan_parse_2() {
294        let raw = Bytes::from_static(&[
295            0x01, 0x00, // TCI: PCP=0(BE), DEI=0, VID=0x100
296            0x08, 0x00, // EtherType: IPv4
297            b'x', b'y', b'z',
298        ]);
299
300        let packet = VlanPacket::from_bytes(raw.clone()).unwrap();
301
302        assert_eq!(packet.header.priority_code_point, ClassOfService::BE);
303        assert_eq!(packet.header.drop_eligible_id, 0);
304        assert_eq!(packet.header.vlan_id, 0x100);
305        assert_eq!(packet.header.ethertype, EtherType::Ipv4);
306        assert_eq!(packet.payload, Bytes::from_static(b"xyz"));
307        assert_eq!(packet.to_bytes(), raw);
308    }
309
310    #[test]
311    fn test_mutable_vlan_packet_changes() {
312        let mut raw = [
313            0x00, 0x01, // TCI
314            0x08, 0x00, // EtherType: IPv4
315            b'a', b'b',
316        ];
317
318        let mut packet = MutableVlanPacket::new(&mut raw).expect("mutable vlan");
319        assert_eq!(packet.get_vlan_id(), 1);
320        packet.set_priority_code_point(ClassOfService::VO);
321        packet.set_vlan_id(0x0abc);
322        packet.set_ethertype(EtherType::Ipv6);
323        packet.payload_mut()[0] = b'z';
324
325        let frozen = packet.freeze().expect("freeze");
326        assert_eq!(frozen.header.priority_code_point, ClassOfService::VO);
327        assert_eq!(frozen.header.vlan_id, 0x0abc);
328        assert_eq!(frozen.header.ethertype, EtherType::Ipv6);
329        assert_eq!(frozen.payload[0], b'z');
330    }
331}