pako_core/
vxlan.rs

1use pnet_macros_support::types::{u16be, u24be};
2
3#[derive(PartialEq)]
4/// A structure enabling manipulation of on the wire packets
5pub struct VxlanPacket<'p> {
6    packet: ::pnet_macros_support::packet::PacketData<'p>,
7}
8
9/// Represents Vxlan flag.
10#[derive(Hash, Ord, PartialOrd, Eq, PartialEq, Debug, Copy, Clone)]
11pub struct VxlanFlag(pub u16);
12
13impl VxlanFlag {
14    /// Create a new `VxlanFlag` instance.
15    pub fn new(value: u16) -> VxlanFlag {
16        VxlanFlag(value)
17    }
18}
19
20/// Vxlan flags as defined in RFC7348
21#[allow(non_snake_case)]
22#[allow(non_upper_case_globals)]
23pub mod VxlanFlags {
24    use super::VxlanFlag;
25
26    /// VXLAN Network ID (VNI)
27    pub const VNI: VxlanFlag = VxlanFlag(0x0800);
28}
29
30impl<'a> VxlanPacket<'a> {
31    /// Constructs a new VxlanPacket. If the provided buffer is less than the minimum required
32    /// packet size, this will return None.
33    #[inline]
34    pub fn new(packet: &[u8]) -> Option<VxlanPacket> {
35        if packet.len() >= VxlanPacket::minimum_packet_size() {
36            use ::pnet_macros_support::packet::PacketData;
37            Some(VxlanPacket {
38                packet: PacketData::Borrowed(packet),
39            })
40        } else {
41            None
42        }
43    }
44    /// The minimum size (in bytes) a packet of this type can be. It's based on the total size
45    /// of the fixed-size fields.
46    #[inline]
47    pub const fn minimum_packet_size() -> usize {
48        8
49    }
50    /// Get the flags field. This field is always stored big-endian
51    /// within the struct, but this accessor returns host order.
52    #[inline]
53    #[allow(trivial_numeric_casts)]
54    #[cfg_attr(feature = "clippy", allow(used_underscore_binding))]
55    pub fn get_flags(&self) -> u16be {
56        let _self = self;
57        let b0 = ((_self.packet[0] as u16be) << 8) as u16be;
58        let b1 = _self.packet[1] as u16be;
59        b0 | b1
60    }
61    /// Get the vxlan_identifier field. This field is always stored big-endian
62    /// within the struct, but this accessor returns host order.
63    #[inline]
64    #[allow(trivial_numeric_casts)]
65    #[cfg_attr(feature = "clippy", allow(used_underscore_binding))]
66    pub fn get_vlan_identifier(&self) -> u24be {
67        let _self = self;
68        let co = 4;
69        let b0 = ((_self.packet[co] as u24be) << 16) as u24be;
70        let b1 = ((_self.packet[co + 1] as u24be) << 8) as u24be;
71        let b2 = _self.packet[co + 2] as u24be;
72        b0 | b1 | b2
73    }
74}
75impl<'a> ::pnet_macros_support::packet::Packet for VxlanPacket<'a> {
76    #[inline]
77    fn packet(&self) -> &[u8] {
78        &self.packet[..]
79    }
80    #[inline]
81    #[cfg_attr(feature = "clippy", allow(used_underscore_binding))]
82    fn payload(&self) -> &[u8] {
83        let _self = self;
84        let start = 8;
85        let end = _self.packet.len();
86        if _self.packet.len() <= start {
87            return &[];
88        }
89        &_self.packet[start..end]
90    }
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96    const DATA: &[u8] = b"\x08\x00\x00\x00\x00\x00\x7b\x00";
97    #[test]
98    fn vxlan_test() {
99        let packet = VxlanPacket::new(DATA).expect("VxlanPacket");
100        assert_eq!(packet.get_vlan_identifier(), 123);
101        assert_eq!(packet.get_flags(), VxlanFlags::VNI.0);
102    }
103}