pako_core/
erspan.rs

1//!
2//! Support for Encapsulated Remote Switched Port Analyzer (ERSPAN)
3//!
4
5use pnet_macros_support::types::{u1, u10be, u12be, u3, u4};
6
7#[derive(PartialEq)]
8/// ERSPAN packet support
9///
10/// ERSPAN is a Cisco proprietary feature and is available only
11/// on specific routers and switches
12pub struct ERSPANPacket<'p> {
13    packet: pnet_macros_support::packet::PacketData<'p>,
14}
15
16impl<'a> ERSPANPacket<'a> {
17    /// Constructs a new ErspanPacket. If the provided buffer is less than the minimum required
18    /// packet size, this will return None.
19    #[inline]
20    pub fn new(packet: &[u8]) -> Option<ERSPANPacket> {
21        if packet.len() >= ERSPANPacket::minimum_packet_size() {
22            use ::pnet_macros_support::packet::PacketData;
23            Some(ERSPANPacket {
24                packet: PacketData::Borrowed(packet),
25            })
26        } else {
27            None
28        }
29    }
30    /// The minimum size (in bytes) a packet of this type can be. It's based on the total size
31    /// of the fixed-size fields.
32    #[inline]
33    pub fn minimum_packet_size() -> usize {
34        8
35    }
36    /// Get the version field.
37    #[inline]
38    #[allow(trivial_numeric_casts)]
39    #[cfg_attr(feature = "clippy", allow(used_underscore_binding))]
40    pub fn get_version(&self) -> u4 {
41        let _self = self;
42        let co = 0;
43        (_self.packet[co] as u4) >> 4
44    }
45    /// Get the vlan field.
46    #[inline]
47    #[allow(trivial_numeric_casts)]
48    #[cfg_attr(feature = "clippy", allow(used_underscore_binding))]
49    pub fn get_vlan(&self) -> u12be {
50        let _self = self;
51        let b0 = (((_self.packet[0] & 0b0000_1111) as u12be) << 8) as u12be;
52        let b1 = (_self.packet[1] as u12be) as u12be;
53        b0 | b1
54    }
55    /// Get the COS field.
56    #[inline]
57    #[allow(trivial_numeric_casts)]
58    #[cfg_attr(feature = "clippy", allow(used_underscore_binding))]
59    pub fn get_cos(&self) -> u3 {
60        let _self = self;
61        let co = 2;
62        (_self.packet[co] as u3) >> 5
63    }
64    /// Get the encap field.
65    #[inline]
66    #[allow(trivial_numeric_casts)]
67    #[cfg_attr(feature = "clippy", allow(used_underscore_binding))]
68    pub fn get_encap(&self) -> u3 {
69        let _self = self;
70        let co = 2;
71        ((_self.packet[co] as u3) >> 3) & 0b11
72    }
73    /// Get the truncated field.
74    #[inline]
75    #[allow(trivial_numeric_casts)]
76    #[cfg_attr(feature = "clippy", allow(used_underscore_binding))]
77    pub fn get_truncated(&self) -> u1 {
78        let _self = self;
79        let co = 2;
80        ((_self.packet[co] as u1) >> 2) & 0b1
81    }
82    /// Get the span ID field.
83    #[inline]
84    #[allow(trivial_numeric_casts, clippy::identity_op)]
85    #[cfg_attr(feature = "clippy", allow(used_underscore_binding))]
86    pub fn get_span_id(&self) -> u10be {
87        let _self = self;
88        let co = 2;
89        let b0 = (((_self.packet[co + 0] & 0b0000_0011) as u10be) << 8) as u10be;
90        let b1 = (_self.packet[co + 1] as u10be) as u10be;
91        b0 | b1
92    }
93}
94impl<'a> ::pnet_macros_support::packet::Packet for ERSPANPacket<'a> {
95    #[inline]
96    fn packet(&self) -> &[u8] {
97        &self.packet[..]
98    }
99    #[inline]
100    #[cfg_attr(feature = "clippy", allow(used_underscore_binding))]
101    fn payload(&self) -> &[u8] {
102        let _self = self;
103        let start = 8;
104        let end = _self.packet.len();
105        if _self.packet.len() <= start {
106            return &[];
107        }
108        &_self.packet[start..end]
109    }
110}
111#[cfg(test)]
112mod tests {
113    use pnet_macros_support::packet::Packet;
114
115    use super::ERSPANPacket;
116    const DATA: &[u8] = b"\x10\x17\x08\x64\x00\x00\x00\x00\x12\x34";
117    #[test]
118    fn erspan_test() {
119        let packet = ERSPANPacket::new(DATA).expect("ErspanPacket");
120        assert_eq!(packet.get_version(), 1);
121        assert_eq!(packet.get_vlan(), 23);
122        assert_eq!(packet.get_cos(), 0);
123        assert_eq!(packet.get_encap(), 1);
124        assert_eq!(packet.get_truncated(), 0);
125        assert_eq!(packet.get_span_id(), 100);
126        assert_eq!(packet.payload(), &[0x12, 0x34]);
127    }
128}