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