nex_packet/
vxlan.rs

1//! A VXLAN packet abstraction.
2use bytes::{Buf, Bytes};
3use nex_core::bitfield::{self, u24be};
4
5use crate::packet::{GenericMutablePacket, Packet};
6
7/// Virtual eXtensible Local Area Network (VXLAN)
8///
9/// See [RFC 7348](https://datatracker.ietf.org/doc/html/rfc7348)
10///
11/// VXLAN Header:
12/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13/// |R|R|R|R|I|R|R|R|            Reserved                           |
14/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15/// |                VXLAN Network Identifier (VNI) |   Reserved    |
16/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17pub struct VxlanPacket {
18    pub flags: u8,
19    pub reserved1: u24be,
20    pub vni: u24be,
21    pub reserved2: u8,
22    pub payload: Bytes,
23}
24
25impl Packet for VxlanPacket {
26    type Header = ();
27
28    fn from_buf(mut bytes: &[u8]) -> Option<Self> {
29        if bytes.len() < 8 {
30            return None;
31        }
32
33        let flags = bytes.get_u8();
34
35        let reserved1 = {
36            let b1 = bytes.get_u8();
37            let b2 = bytes.get_u8();
38            let b3 = bytes.get_u8();
39            bitfield::utils::u24be_from_bytes([b1, b2, b3])
40        };
41
42        let vni = {
43            let b1 = bytes.get_u8();
44            let b2 = bytes.get_u8();
45            let b3 = bytes.get_u8();
46            bitfield::utils::u24be_from_bytes([b1, b2, b3])
47        };
48
49        let reserved2 = bytes.get_u8();
50
51        let payload = Bytes::copy_from_slice(bytes);
52
53        Some(Self {
54            flags,
55            reserved1,
56            vni,
57            reserved2,
58            payload,
59        })
60    }
61
62    fn from_bytes(bytes: Bytes) -> Option<Self> {
63        Self::from_buf(&bytes)
64    }
65
66    fn to_bytes(&self) -> Bytes {
67        use bytes::BufMut;
68        let mut buf = bytes::BytesMut::with_capacity(8 + self.payload.len());
69
70        buf.put_u8(self.flags);
71        buf.put_slice(&bitfield::utils::u24be_to_bytes(self.reserved1));
72        buf.put_slice(&bitfield::utils::u24be_to_bytes(self.vni));
73        buf.put_u8(self.reserved2);
74        buf.put_slice(&self.payload);
75
76        buf.freeze()
77    }
78    fn header(&self) -> Bytes {
79        use bytes::BufMut;
80        let mut buf = bytes::BytesMut::with_capacity(8);
81
82        buf.put_u8(self.flags);
83        buf.put_slice(&self.reserved1.to_be_bytes());
84        buf.put_slice(&self.vni.to_be_bytes());
85        buf.put_u8(self.reserved2);
86
87        buf.freeze()
88    }
89
90    fn payload(&self) -> Bytes {
91        self.payload.clone()
92    }
93
94    fn header_len(&self) -> usize {
95        8
96    }
97
98    fn payload_len(&self) -> usize {
99        self.payload.len()
100    }
101
102    fn total_len(&self) -> usize {
103        self.header_len() + self.payload_len()
104    }
105
106    fn into_parts(self) -> (Self::Header, Bytes) {
107        ((), self.payload)
108    }
109}
110
111/// Represents a mutable VXLAN packet.
112pub type MutableVxlanPacket<'a> = GenericMutablePacket<'a, VxlanPacket>;
113
114#[cfg(test)]
115mod tests {
116    use super::*;
117
118    #[test]
119    fn vxlan_packet_test() {
120        let packet = Bytes::from_static(&[
121            0x08, // I flag
122            0x00, 0x00, 0x00, // Reserved
123            0x12, 0x34, 0x56, // VNI
124            0x00, // Reserved
125        ]);
126        let vxlan_packet = VxlanPacket::from_bytes(packet.clone()).unwrap();
127        assert_eq!(vxlan_packet.to_bytes(), packet);
128    }
129
130    #[test]
131    fn mutable_vxlan_packet_test() {
132        let mut raw = [0x08, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00, 0xaa];
133
134        use crate::packet::MutablePacket;
135        let mut packet =
136            <MutableVxlanPacket as MutablePacket>::new(&mut raw).expect("mutable vxlan");
137        packet.header_mut()[0] = 0x0c;
138        packet.payload_mut()[0] = 0xff;
139
140        let frozen = MutablePacket::freeze(&packet).expect("freeze");
141        assert_eq!(frozen.payload[0], 0xff);
142    }
143}