1use 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
83pub const GENEVE_PORT: u16 = 6081;
85
86pub const GENEVE_MAX_VNI: u32 = 0xFFFFFF;
88
89pub const GENEVE_MAX_OPTIONS_LEN: usize = 252;
91
92pub const GENEVE_VERSION: u8 = 0;
94
95#[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 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 #[inline]
136 pub fn version(&self) -> u8 {
137 ((self.ver_optlen_flags.get() & Self::VERSION_MASK) >> Self::VERSION_SHIFT) as u8
138 }
139
140 #[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 #[inline]
148 pub fn options_length(&self) -> usize {
149 self.options_length_units() as usize * 4
150 }
151
152 #[inline]
156 pub fn is_oam(&self) -> bool {
157 self.ver_optlen_flags.get() & Self::FLAG_O_MASK != 0
158 }
159
160 #[inline]
164 pub fn is_critical(&self) -> bool {
165 self.ver_optlen_flags.get() & Self::FLAG_C_MASK != 0
166 }
167
168 #[inline]
170 pub fn reserved_flags(&self) -> u8 {
171 (self.ver_optlen_flags.get() & Self::RESERVED_MASK) as u8
172 }
173
174 #[inline]
178 pub fn protocol_type(&self) -> EtherProto {
179 self.protocol_type.get().into()
180 }
181
182 #[inline]
184 pub fn protocol_type_raw(&self) -> u16 {
185 self.protocol_type.get()
186 }
187
188 #[inline]
190 pub fn vni(&self) -> u32 {
191 (self.vni_reserved.get() & Self::VNI_MASK) >> Self::VNI_SHIFT
192 }
193
194 #[inline]
196 pub fn reserved_vni(&self) -> u8 {
197 (self.vni_reserved.get() & Self::VNI_RESERVED_MASK) as u8
198 }
199
200 #[inline]
202 pub fn header_length(&self) -> usize {
203 Self::FIXED_LEN + self.options_length()
204 }
205
206 #[inline]
208 fn is_valid(&self) -> bool {
209 if self.version() != GENEVE_VERSION {
211 return false;
212 }
213
214 if self.options_length() > GENEVE_MAX_OPTIONS_LEN {
216 return false;
217 }
218
219 true
220 }
221
222 #[inline]
226 pub fn is_valid_strict(&self) -> bool {
227 self.is_valid() && self.reserved_flags() == 0 && self.reserved_vni() == 0
228 }
229
230 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#[derive(Debug, Clone)]
251pub struct GeneveHeaderOpt<'a> {
252 pub header: &'a GeneveHeader,
253 pub options: &'a [u8],
254}
255
256impl<'a> GeneveHeaderOpt<'a> {
257 pub fn options_iter(&self) -> GeneveOptionsIter<'a> {
259 GeneveOptionsIter {
260 data: self.options,
261 offset: 0,
262 }
263 }
264
265 #[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#[derive(Debug, Clone, Copy)]
357pub struct GeneveOption<'a> {
358 pub option_class: u16,
360 pub option_type: u8,
362 pub length_units: u8,
364 pub data: &'a [u8],
366}
367
368impl<'a> GeneveOption<'a> {
369 pub const HEADER_SIZE: usize = 4;
371
372 #[inline]
374 pub fn is_critical(&self) -> bool {
375 self.option_type & 0x80 != 0
376 }
377
378 #[inline]
380 pub fn type_value(&self) -> u8 {
381 self.option_type & 0x7F
382 }
383
384 #[inline]
386 pub fn data_length(&self) -> usize {
387 self.length_units as usize * 4
388 }
389
390 #[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
410pub 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; 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#[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), protocol_type: U16::new(0x6558), vni_reserved: U32::new(0x00006400), };
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), protocol_type: U16::new(0x6558),
489 vni_reserved: U32::new(0x00010000), };
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); assert_eq!(header.vni(), 256);
497 assert!(header.is_valid());
498 }
499
500 #[test]
501 fn test_geneve_flags() {
502 let header_oam = GeneveHeader {
504 ver_optlen_flags: U16::new(0x0080), 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 let header_crit = GeneveHeader {
513 ver_optlen_flags: U16::new(0x0040), 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 let header_both = GeneveHeader {
522 ver_optlen_flags: U16::new(0x00C0), 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 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 let header = GeneveHeader {
557 ver_optlen_flags: U16::new(0x4000), 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 packet.extend_from_slice(&0x0000u16.to_be_bytes()); packet.extend_from_slice(&0x6558u16.to_be_bytes()); packet.extend_from_slice(&0x00006400u32.to_be_bytes()); 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 packet.extend_from_slice(&0x0200u16.to_be_bytes()); packet.extend_from_slice(&0x6558u16.to_be_bytes()); packet.extend_from_slice(&0x00010000u32.to_be_bytes()); packet.extend_from_slice(&0x0001u16.to_be_bytes()); packet.push(0x80); packet.push(0x01); packet.extend_from_slice(&[0x12, 0x34, 0x56, 0x78]); 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 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]; 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 packet.extend_from_slice(&0x4000u16.to_be_bytes()); 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), 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), 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), 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)); assert!(!is_geneve_port(80));
703 }
704
705 #[test]
706 fn test_geneve_option_parsing() {
707 let option_data = vec![
708 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, ];
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 packet.extend_from_slice(&0x0400u16.to_be_bytes()); packet.extend_from_slice(&0x6558u16.to_be_bytes());
736 packet.extend_from_slice(&0x00000000u32.to_be_bytes());
737
738 packet.extend_from_slice(&0x0001u16.to_be_bytes());
740 packet.push(0x01);
741 packet.push(0x01); packet.extend_from_slice(&[0xAA, 0xBB, 0xCC, 0xDD]);
743
744 packet.extend_from_slice(&0x0002u16.to_be_bytes());
746 packet.push(0x82); 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 let header = GeneveHeader {
764 ver_optlen_flags: U16::new(0x3F00), 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 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 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 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), protocol_type: U16::new(0x6558),
806 vni_reserved: U32::new(0x000000FF), };
808
809 assert_eq!(header.reserved_flags(), 0x3F);
810 assert_eq!(header.reserved_vni(), 0xFF);
811 assert!(header.is_valid()); assert!(!header.is_valid_strict()); }
814}