pako_core/
geneve.rs

1//!
2//! Support for Generic Network Virtualization Encapsulation (GENEVE)
3//!
4
5use pnet_macros_support::types::{u1, u16be, u2, u24be, u5, u6};
6
7#[derive(PartialEq)]
8/// A structure enabling manipulation of on the wire packets
9pub struct GENEVEPacket<'p> {
10    packet: pnet_macros_support::packet::PacketData<'p>,
11}
12
13impl<'a> GENEVEPacket<'a> {
14    /// Constructs a new GENEVE packet. If the provided buffer is less than the minimum required
15    /// packet size, this will return None.
16    pub fn new(packet: &[u8]) -> Option<GENEVEPacket> {
17        if packet.len() >= GENEVEPacket::minimum_packet_size() {
18            use ::pnet_macros_support::packet::PacketData;
19            Some(GENEVEPacket {
20                packet: PacketData::Borrowed(packet),
21            })
22        } else {
23            None
24        }
25    }
26
27    /// The minimum size (in bytes) a packet of this type can be. It's based on the total size
28    /// of the fixed-size fields.
29    pub fn minimum_packet_size() -> usize {
30        8
31    }
32
33    /// The version the GENEVE tunnel header.
34    pub fn get_stack_size(&self) -> u2 {
35        (self.packet[0] >> 6) as u2
36    }
37
38    /// The length of option fields
39    pub fn get_option_length(&self) -> u6 {
40        (self.packet[0] & 0b0011_1111) as u6
41    }
42
43    /// Get control packet flag
44    ///
45    /// True if packet contains a control message.
46    pub fn get_control(&self) -> u1 {
47        (self.packet[1] >> 7) as u1
48    }
49
50    /// Get critical flag
51    pub fn get_critical(&self) -> u1 {
52        ((self.packet[1] >> 6) & 0b01) as u1
53    }
54
55    /// Get reserved bits
56    pub fn get_reserved(&self) -> u6 {
57        (self.packet[1] & 0b0011_1111) as u1
58    }
59
60    /// Get protocol type
61    pub fn get_protocol_type(&self) -> u16be {
62        ((self.packet[2] as u16be) << 8) | (self.packet[3] as u16be)
63    }
64
65    /// Get Virtual Network Identifier (VNI)
66    pub fn get_virtual_network_identifier(&self) -> u24be {
67        ((self.packet[4] as u24be) << 16)
68            | ((self.packet[5] as u24be) << 8)
69            | (self.packet[6] as u24be)
70    }
71
72    /// Get second reserved bits
73    pub fn get_reserved2(&self) -> u8 {
74        self.packet[7]
75    }
76
77    /// Get the raw &[u8] value of the options field, without copying
78    pub fn get_options_raw(&self) -> &[u8] {
79        use std::cmp::min;
80        let _self = self;
81        let current_offset = 8;
82        let options_len = (self.get_option_length() as usize) * 4;
83        let end = min(current_offset + options_len, _self.packet.len());
84        &_self.packet[current_offset..end]
85    }
86
87    /// Get the value of the options field (copies contents)
88    pub fn get_options(&self) -> Vec<GENEVEOption> {
89        use pnet_packet::FromPacket;
90        let buf = self.get_options_raw();
91        GENEVEOptionIterable { buf }
92            .map(|packet| packet.from_packet())
93            .collect::<Vec<_>>()
94    }
95
96    /// Get the value of the options field as iterator
97    pub fn get_options_iter(&self) -> GENEVEOptionIterable {
98        let buf = self.get_options_raw();
99        GENEVEOptionIterable { buf }
100    }
101}
102
103impl<'a> pnet_macros_support::packet::Packet for GENEVEPacket<'a> {
104    fn packet(&self) -> &[u8] {
105        &self.packet[..]
106    }
107
108    fn payload(&self) -> &[u8] {
109        let _self = self;
110        let options_len = (self.get_option_length() as usize) * 4;
111        let start = std::cmp::min(8 + options_len, self.packet.len());
112        &_self.packet[start..]
113    }
114}
115
116/// Represents the Geneve Option field.
117#[derive(Clone, Debug)]
118pub struct GENEVEOption {
119    option_class: u16be,
120    option_type: u8,
121    length: u5,
122    data: Vec<u8>,
123}
124
125impl GENEVEOption {
126    pub fn option_class(&self) -> u16be {
127        self.option_class
128    }
129    pub fn option_type(&self) -> u8 {
130        self.option_type
131    }
132    pub fn option_length(&self) -> u5 {
133        self.length
134    }
135    pub fn option_data(&self) -> &[u8] {
136        &self.data
137    }
138}
139
140#[derive(PartialEq)]
141/// A structure enabling manipulation of on the wire packets
142pub struct GENEVEOptionPacket<'p> {
143    packet: pnet_macros_support::packet::PacketData<'p>,
144}
145
146impl<'a> GENEVEOptionPacket<'a> {
147    /// Constructs a new GeneveOptionPacket. If the provided buffer is less than the minimum required
148    /// packet size, this will return None.
149    pub fn new(packet: &'_ [u8]) -> Option<GENEVEOptionPacket<'_>> {
150        if packet.len() >= GENEVEOptionPacket::minimum_packet_size() {
151            use ::pnet_macros_support::packet::PacketData;
152            Some(GENEVEOptionPacket {
153                packet: PacketData::Borrowed(packet),
154            })
155        } else {
156            None
157        }
158    }
159
160    /// The minimum size (in bytes) a packet of this type can be. It's based on the total size
161    /// of the fixed-size fields.
162    pub const fn minimum_packet_size() -> usize {
163        4
164    }
165
166    /// Get Option Class
167    pub fn get_option_class(&self) -> u16be {
168        ((self.packet[0] as u16be) << 8) | (self.packet[1] as u16be)
169    }
170
171    /// Get Option Type
172    pub fn get_option_type(&self) -> u8 {
173        self.packet[2]
174    }
175
176    /// Get the Option Length field
177    pub fn get_option_length(&self) -> u5 {
178        (self.packet[3] & 0b0001_1111) as u5
179    }
180}
181
182impl<'a> pnet_macros_support::packet::Packet for GENEVEOptionPacket<'a> {
183    fn packet(&self) -> &[u8] {
184        &self.packet[..]
185    }
186
187    fn payload(&self) -> &[u8] {
188        let _self = self;
189        let options_len = (self.get_option_length() as usize) * 4;
190        let start = std::cmp::min(4 + options_len, self.packet.len());
191        &_self.packet[start..]
192    }
193}
194
195impl<'a> pnet_macros_support::packet::PacketSize for GENEVEOptionPacket<'a> {
196    fn packet_size(&self) -> usize {
197        4 + 4 * (self.get_option_length() as usize)
198    }
199}
200
201impl<'p> pnet_macros_support::packet::FromPacket for GENEVEOptionPacket<'p> {
202    type T = GENEVEOption;
203
204    fn from_packet(&self) -> GENEVEOption {
205        use pnet_macros_support::packet::Packet;
206        let _self = self;
207        GENEVEOption {
208            option_class: _self.get_option_class(),
209            option_type: _self.get_option_type(),
210            length: _self.get_option_length(),
211            data: {
212                let payload = self.payload();
213                let mut vec = Vec::with_capacity(payload.len());
214                vec.extend_from_slice(payload);
215                vec
216            },
217        }
218    }
219}
220
221pub struct GENEVEOptionIterable<'a> {
222    buf: &'a [u8],
223}
224
225impl<'a> Iterator for GENEVEOptionIterable<'a> {
226    type Item = GENEVEOptionPacket<'a>;
227    fn next(&mut self) -> Option<GENEVEOptionPacket<'a>> {
228        use std::cmp::min;
229
230        use pnet_macros_support::packet::PacketSize;
231        if !self.buf.is_empty() {
232            if let Some(ret) = GENEVEOptionPacket::new(self.buf) {
233                let start = min(ret.packet_size(), self.buf.len());
234                self.buf = &self.buf[start..];
235                return Some(ret);
236            }
237        }
238        None
239    }
240    fn size_hint(&self) -> (usize, Option<usize>) {
241        (0, None)
242    }
243}