packet_strata/packet/tunnel/
nvgre.rs1use std::fmt::{self, Formatter};
77
78use zerocopy::byteorder::{BigEndian, U16, U32};
79use zerocopy::{FromBytes, IntoBytes, Unaligned};
80
81use crate::packet::protocol::EtherProto;
82use crate::packet::{HeaderParser, PacketHeader};
83
84pub const NVGRE_PROTOCOL_TEB: u16 = 0x6558;
86
87pub const NVGRE_MAX_VSID: u32 = 0xFFFFFF;
89
90pub const NVGRE_VSID_RESERVED_MIN: u32 = 0xFFFFF0;
92pub const NVGRE_VSID_RESERVED_MAX: u32 = 0xFFFFFF;
93
94#[repr(C, packed)]
110#[derive(
111 FromBytes, IntoBytes, Unaligned, Debug, Clone, Copy, zerocopy::KnownLayout, zerocopy::Immutable,
112)]
113pub struct NvgreHeader {
114 flags_version: U16<BigEndian>,
115 protocol_type: U16<BigEndian>,
116 vsid_flowid: U32<BigEndian>,
117}
118
119impl NvgreHeader {
120 pub const FLAG_CHECKSUM: u16 = 0x8000; pub const FLAG_ROUTING: u16 = 0x4000; pub const FLAG_KEY: u16 = 0x2000; pub const FLAG_SEQUENCE: u16 = 0x1000; pub const FLAG_STRICT_ROUTE: u16 = 0x0800; pub const VERSION_MASK: u16 = 0x0007; pub const RECUR_MASK: u16 = 0x0700; pub const FLAGS_MASK: u16 = 0x00F8; pub const VERSION_NVGRE: u16 = 0x0000; const VSID_MASK: u32 = 0xFFFFFF00;
135 const VSID_SHIFT: u32 = 8;
136 const FLOWID_MASK: u32 = 0x000000FF;
137
138 #[allow(unused)]
139 const NAME: &'static str = "NvgreHeader";
140
141 #[inline]
143 pub fn flags_version(&self) -> u16 {
144 self.flags_version.get()
145 }
146
147 #[inline]
149 pub fn version(&self) -> u8 {
150 (self.flags_version() & Self::VERSION_MASK) as u8
151 }
152
153 #[inline]
155 pub fn protocol_type(&self) -> EtherProto {
156 self.protocol_type.get().into()
157 }
158
159 #[inline]
161 pub fn protocol_type_raw(&self) -> u16 {
162 self.protocol_type.get()
163 }
164
165 #[inline]
170 pub fn vsid(&self) -> u32 {
171 (self.vsid_flowid.get() & Self::VSID_MASK) >> Self::VSID_SHIFT
172 }
173
174 #[inline]
178 pub fn flow_id(&self) -> u8 {
179 (self.vsid_flowid.get() & Self::FLOWID_MASK) as u8
180 }
181
182 #[inline]
184 pub fn key(&self) -> u32 {
185 self.vsid_flowid.get()
186 }
187
188 #[inline]
190 pub fn has_checksum(&self) -> bool {
191 self.flags_version() & Self::FLAG_CHECKSUM != 0
192 }
193
194 #[inline]
196 pub fn has_routing(&self) -> bool {
197 self.flags_version() & Self::FLAG_ROUTING != 0
198 }
199
200 #[inline]
202 pub fn has_key(&self) -> bool {
203 self.flags_version() & Self::FLAG_KEY != 0
204 }
205
206 #[inline]
208 pub fn has_sequence(&self) -> bool {
209 self.flags_version() & Self::FLAG_SEQUENCE != 0
210 }
211
212 #[inline]
214 pub fn has_strict_route(&self) -> bool {
215 self.flags_version() & Self::FLAG_STRICT_ROUTE != 0
216 }
217
218 #[inline]
220 pub fn recursion_control(&self) -> u8 {
221 ((self.flags_version() & Self::RECUR_MASK) >> 8) as u8
222 }
223
224 #[inline]
226 pub fn is_vsid_reserved(&self) -> bool {
227 let vsid = self.vsid();
228 (NVGRE_VSID_RESERVED_MIN..=NVGRE_VSID_RESERVED_MAX).contains(&vsid)
229 }
230
231 #[inline]
241 fn is_valid(&self) -> bool {
242 if self.version() != 0 {
244 return false;
245 }
246
247 if !self.has_key() {
249 return false;
250 }
251
252 if self.has_routing() {
254 return false;
255 }
256
257 if self.has_strict_route() {
259 return false;
260 }
261
262 if self.recursion_control() != 0 {
264 return false;
265 }
266
267 if self.protocol_type_raw() != NVGRE_PROTOCOL_TEB {
269 return false;
270 }
271
272 true
273 }
274
275 #[inline]
281 pub fn is_valid_relaxed(&self) -> bool {
282 self.version() == 0 && self.has_key()
283 }
284
285 pub fn flags_string(&self) -> String {
287 let mut flags = Vec::new();
288
289 if self.has_checksum() {
290 flags.push("C");
291 }
292 if self.has_routing() {
293 flags.push("R");
294 }
295 if self.has_key() {
296 flags.push("K");
297 }
298 if self.has_sequence() {
299 flags.push("S");
300 }
301 if self.has_strict_route() {
302 flags.push("s");
303 }
304
305 if flags.is_empty() {
306 "none".to_string()
307 } else {
308 flags.join("")
309 }
310 }
311}
312
313impl PacketHeader for NvgreHeader {
314 const NAME: &'static str = "NvgreHeader";
315 type InnerType = EtherProto;
316
317 #[inline]
318 fn inner_type(&self) -> Self::InnerType {
319 self.protocol_type()
320 }
321
322 #[inline]
324 fn total_len(&self, _buf: &[u8]) -> usize {
325 Self::FIXED_LEN
326 }
327
328 #[inline]
330 fn is_valid(&self) -> bool {
331 self.is_valid()
332 }
333}
334
335impl HeaderParser for NvgreHeader {
336 type Output<'a> = &'a NvgreHeader;
337
338 #[inline]
339 fn into_view<'a>(header: &'a Self, _raw_options: &'a [u8]) -> Self::Output<'a> {
340 header
341 }
342}
343
344impl fmt::Display for NvgreHeader {
345 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
346 write!(
347 f,
348 "NVGRE vsid={} flow_id={} proto={}(0x{:04x}) flags={}",
349 self.vsid(),
350 self.flow_id(),
351 self.protocol_type(),
352 self.protocol_type().0,
353 self.flags_string()
354 )
355 }
356}
357
358#[cfg(test)]
359mod tests {
360 use super::*;
361
362 #[test]
363 fn test_nvgre_header_size() {
364 assert_eq!(std::mem::size_of::<NvgreHeader>(), 8);
365 assert_eq!(NvgreHeader::FIXED_LEN, 8);
366 }
367
368 #[test]
369 fn test_nvgre_basic_header() {
370 let header = NvgreHeader {
371 flags_version: U16::new(0x2000), protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
373 vsid_flowid: U32::new(0x00010000), };
375
376 assert_eq!(header.version(), 0);
377 assert_eq!(header.protocol_type(), EtherProto::TEB);
378 assert!(header.has_key());
379 assert!(!header.has_checksum());
380 assert!(!header.has_sequence());
381 assert!(header.is_valid());
382 assert_eq!(header.vsid(), 256);
383 assert_eq!(header.flow_id(), 0);
384 }
385
386 #[test]
387 fn test_nvgre_vsid_flowid() {
388 let header = NvgreHeader {
390 flags_version: U16::new(0x2000),
391 protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
392 vsid_flowid: U32::new(0x123456AB),
393 };
394
395 assert_eq!(header.vsid(), 0x123456);
396 assert_eq!(header.flow_id(), 0xAB);
397 assert_eq!(header.key(), 0x123456AB);
398 }
399
400 #[test]
401 fn test_nvgre_max_vsid() {
402 let header = NvgreHeader {
404 flags_version: U16::new(0x2000),
405 protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
406 vsid_flowid: U32::new(0xFFFFFFFF),
407 };
408
409 assert_eq!(header.vsid(), 0xFFFFFF);
410 assert_eq!(header.flow_id(), 0xFF);
411 assert!(header.is_vsid_reserved());
412 }
413
414 #[test]
415 fn test_nvgre_reserved_vsid_range() {
416 let header1 = NvgreHeader {
418 flags_version: U16::new(0x2000),
419 protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
420 vsid_flowid: U32::new(0xFFFFF000),
421 };
422 assert!(header1.is_vsid_reserved());
423
424 let header2 = NvgreHeader {
426 flags_version: U16::new(0x2000),
427 protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
428 vsid_flowid: U32::new(0xFFFFEF00),
429 };
430 assert!(!header2.is_vsid_reserved());
431 }
432
433 #[test]
434 fn test_nvgre_version_validation() {
435 let header = NvgreHeader {
437 flags_version: U16::new(0x2001), protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
439 vsid_flowid: U32::new(0x00010000),
440 };
441 assert!(!header.is_valid());
442 assert!(!header.is_valid_relaxed());
443 }
444
445 #[test]
446 fn test_nvgre_key_flag_required() {
447 let header = NvgreHeader {
449 flags_version: U16::new(0x0000), protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
451 vsid_flowid: U32::new(0x00010000),
452 };
453 assert!(!header.is_valid());
454 assert!(!header.is_valid_relaxed());
455 }
456
457 #[test]
458 fn test_nvgre_routing_forbidden() {
459 let header = NvgreHeader {
461 flags_version: U16::new(0x6000), protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
463 vsid_flowid: U32::new(0x00010000),
464 };
465 assert!(!header.is_valid());
466 assert!(header.is_valid_relaxed());
468 }
469
470 #[test]
471 fn test_nvgre_wrong_protocol_type() {
472 let header = NvgreHeader {
474 flags_version: U16::new(0x2000),
475 protocol_type: U16::new(0x0800), vsid_flowid: U32::new(0x00010000),
477 };
478 assert!(!header.is_valid());
479 assert!(header.is_valid_relaxed());
481 }
482
483 #[test]
484 fn test_nvgre_with_checksum_flag() {
485 let header = NvgreHeader {
487 flags_version: U16::new(0xA000), protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
489 vsid_flowid: U32::new(0x00010000),
490 };
491 assert!(header.has_checksum());
492 assert!(header.is_valid());
494 }
495
496 #[test]
497 fn test_nvgre_with_sequence_flag() {
498 let header = NvgreHeader {
500 flags_version: U16::new(0x3000), protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
502 vsid_flowid: U32::new(0x00010000),
503 };
504 assert!(header.has_sequence());
505 assert!(header.is_valid());
507 }
508
509 #[test]
510 fn test_nvgre_parsing_basic() {
511 let mut packet = Vec::new();
512
513 packet.extend_from_slice(&0x2000u16.to_be_bytes()); packet.extend_from_slice(&NVGRE_PROTOCOL_TEB.to_be_bytes()); packet.extend_from_slice(&0x00010001u32.to_be_bytes()); packet.extend_from_slice(b"payload");
520
521 let result = NvgreHeader::from_bytes(&packet);
522 assert!(result.is_ok());
523
524 let (header, payload) = result.unwrap();
525 assert_eq!(header.version(), 0);
526 assert_eq!(header.protocol_type(), EtherProto::TEB);
527 assert_eq!(header.vsid(), 256);
528 assert_eq!(header.flow_id(), 1);
529 assert_eq!(payload, b"payload");
530 }
531
532 #[test]
533 fn test_nvgre_parsing_with_vsid() {
534 let mut packet = Vec::new();
535
536 packet.extend_from_slice(&0x2000u16.to_be_bytes()); packet.extend_from_slice(&NVGRE_PROTOCOL_TEB.to_be_bytes()); packet.extend_from_slice(&0x12345600u32.to_be_bytes()); let result = NvgreHeader::from_bytes(&packet);
541 assert!(result.is_ok());
542
543 let (header, _) = result.unwrap();
544 assert_eq!(header.vsid(), 0x123456);
545 assert_eq!(header.flow_id(), 0);
546 }
547
548 #[test]
549 fn test_nvgre_parsing_too_small() {
550 let packet = vec![0u8; 7]; let result = NvgreHeader::from_bytes(&packet);
553 assert!(result.is_err());
554 }
555
556 #[test]
557 fn test_nvgre_parsing_invalid_version() {
558 let mut packet = Vec::new();
559
560 packet.extend_from_slice(&0x2001u16.to_be_bytes()); packet.extend_from_slice(&NVGRE_PROTOCOL_TEB.to_be_bytes());
563 packet.extend_from_slice(&0x00010000u32.to_be_bytes());
564
565 let result = NvgreHeader::from_bytes(&packet);
566 assert!(result.is_err());
567 }
568
569 #[test]
570 fn test_nvgre_parsing_missing_key() {
571 let mut packet = Vec::new();
572
573 packet.extend_from_slice(&0x0000u16.to_be_bytes()); packet.extend_from_slice(&NVGRE_PROTOCOL_TEB.to_be_bytes());
576 packet.extend_from_slice(&0x00010000u32.to_be_bytes());
577
578 let result = NvgreHeader::from_bytes(&packet);
579 assert!(result.is_err());
580 }
581
582 #[test]
583 fn test_nvgre_flags_string() {
584 let header1 = NvgreHeader {
585 flags_version: U16::new(0x2000), protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
587 vsid_flowid: U32::new(0x00010000),
588 };
589 assert_eq!(header1.flags_string(), "K");
590
591 let header2 = NvgreHeader {
592 flags_version: U16::new(0xA000), protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
594 vsid_flowid: U32::new(0x00010000),
595 };
596 assert_eq!(header2.flags_string(), "CK");
597
598 let header3 = NvgreHeader {
599 flags_version: U16::new(0x3000), protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
601 vsid_flowid: U32::new(0x00010000),
602 };
603 assert_eq!(header3.flags_string(), "KS");
604 }
605
606 #[test]
607 fn test_nvgre_display() {
608 let header = NvgreHeader {
609 flags_version: U16::new(0x2000),
610 protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
611 vsid_flowid: U32::new(0x00010001),
612 };
613
614 let display = format!("{}", header);
615 assert!(display.contains("NVGRE"));
616 assert!(display.contains("vsid=256"));
617 assert!(display.contains("flow_id=1"));
618 }
619
620 #[test]
621 fn test_nvgre_zero_vsid() {
622 let header = NvgreHeader {
623 flags_version: U16::new(0x2000),
624 protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
625 vsid_flowid: U32::new(0x00000000), };
627
628 assert_eq!(header.vsid(), 0);
629 assert_eq!(header.flow_id(), 0);
630 assert!(header.is_valid());
631 assert!(!header.is_vsid_reserved());
632 }
633
634 #[test]
635 fn test_nvgre_inner_type() {
636 let header = NvgreHeader {
637 flags_version: U16::new(0x2000),
638 protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
639 vsid_flowid: U32::new(0x00010000),
640 };
641
642 assert_eq!(header.inner_type(), EtherProto::TEB);
644 }
645
646 #[test]
647 fn test_nvgre_multicast_vsid() {
648 let header = NvgreHeader {
650 flags_version: U16::new(0x2000),
651 protocol_type: U16::new(NVGRE_PROTOCOL_TEB),
652 vsid_flowid: U32::new(0x00ABCD00), };
654
655 assert_eq!(header.vsid(), 0x00ABCD);
656 assert!(!header.is_vsid_reserved());
657 }
658}