1use pnet_macros_support::types::{u1, u10be, u12be, u3, u4};
6
7#[derive(PartialEq)]
8pub struct ERSPANPacket<'p> {
13 packet: pnet_macros_support::packet::PacketData<'p>,
14}
15
16impl<'a> ERSPANPacket<'a> {
17 #[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 #[inline]
33 pub fn minimum_packet_size() -> usize {
34 8
35 }
36 #[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 #[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 #[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 #[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 #[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 #[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}