Skip to main content

network_types/
geneve.rs

1use crate::{getter_be, setter_be};
2
3/// Represents a Geneve (Generic Network Virtualization Encapsulation) header, according to RFC 8926.
4/// Geneve is an encapsulation protocol designed for network virtualization.
5///
6#[repr(C)]
7#[derive(Debug, Copy, Clone, Default)]
8pub struct GeneveHdr {
9    /// Combined field: Version (2 bits) and Option Length (6 bits).
10    pub ver_opt_len: u8,
11    /// Combined field: OAM flag (1 bit), Critical flag (1 bit), Reserved (6 bits).
12    pub o_c_rsvd: u8,
13    /// Protocol Type of the encapsulated payload (16 bits).
14    pub protocol_type: [u8; 2],
15    /// Virtual Network Identifier (VNI) (24 bits).
16    pub vni: [u8; 3],
17    /// Reserved field (8 bits). MUST be zero on transmission.
18    pub reserved2: u8,
19}
20
21impl GeneveHdr {
22    /// The length of the Geneve header in bytes.
23    pub const LEN: usize = core::mem::size_of::<GeneveHdr>();
24
25    /// Returns the Geneve protocol version (2 bits).
26    ///
27    /// According to RFC 8926, the current version is 0.
28    #[inline]
29    pub fn ver(&self) -> u8 {
30        (self.ver_opt_len >> 6) & 0x03
31    }
32
33    /// Sets the Geneve protocol version (2 bits).
34    ///
35    /// `ver` should be a 2-bit value (0-3).
36    #[inline]
37    pub fn set_ver(&mut self, ver: u8) {
38        let preserved_bits = self.ver_opt_len & 0x3F;
39        self.ver_opt_len = preserved_bits | ((ver & 0x03) << 6);
40    }
41
42    /// Returns the length of the option fields in 4-byte multiples (6 bits).
43    #[inline]
44    pub fn opt_len(&self) -> u8 {
45        self.ver_opt_len & 0x3F
46    }
47
48    /// Sets the length of the option fields (6 bits).
49    ///
50    /// `opt_len` should be a 6-bit value (0-63).
51    #[inline]
52    pub fn set_opt_len(&mut self, opt_len: u8) {
53        let preserved_bits = self.ver_opt_len & 0xC0;
54        self.ver_opt_len = preserved_bits | (opt_len & 0x3F);
55    }
56
57    /// Returns the OAM (Operations, Administration, and Maintenance) packet flag (1 bit).
58    ///
59    /// If set (1), this packet is an OAM packet. Referred to as 'O' bit in RFC 8926.
60    #[inline]
61    pub fn o_flag(&self) -> u8 {
62        (self.o_c_rsvd >> 7) & 0x01
63    }
64
65    /// Sets the OAM packet flag (1 bit).
66    ///
67    /// `o_flag` should be a 1-bit value (0 or 1).
68    #[inline]
69    pub fn set_o_flag(&mut self, o_flag: u8) {
70        let preserved_bits = self.o_c_rsvd & 0x7F;
71        self.o_c_rsvd = preserved_bits | ((o_flag & 0x01) << 7);
72    }
73
74    /// Returns the Critical Options Present flag (1 bit).
75    ///
76    /// If set (1), one or more options are marked as critical. Referred to as 'C' bit in RFC 8926.
77    #[inline]
78    pub fn c_flag(&self) -> u8 {
79        (self.o_c_rsvd >> 6) & 0x01
80    }
81
82    /// Sets the Critical Options Present flag (1 bit).
83    ///
84    /// `c_flag` should be a 1-bit value (0 or 1).
85    #[inline]
86    pub fn set_c_flag(&mut self, c_flag: u8) {
87        let preserved_bits = self.o_c_rsvd & 0xBF;
88        self.o_c_rsvd = preserved_bits | ((c_flag & 0x01) << 6);
89    }
90
91    /// Returns the Protocol Type of the encapsulated payload (16 bits, network byte order).
92    ///
93    /// This follows the Ethertype convention.
94    #[inline]
95    pub fn protocol_type(&self) -> u16 {
96        // SAFETY: Pointer arithmetic in bounds of the struct.
97        unsafe { getter_be!(self, protocol_type, u16) }
98    }
99
100    /// Sets the Protocol Type (16 bits).
101    ///
102    /// The value is stored in network byte order.
103    #[inline]
104    pub fn set_protocol_type(&mut self, protocol_type: u16) {
105        // SAFETY: Pointer arithmetic in bounds of the struct.
106        unsafe { setter_be!(self, protocol_type, protocol_type) }
107    }
108
109    /// Returns the Virtual Network Identifier (VNI) (24 bits).
110    #[inline]
111    pub fn vni(&self) -> u32 {
112        u32::from_be_bytes([0, self.vni[0], self.vni[1], self.vni[2]])
113    }
114
115    /// Sets the Virtual Network Identifier (VNI) (24 bits).
116    ///
117    /// `vni` should be a 24-bit value. Higher bits are masked.
118    /// The value is stored in network byte order.
119    #[inline]
120    pub fn set_vni(&mut self, vni: u32) {
121        let vni_val = vni & 0x00FFFFFF;
122        let bytes = vni_val.to_be_bytes();
123        self.vni[0] = bytes[1];
124        self.vni[1] = bytes[2];
125        self.vni[2] = bytes[3]
126    }
127}
128
129#[cfg(test)]
130mod tests {
131    use super::*;
132
133    #[test]
134    fn test_len() {
135        assert_eq!(GeneveHdr::LEN, 8);
136    }
137
138    #[test]
139    fn test_default() {
140        let hdr = GeneveHdr::default();
141        assert_eq!(hdr.ver_opt_len, 0);
142        assert_eq!(hdr.o_c_rsvd, 0);
143        assert_eq!(hdr.protocol_type, [0, 0]);
144        assert_eq!(hdr.vni, [0, 0, 0]);
145        assert_eq!(hdr.reserved2, 0);
146
147        assert_eq!(hdr.ver(), 0);
148        assert_eq!(hdr.opt_len(), 0);
149        assert_eq!(hdr.o_flag(), 0);
150        assert_eq!(hdr.c_flag(), 0);
151        assert_eq!(hdr.protocol_type(), 0);
152        assert_eq!(hdr.vni(), 0);
153    }
154
155    #[test]
156    fn test_ver() {
157        let mut hdr = GeneveHdr::default();
158        hdr.set_ver(0b10); // Version 2
159        assert_eq!(hdr.ver(), 0b10);
160        assert_eq!(hdr.ver_opt_len, 0b10000000, "Raw byte for ver failed");
161
162        hdr.set_ver(0b111); // Input 7 (3 bits), should be masked to 0b11 (3)
163        assert_eq!(hdr.ver(), 0b11);
164        assert_eq!(hdr.ver_opt_len, 0b11000000, "Masking for ver failed");
165
166        // Test interaction with opt_len
167        hdr.ver_opt_len = 0; // Reset
168        hdr.set_opt_len(0x3F); // Max opt_len (all lower 6 bits set)
169        hdr.set_ver(0b01);
170        assert_eq!(hdr.ver(), 0b01);
171        assert_eq!(hdr.opt_len(), 0x3F, "opt_len altered by set_ver");
172        assert_eq!(
173            hdr.ver_opt_len, 0b01111111,
174            "Interaction with opt_len failed"
175        );
176    }
177
178    #[test]
179    fn test_opt_len() {
180        let mut hdr = GeneveHdr::default();
181        hdr.set_opt_len(0x2A); // 42
182        assert_eq!(hdr.opt_len(), 0x2A);
183        assert_eq!(hdr.ver_opt_len, 0b00101010, "Raw byte for opt_len failed");
184
185        hdr.set_opt_len(0xFF); // Input 255, should be masked to 0x3F (63)
186        assert_eq!(hdr.opt_len(), 0x3F);
187        assert_eq!(hdr.ver_opt_len, 0b00111111, "Masking for opt_len failed");
188
189        // Test interaction with ver
190        hdr.ver_opt_len = 0; // Reset
191        hdr.set_ver(0b11); // Max ver (top 2 bits set)
192        hdr.set_opt_len(0x15); // 21
193        assert_eq!(hdr.ver(), 0b11, "ver altered by set_opt_len");
194        assert_eq!(hdr.opt_len(), 0x15);
195        assert_eq!(hdr.ver_opt_len, 0b11010101, "Interaction with ver failed");
196    }
197
198    #[test]
199    fn test_o_flag() {
200        let mut hdr = GeneveHdr::default();
201        hdr.set_o_flag(1);
202        assert_eq!(hdr.o_flag(), 1);
203        assert_eq!(hdr.o_c_rsvd, 0b10000000, "Raw byte for o_flag failed");
204
205        // The implementation correctly masks the input, so an input of 2 (0b10) becomes 0.
206        // This sets the o_flag back to 0.
207        hdr.set_o_flag(0b10);
208        assert_eq!(hdr.o_flag(), 0);
209        assert_eq!(hdr.o_c_rsvd, 0b00000000, "Masking for o_flag failed");
210
211        // Test that setting the O flag preserves the C flag and reserved bits.
212        hdr.o_c_rsvd = 0; // Reset
213        hdr.set_c_flag(1); // o_c_rsvd is now 0b01000000
214
215        // Now, set the O flag.
216        hdr.set_o_flag(1);
217
218        // Verify that only the O flag bit changed.
219        assert_eq!(hdr.o_flag(), 1, "o_flag should be 1");
220        assert_eq!(hdr.c_flag(), 1, "c_flag should be preserved");
221    }
222
223    #[test]
224    fn test_c_flag() {
225        let mut hdr = GeneveHdr::default();
226        hdr.set_c_flag(1);
227        assert_eq!(hdr.c_flag(), 1);
228        assert_eq!(hdr.o_c_rsvd, 0b01000000, "Raw byte for c_flag failed");
229
230        // The implementation correctly masks the input, so an input of 2 (0b10) becomes 0.
231        // This sets the c_flag back to 0.
232        hdr.set_c_flag(0b10);
233        assert_eq!(hdr.c_flag(), 0);
234        assert_eq!(hdr.o_c_rsvd, 0b00000000, "Masking for c_flag failed");
235
236        // Test that setting the C flag preserves the O flag and reserved bits.
237        hdr.o_c_rsvd = 0; // Reset
238        hdr.set_o_flag(1); // o_c_rsvd is now 0b10000000
239
240        // Now, set the C flag.
241        hdr.set_c_flag(1);
242
243        // Verify that only the C flag bit changed.
244        assert_eq!(hdr.c_flag(), 1, "c_flag should be 1");
245        assert_eq!(hdr.o_flag(), 1, "o_flag should be preserved");
246    }
247
248    #[test]
249    fn test_protocol_type() {
250        let mut hdr = GeneveHdr::default();
251        hdr.set_protocol_type(0xABCD);
252        assert_eq!(hdr.protocol_type(), 0xABCD);
253        assert_eq!(
254            hdr.protocol_type,
255            [0xAB, 0xCD],
256            "Raw bytes for protocol_type failed (Big Endian check)"
257        );
258    }
259
260    #[test]
261    fn test_vni() {
262        let mut hdr = GeneveHdr::default();
263        hdr.set_vni(0x00123456);
264        assert_eq!(hdr.vni(), 0x00123456);
265        assert_eq!(
266            hdr.vni,
267            [0x12, 0x34, 0x56],
268            "Raw bytes for VNI failed (Big Endian check)"
269        );
270
271        hdr.set_vni(0xFF123456); // Input with >24 bits
272        assert_eq!(hdr.vni(), 0x00123456, "Masking for VNI failed");
273        assert_eq!(
274            hdr.vni,
275            [0x12, 0x34, 0x56],
276            "Raw bytes after VNI masking failed"
277        );
278    }
279}