packet_strata/packet/tunnel/
geneve.rs

1//! Geneve (Generic Network Virtualization Encapsulation) protocol parser
2//!
3//! This module implements parsing for Geneve tunnels as defined in RFC 8926.
4//! Geneve provides a flexible encapsulation format for network virtualization
5//! that supports variable-length options.
6//!
7//! # Geneve Header Format
8//!
9//! ```text
10//!  0                   1                   2                   3
11//!  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
12//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13//! |Ver|  Opt Len  |O|C|    Rsvd.  |          Protocol Type        |
14//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15//! |        Virtual Network Identifier (VNI)       |    Reserved   |
16//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17//! |                                                               |
18//! ~                    Variable-Length Options                    ~
19//! |                                                               |
20//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21//! ```
22//!
23//! # Key characteristics
24//!
25//! - UDP destination port: 6081 (IANA assigned)
26//! - VNI (Virtual Network Identifier): 24 bits
27//! - Variable-length options: 0-252 bytes (in 4-byte multiples)
28//! - Version: must be 0
29//! - Typically encapsulates Ethernet frames (protocol type 0x6558)
30//!
31//! # Examples
32//!
33//! ## Basic Geneve parsing (no options)
34//!
35//! ```
36//! use packet_strata::packet::tunnel::geneve::GeneveHeader;
37//! use packet_strata::packet::protocol::EtherProto;
38//! use packet_strata::packet::{HeaderParser, PacketHeader};
39//!
40//! // Geneve packet with VNI = 100, no options
41//! let packet = vec![
42//!     0x00, 0x00, 0x65, 0x58,  // Ver=0, OptLen=0, O=0, C=0, Proto=TEB
43//!     0x00, 0x00, 0x64, 0x00,  // VNI = 100, Reserved
44//!     // ... Ethernet frame follows ...
45//! ];
46//!
47//! let (header, payload) = GeneveHeader::from_bytes(&packet).unwrap();
48//! assert_eq!(header.version(), 0);
49//! assert_eq!(header.vni(), 100);
50//! assert_eq!(header.options_length(), 0);
51//! assert_eq!(header.protocol_type(), EtherProto::TEB);
52//! ```
53//!
54//! ## Geneve with options
55//!
56//! ```
57//! use packet_strata::packet::tunnel::geneve::GeneveHeader;
58//! use packet_strata::packet::HeaderParser;
59//!
60//! // Geneve with 8 bytes of options
61//! let packet = vec![
62//!     0x02, 0x00, 0x65, 0x58,  // Ver=0, OptLen=2 (8 bytes), Proto=TEB
63//!     0x00, 0x01, 0x00, 0x00,  // VNI = 256, Reserved
64//!     // Options (8 bytes)
65//!     0x00, 0x01, 0x80, 0x01,  // Option: Class=1, Type=0x80, Len=1
66//!     0x12, 0x34, 0x56, 0x78,  // Option data
67//!     // ... Ethernet frame follows ...
68//! ];
69//!
70//! let (header, _) = GeneveHeader::from_bytes(&packet).unwrap();
71//! assert_eq!(header.options_length(), 8);
72//! assert_eq!(header.vni(), 256);
73//! ```
74
75use std::fmt::{self, Formatter};
76
77use zerocopy::byteorder::{BigEndian, U16, U32};
78use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
79
80use crate::packet::protocol::EtherProto;
81use crate::packet::{HeaderParser, PacketHeader};
82
83/// Geneve UDP destination port (IANA assigned)
84pub const GENEVE_PORT: u16 = 6081;
85
86/// Maximum VNI value (24-bit field)
87pub const GENEVE_MAX_VNI: u32 = 0xFFFFFF;
88
89/// Maximum options length in bytes (63 * 4 = 252)
90pub const GENEVE_MAX_OPTIONS_LEN: usize = 252;
91
92/// Geneve version (must be 0)
93pub const GENEVE_VERSION: u8 = 0;
94
95/// Geneve Header structure as defined in RFC 8926
96///
97/// The fixed Geneve header is 8 bytes. Variable-length options may follow.
98///
99/// Header format (8 bytes fixed):
100/// ```text
101///  0                   1                   2                   3
102///  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
103/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104/// |Ver|  Opt Len  |O|C|    Rsvd.  |          Protocol Type        |
105/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106/// |        Virtual Network Identifier (VNI)       |    Reserved   |
107/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108/// ```
109#[repr(C, packed)]
110#[derive(FromBytes, IntoBytes, Unaligned, Debug, Clone, Copy, KnownLayout, Immutable)]
111pub struct GeneveHeader {
112    ver_optlen_flags: U16<BigEndian>,
113    protocol_type: U16<BigEndian>,
114    vni_reserved: U32<BigEndian>,
115}
116
117impl GeneveHeader {
118    // Field masks and shifts
119    const VERSION_MASK: u16 = 0xC000;
120    const VERSION_SHIFT: u16 = 14;
121    const OPTLEN_MASK: u16 = 0x3F00;
122    const OPTLEN_SHIFT: u16 = 8;
123    const FLAG_O_MASK: u16 = 0x0080;
124    const FLAG_C_MASK: u16 = 0x0040;
125    const RESERVED_MASK: u16 = 0x003F;
126
127    const VNI_MASK: u32 = 0xFFFFFF00;
128    const VNI_SHIFT: u32 = 8;
129    const VNI_RESERVED_MASK: u32 = 0x000000FF;
130
131    #[allow(unused)]
132    const NAME: &'static str = "GeneveHeader";
133
134    /// Returns the version field (2 bits, must be 0)
135    #[inline]
136    pub fn version(&self) -> u8 {
137        ((self.ver_optlen_flags.get() & Self::VERSION_MASK) >> Self::VERSION_SHIFT) as u8
138    }
139
140    /// Returns the options length in 4-byte units (6 bits)
141    #[inline]
142    pub fn options_length_units(&self) -> u8 {
143        ((self.ver_optlen_flags.get() & Self::OPTLEN_MASK) >> Self::OPTLEN_SHIFT) as u8
144    }
145
146    /// Returns the options length in bytes
147    #[inline]
148    pub fn options_length(&self) -> usize {
149        self.options_length_units() as usize * 4
150    }
151
152    /// Check if the O (OAM) flag is set
153    ///
154    /// When set, indicates this is an OAM (Operations, Administration, and Maintenance) frame.
155    #[inline]
156    pub fn is_oam(&self) -> bool {
157        self.ver_optlen_flags.get() & Self::FLAG_O_MASK != 0
158    }
159
160    /// Check if the C (Critical) flag is set
161    ///
162    /// When set, indicates that critical options are present that must be understood.
163    #[inline]
164    pub fn is_critical(&self) -> bool {
165        self.ver_optlen_flags.get() & Self::FLAG_C_MASK != 0
166    }
167
168    /// Returns the reserved bits in the first word (should be 0)
169    #[inline]
170    pub fn reserved_flags(&self) -> u8 {
171        (self.ver_optlen_flags.get() & Self::RESERVED_MASK) as u8
172    }
173
174    /// Returns the protocol type field
175    ///
176    /// Typically 0x6558 (TEB - Transparent Ethernet Bridging) for Ethernet frames.
177    #[inline]
178    pub fn protocol_type(&self) -> EtherProto {
179        self.protocol_type.get().into()
180    }
181
182    /// Returns the raw protocol type value
183    #[inline]
184    pub fn protocol_type_raw(&self) -> u16 {
185        self.protocol_type.get()
186    }
187
188    /// Returns the Virtual Network Identifier (VNI) - 24 bits
189    #[inline]
190    pub fn vni(&self) -> u32 {
191        (self.vni_reserved.get() & Self::VNI_MASK) >> Self::VNI_SHIFT
192    }
193
194    /// Returns the reserved byte after VNI (should be 0)
195    #[inline]
196    pub fn reserved_vni(&self) -> u8 {
197        (self.vni_reserved.get() & Self::VNI_RESERVED_MASK) as u8
198    }
199
200    /// Returns the total header length including options
201    #[inline]
202    pub fn header_length(&self) -> usize {
203        Self::FIXED_LEN + self.options_length()
204    }
205
206    /// Validates the Geneve header according to RFC 8926
207    #[inline]
208    fn is_valid(&self) -> bool {
209        // Version must be 0
210        if self.version() != GENEVE_VERSION {
211            return false;
212        }
213
214        // Options length must not exceed maximum (63 units = 252 bytes)
215        if self.options_length() > GENEVE_MAX_OPTIONS_LEN {
216            return false;
217        }
218
219        true
220    }
221
222    /// Validates the Geneve header strictly
223    ///
224    /// Checks version, options length, and that reserved bits are 0.
225    #[inline]
226    pub fn is_valid_strict(&self) -> bool {
227        self.is_valid() && self.reserved_flags() == 0 && self.reserved_vni() == 0
228    }
229
230    /// Returns a string representation of flags
231    pub fn flags_string(&self) -> String {
232        let mut flags = Vec::new();
233
234        if self.is_oam() {
235            flags.push("O");
236        }
237        if self.is_critical() {
238            flags.push("C");
239        }
240
241        if flags.is_empty() {
242            "none".to_string()
243        } else {
244            flags.join("")
245        }
246    }
247}
248
249/// Geneve Header with options parsed
250#[derive(Debug, Clone)]
251pub struct GeneveHeaderOpt<'a> {
252    pub header: &'a GeneveHeader,
253    pub options: &'a [u8],
254}
255
256impl<'a> GeneveHeaderOpt<'a> {
257    /// Returns an iterator over the Geneve options
258    pub fn options_iter(&self) -> GeneveOptionsIter<'a> {
259        GeneveOptionsIter {
260            data: self.options,
261            offset: 0,
262        }
263    }
264
265    /// Check if there are any options
266    #[inline]
267    pub fn has_options(&self) -> bool {
268        !self.options.is_empty()
269    }
270}
271
272impl std::ops::Deref for GeneveHeaderOpt<'_> {
273    type Target = GeneveHeader;
274
275    #[inline]
276    fn deref(&self) -> &Self::Target {
277        self.header
278    }
279}
280
281impl PacketHeader for GeneveHeader {
282    const NAME: &'static str = "GeneveHeader";
283    type InnerType = EtherProto;
284
285    #[inline]
286    fn inner_type(&self) -> Self::InnerType {
287        self.protocol_type()
288    }
289
290    #[inline]
291    fn total_len(&self, _buf: &[u8]) -> usize {
292        self.header_length()
293    }
294
295    #[inline]
296    fn is_valid(&self) -> bool {
297        self.is_valid()
298    }
299}
300
301impl HeaderParser for GeneveHeader {
302    type Output<'a> = GeneveHeaderOpt<'a>;
303
304    #[inline]
305    fn into_view<'a>(header: &'a Self, options: &'a [u8]) -> Self::Output<'a> {
306        GeneveHeaderOpt { header, options }
307    }
308}
309
310impl fmt::Display for GeneveHeader {
311    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
312        write!(
313            f,
314            "Geneve v{} vni={} proto={}(0x{:04x}) opt_len={} flags={}",
315            self.version(),
316            self.vni(),
317            self.protocol_type(),
318            self.protocol_type().0,
319            self.options_length(),
320            self.flags_string()
321        )
322    }
323}
324
325impl fmt::Display for GeneveHeaderOpt<'_> {
326    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
327        write!(
328            f,
329            "Geneve v{} vni={} proto={} opt_len={} flags={}",
330            self.version(),
331            self.vni(),
332            self.protocol_type(),
333            self.options_length(),
334            self.flags_string()
335        )?;
336
337        if self.has_options() {
338            write!(f, " options={}", self.options_iter().count())?;
339        }
340
341        Ok(())
342    }
343}
344
345/// Geneve Option header (4 bytes fixed + variable data)
346///
347/// ```text
348///  0                   1                   2                   3
349///  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
350/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
351/// |          Option Class         |      Type     |R|R|R| Length  |
352/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
353/// |                  Variable-Length Option Data                  |
354/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
355/// ```
356#[derive(Debug, Clone, Copy)]
357pub struct GeneveOption<'a> {
358    /// Option class (16 bits)
359    pub option_class: u16,
360    /// Option type (8 bits, high bit indicates critical)
361    pub option_type: u8,
362    /// Option data length in 4-byte units (5 bits)
363    pub length_units: u8,
364    /// Option data
365    pub data: &'a [u8],
366}
367
368impl<'a> GeneveOption<'a> {
369    /// Option header size in bytes
370    pub const HEADER_SIZE: usize = 4;
371
372    /// Check if this is a critical option (high bit of type set)
373    #[inline]
374    pub fn is_critical(&self) -> bool {
375        self.option_type & 0x80 != 0
376    }
377
378    /// Returns the option type without the critical bit
379    #[inline]
380    pub fn type_value(&self) -> u8 {
381        self.option_type & 0x7F
382    }
383
384    /// Returns the data length in bytes
385    #[inline]
386    pub fn data_length(&self) -> usize {
387        self.length_units as usize * 4
388    }
389
390    /// Returns the total option length (header + data)
391    #[inline]
392    pub fn total_length(&self) -> usize {
393        Self::HEADER_SIZE + self.data_length()
394    }
395}
396
397impl fmt::Display for GeneveOption<'_> {
398    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
399        write!(
400            f,
401            "GeneveOpt class=0x{:04x} type=0x{:02x}{} len={}",
402            self.option_class,
403            self.option_type,
404            if self.is_critical() { "(C)" } else { "" },
405            self.data_length()
406        )
407    }
408}
409
410/// Iterator over Geneve options
411pub struct GeneveOptionsIter<'a> {
412    data: &'a [u8],
413    offset: usize,
414}
415
416impl<'a> Iterator for GeneveOptionsIter<'a> {
417    type Item = GeneveOption<'a>;
418
419    fn next(&mut self) -> Option<Self::Item> {
420        if self.offset + GeneveOption::HEADER_SIZE > self.data.len() {
421            return None;
422        }
423
424        let option_class = u16::from_be_bytes([self.data[self.offset], self.data[self.offset + 1]]);
425        let option_type = self.data[self.offset + 2];
426        let length_byte = self.data[self.offset + 3];
427        let length_units = length_byte & 0x1F; // 5 bits for length
428
429        let data_len = length_units as usize * 4;
430        let data_start = self.offset + GeneveOption::HEADER_SIZE;
431        let data_end = data_start + data_len;
432
433        if data_end > self.data.len() {
434            return None;
435        }
436
437        let option = GeneveOption {
438            option_class,
439            option_type,
440            length_units,
441            data: &self.data[data_start..data_end],
442        };
443
444        self.offset = data_end;
445        Some(option)
446    }
447}
448
449/// Check if a UDP packet might be Geneve based on destination port
450#[inline]
451pub fn is_geneve_port(dst_port: u16) -> bool {
452    dst_port == GENEVE_PORT
453}
454
455#[cfg(test)]
456mod tests {
457    use super::*;
458
459    #[test]
460    fn test_geneve_header_size() {
461        assert_eq!(std::mem::size_of::<GeneveHeader>(), 8);
462        assert_eq!(GeneveHeader::FIXED_LEN, 8);
463    }
464
465    #[test]
466    fn test_geneve_basic_header() {
467        let header = GeneveHeader {
468            ver_optlen_flags: U16::new(0x0000), // Ver=0, OptLen=0, O=0, C=0
469            protocol_type: U16::new(0x6558),    // TEB
470            vni_reserved: U32::new(0x00006400), // VNI = 100
471        };
472
473        assert_eq!(header.version(), 0);
474        assert_eq!(header.options_length_units(), 0);
475        assert_eq!(header.options_length(), 0);
476        assert!(!header.is_oam());
477        assert!(!header.is_critical());
478        assert_eq!(header.protocol_type(), EtherProto::TEB);
479        assert_eq!(header.vni(), 100);
480        assert!(header.is_valid());
481        assert!(header.is_valid_strict());
482    }
483
484    #[test]
485    fn test_geneve_with_options() {
486        let header = GeneveHeader {
487            ver_optlen_flags: U16::new(0x0200), // Ver=0, OptLen=2 (8 bytes)
488            protocol_type: U16::new(0x6558),
489            vni_reserved: U32::new(0x00010000), // VNI = 256
490        };
491
492        assert_eq!(header.version(), 0);
493        assert_eq!(header.options_length_units(), 2);
494        assert_eq!(header.options_length(), 8);
495        assert_eq!(header.header_length(), 16); // 8 + 8
496        assert_eq!(header.vni(), 256);
497        assert!(header.is_valid());
498    }
499
500    #[test]
501    fn test_geneve_flags() {
502        // OAM flag set
503        let header_oam = GeneveHeader {
504            ver_optlen_flags: U16::new(0x0080), // O=1
505            protocol_type: U16::new(0x6558),
506            vni_reserved: U32::new(0x00000000),
507        };
508        assert!(header_oam.is_oam());
509        assert!(!header_oam.is_critical());
510
511        // Critical flag set
512        let header_crit = GeneveHeader {
513            ver_optlen_flags: U16::new(0x0040), // C=1
514            protocol_type: U16::new(0x6558),
515            vni_reserved: U32::new(0x00000000),
516        };
517        assert!(!header_crit.is_oam());
518        assert!(header_crit.is_critical());
519
520        // Both flags set
521        let header_both = GeneveHeader {
522            ver_optlen_flags: U16::new(0x00C0), // O=1, C=1
523            protocol_type: U16::new(0x6558),
524            vni_reserved: U32::new(0x00000000),
525        };
526        assert!(header_both.is_oam());
527        assert!(header_both.is_critical());
528    }
529
530    #[test]
531    fn test_geneve_vni_values() {
532        // VNI = 0x123456
533        let header = GeneveHeader {
534            ver_optlen_flags: U16::new(0x0000),
535            protocol_type: U16::new(0x6558),
536            vni_reserved: U32::new(0x12345600),
537        };
538
539        assert_eq!(header.vni(), 0x123456);
540    }
541
542    #[test]
543    fn test_geneve_max_vni() {
544        let header = GeneveHeader {
545            ver_optlen_flags: U16::new(0x0000),
546            protocol_type: U16::new(0x6558),
547            vni_reserved: U32::new(0xFFFFFF00),
548        };
549
550        assert_eq!(header.vni(), GENEVE_MAX_VNI);
551    }
552
553    #[test]
554    fn test_geneve_invalid_version() {
555        // Version 1 (invalid)
556        let header = GeneveHeader {
557            ver_optlen_flags: U16::new(0x4000), // Ver=1
558            protocol_type: U16::new(0x6558),
559            vni_reserved: U32::new(0x00000000),
560        };
561
562        assert_eq!(header.version(), 1);
563        assert!(!header.is_valid());
564    }
565
566    #[test]
567    fn test_geneve_parsing_basic() {
568        let mut packet = Vec::new();
569
570        // Geneve header: Ver=0, OptLen=0, Proto=TEB, VNI=100
571        packet.extend_from_slice(&0x0000u16.to_be_bytes()); // ver_optlen_flags
572        packet.extend_from_slice(&0x6558u16.to_be_bytes()); // protocol_type
573        packet.extend_from_slice(&0x00006400u32.to_be_bytes()); // vni_reserved
574
575        // Payload
576        packet.extend_from_slice(b"ethernet");
577
578        let result = GeneveHeader::from_bytes(&packet);
579        assert!(result.is_ok());
580
581        let (header, payload) = result.unwrap();
582        assert_eq!(header.version(), 0);
583        assert_eq!(header.vni(), 100);
584        assert_eq!(header.options_length(), 0);
585        assert!(!header.has_options());
586        assert_eq!(payload, b"ethernet");
587    }
588
589    #[test]
590    fn test_geneve_parsing_with_options() {
591        let mut packet = Vec::new();
592
593        // Geneve header: Ver=0, OptLen=2 (8 bytes), Proto=TEB, VNI=256
594        packet.extend_from_slice(&0x0200u16.to_be_bytes()); // ver_optlen_flags
595        packet.extend_from_slice(&0x6558u16.to_be_bytes()); // protocol_type
596        packet.extend_from_slice(&0x00010000u32.to_be_bytes()); // vni_reserved
597
598        // Options (8 bytes)
599        packet.extend_from_slice(&0x0001u16.to_be_bytes()); // Option class
600        packet.push(0x80); // Option type (critical)
601        packet.push(0x01); // Length = 1 (4 bytes)
602        packet.extend_from_slice(&[0x12, 0x34, 0x56, 0x78]); // Option data
603
604        // Payload
605        packet.extend_from_slice(b"data");
606
607        let result = GeneveHeader::from_bytes(&packet);
608        assert!(result.is_ok());
609
610        let (header, payload) = result.unwrap();
611        assert_eq!(header.vni(), 256);
612        assert_eq!(header.options_length(), 8);
613        assert!(header.has_options());
614        assert_eq!(payload, b"data");
615
616        // Check options iterator
617        let mut opts = header.options_iter();
618        let opt1 = opts.next().unwrap();
619        assert_eq!(opt1.option_class, 0x0001);
620        assert_eq!(opt1.option_type, 0x80);
621        assert!(opt1.is_critical());
622        assert_eq!(opt1.data_length(), 4);
623        assert_eq!(opt1.data, &[0x12, 0x34, 0x56, 0x78]);
624
625        assert!(opts.next().is_none());
626    }
627
628    #[test]
629    fn test_geneve_parsing_too_small() {
630        let packet = vec![0u8; 7]; // Only 7 bytes, need 8
631
632        let result = GeneveHeader::from_bytes(&packet);
633        assert!(result.is_err());
634    }
635
636    #[test]
637    fn test_geneve_parsing_invalid_version() {
638        let mut packet = Vec::new();
639
640        // Invalid version 1
641        packet.extend_from_slice(&0x4000u16.to_be_bytes()); // Ver=1
642        packet.extend_from_slice(&0x6558u16.to_be_bytes());
643        packet.extend_from_slice(&0x00000000u32.to_be_bytes());
644
645        let result = GeneveHeader::from_bytes(&packet);
646        assert!(result.is_err());
647    }
648
649    #[test]
650    fn test_geneve_inner_type() {
651        let header = GeneveHeader {
652            ver_optlen_flags: U16::new(0x0000),
653            protocol_type: U16::new(0x6558),
654            vni_reserved: U32::new(0x00006400),
655        };
656
657        assert_eq!(header.inner_type(), EtherProto::TEB);
658    }
659
660    #[test]
661    fn test_geneve_display() {
662        let header = GeneveHeader {
663            ver_optlen_flags: U16::new(0x00C0), // O=1, C=1
664            protocol_type: U16::new(0x6558),
665            vni_reserved: U32::new(0x00006400),
666        };
667
668        let display = format!("{}", header);
669        assert!(display.contains("Geneve"));
670        assert!(display.contains("vni=100"));
671        assert!(display.contains("OC"));
672    }
673
674    #[test]
675    fn test_geneve_flags_string() {
676        let header1 = GeneveHeader {
677            ver_optlen_flags: U16::new(0x0000),
678            protocol_type: U16::new(0x6558),
679            vni_reserved: U32::new(0x00000000),
680        };
681        assert_eq!(header1.flags_string(), "none");
682
683        let header2 = GeneveHeader {
684            ver_optlen_flags: U16::new(0x0080), // O
685            protocol_type: U16::new(0x6558),
686            vni_reserved: U32::new(0x00000000),
687        };
688        assert_eq!(header2.flags_string(), "O");
689
690        let header3 = GeneveHeader {
691            ver_optlen_flags: U16::new(0x00C0), // O + C
692            protocol_type: U16::new(0x6558),
693            vni_reserved: U32::new(0x00000000),
694        };
695        assert_eq!(header3.flags_string(), "OC");
696    }
697
698    #[test]
699    fn test_geneve_port_check() {
700        assert!(is_geneve_port(6081));
701        assert!(!is_geneve_port(4789)); // VXLAN
702        assert!(!is_geneve_port(80));
703    }
704
705    #[test]
706    fn test_geneve_option_parsing() {
707        let option_data = vec![
708            0x00, 0x01, // Option class
709            0x01, // Option type (not critical)
710            0x02, // Length = 2 (8 bytes data)
711            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Data
712        ];
713
714        let mut iter = GeneveOptionsIter {
715            data: &option_data,
716            offset: 0,
717        };
718
719        let opt = iter.next().unwrap();
720        assert_eq!(opt.option_class, 0x0001);
721        assert_eq!(opt.option_type, 0x01);
722        assert!(!opt.is_critical());
723        assert_eq!(opt.type_value(), 0x01);
724        assert_eq!(opt.length_units, 2);
725        assert_eq!(opt.data_length(), 8);
726        assert_eq!(opt.total_length(), 12);
727    }
728
729    #[test]
730    fn test_geneve_multiple_options() {
731        let mut packet = Vec::new();
732
733        // Geneve header with 16 bytes of options
734        packet.extend_from_slice(&0x0400u16.to_be_bytes()); // OptLen=4 (16 bytes)
735        packet.extend_from_slice(&0x6558u16.to_be_bytes());
736        packet.extend_from_slice(&0x00000000u32.to_be_bytes());
737
738        // Option 1: 8 bytes
739        packet.extend_from_slice(&0x0001u16.to_be_bytes());
740        packet.push(0x01);
741        packet.push(0x01); // Len=1 (4 bytes)
742        packet.extend_from_slice(&[0xAA, 0xBB, 0xCC, 0xDD]);
743
744        // Option 2: 8 bytes
745        packet.extend_from_slice(&0x0002u16.to_be_bytes());
746        packet.push(0x82); // Critical
747        packet.push(0x01);
748        packet.extend_from_slice(&[0x11, 0x22, 0x33, 0x44]);
749
750        let (header, _) = GeneveHeader::from_bytes(&packet).unwrap();
751        let opts: Vec<_> = header.options_iter().collect();
752
753        assert_eq!(opts.len(), 2);
754        assert_eq!(opts[0].option_class, 0x0001);
755        assert!(!opts[0].is_critical());
756        assert_eq!(opts[1].option_class, 0x0002);
757        assert!(opts[1].is_critical());
758    }
759
760    #[test]
761    fn test_geneve_max_options_length() {
762        // Max options length is 63 units = 252 bytes
763        let header = GeneveHeader {
764            ver_optlen_flags: U16::new(0x3F00), // OptLen=63
765            protocol_type: U16::new(0x6558),
766            vni_reserved: U32::new(0x00000000),
767        };
768
769        assert_eq!(header.options_length_units(), 63);
770        assert_eq!(header.options_length(), 252);
771        assert!(header.is_valid());
772    }
773
774    #[test]
775    fn test_geneve_header_length_calculation() {
776        // No options
777        let h1 = GeneveHeader {
778            ver_optlen_flags: U16::new(0x0000),
779            protocol_type: U16::new(0x6558),
780            vni_reserved: U32::new(0x00000000),
781        };
782        assert_eq!(h1.header_length(), 8);
783
784        // 8 bytes options
785        let h2 = GeneveHeader {
786            ver_optlen_flags: U16::new(0x0200),
787            protocol_type: U16::new(0x6558),
788            vni_reserved: U32::new(0x00000000),
789        };
790        assert_eq!(h2.header_length(), 16);
791
792        // Max options (252 bytes)
793        let h3 = GeneveHeader {
794            ver_optlen_flags: U16::new(0x3F00),
795            protocol_type: U16::new(0x6558),
796            vni_reserved: U32::new(0x00000000),
797        };
798        assert_eq!(h3.header_length(), 260);
799    }
800
801    #[test]
802    fn test_geneve_reserved_bits() {
803        let header = GeneveHeader {
804            ver_optlen_flags: U16::new(0x003F), // Reserved bits set
805            protocol_type: U16::new(0x6558),
806            vni_reserved: U32::new(0x000000FF), // VNI reserved byte set
807        };
808
809        assert_eq!(header.reserved_flags(), 0x3F);
810        assert_eq!(header.reserved_vni(), 0xFF);
811        assert!(header.is_valid()); // Basic validation passes
812        assert!(!header.is_valid_strict()); // Strict fails
813    }
814}