1use serde::{Deserialize, Serialize};
38use smallvec::SmallVec;
39use std::collections::BTreeMap;
40use std::fmt;
41use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
42
43use crate::packet::ether::EtherHeaderVlan;
44use crate::packet::header::{LinkLayer, NetworkLayer, NetworkTunnelLayer, TunnelLayer};
45use crate::packet::Packet;
46
47#[derive(Debug, Clone, PartialEq, Eq)]
49pub enum VniError {
50 InvalidHeaderLength,
52 InvalidIpVersion,
54}
55
56impl fmt::Display for VniError {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 match self {
59 Self::InvalidHeaderLength => write!(f, "Invalid IP header length"),
60 Self::InvalidIpVersion => write!(f, "Invalid IP version"),
61 }
62 }
63}
64
65impl std::error::Error for VniError {}
66
67#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
72pub enum VniLayer {
73 Vlan { vid: u16 },
77
78 Mpls { label: u32 },
82
83 Gre {
87 protocol_type: u16,
88 key: Option<u32>,
89 endpoints: [IpAddr; 2],
90 },
91
92 NvGre {
96 protocol_type: u16,
97 vsid_flowid: u32,
98 endpoints: [IpAddr; 2],
99 },
100
101 Vxlan {
105 vni: u32,
106 group_id: u16,
107 endpoints: [IpAddr; 2],
108 },
109
110 Geneve {
114 vni: u32,
115 protocol_type: u16,
116 endpoints: [IpAddr; 2],
117 },
118
119 Ipip { endpoints: [IpAddr; 2] },
123
124 Ip4in6 { endpoints: [IpAddr; 2] },
128
129 Sit { endpoints: [IpAddr; 2] },
133
134 Ip6Tnl { endpoints: [IpAddr; 2] },
138
139 GtpU { teid: u32, endpoints: [IpAddr; 2] },
144
145 Teredo { endpoints: [IpAddr; 2] },
149
150 L2tpV2 {
154 tunnel_id: u16,
155 session_id: u16,
156 endpoints: [IpAddr; 2],
157 },
158
159 L2tpV3 {
163 session_id: u32,
164 endpoints: [IpAddr; 2],
165 },
166
167 Pbb { isid: u32, bvid: Option<u16> },
171
172 Stt {
176 context_id: u64,
177 endpoints: [IpAddr; 2],
178 },
179
180 Pptp {
184 call_id: u16,
185 endpoints: [IpAddr; 2],
186 },
187}
188
189impl fmt::Display for VniLayer {
190 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191 match self {
192 Self::Vlan { vid } => write!(f, "vlan({})", vid),
193 Self::Mpls { label } => write!(f, "mpls({})", label),
194 Self::Gre {
195 protocol_type,
196 key,
197 endpoints,
198 } => {
199 write!(f, "gre(ptype:0x{:04x}", protocol_type)?;
200 if let Some(k) = key {
201 write!(f, " key:{}", k)?;
202 }
203 write!(f, " {}↔{})", endpoints[0], endpoints[1])
204 }
205 Self::NvGre {
206 protocol_type,
207 vsid_flowid,
208 endpoints,
209 } => {
210 write!(
211 f,
212 "nvgre(ptype:0x{:04x} vsid:{} {}↔{})",
213 protocol_type, vsid_flowid, endpoints[0], endpoints[1]
214 )
215 }
216 Self::Vxlan {
217 vni,
218 group_id,
219 endpoints,
220 } => {
221 write!(f, "vxlan(vni:{}", vni)?;
222 if *group_id != 0 {
223 write!(f, " gid:{}", group_id)?;
224 }
225 write!(f, " {}↔{})", endpoints[0], endpoints[1])
226 }
227 Self::Geneve {
228 vni,
229 protocol_type,
230 endpoints,
231 } => {
232 write!(
233 f,
234 "geneve(vni:{} ptype:0x{:04x} {}↔{})",
235 vni, protocol_type, endpoints[0], endpoints[1]
236 )
237 }
238 Self::Ipip { endpoints } => {
239 write!(f, "ipip({}↔{})", endpoints[0], endpoints[1])
240 }
241 Self::Ip4in6 { endpoints } => {
242 write!(f, "ip4in6({}↔{})", endpoints[0], endpoints[1])
243 }
244 Self::Sit { endpoints } => {
245 write!(f, "sit({}↔{})", endpoints[0], endpoints[1])
246 }
247 Self::Ip6Tnl { endpoints } => {
248 write!(f, "ip6tnl({}↔{})", endpoints[0], endpoints[1])
249 }
250 Self::GtpU { teid, endpoints } => {
251 write!(
252 f,
253 "gtp-u(teid:0x{:08x} {}↔{})",
254 teid, endpoints[0], endpoints[1]
255 )
256 }
257 Self::Teredo { endpoints } => {
258 write!(f, "teredo({}↔{})", endpoints[0], endpoints[1])
259 }
260 Self::L2tpV2 {
261 tunnel_id,
262 session_id,
263 endpoints,
264 } => {
265 write!(
266 f,
267 "l2tpv2(tid:{} sid:{} {}↔{})",
268 tunnel_id, session_id, endpoints[0], endpoints[1]
269 )
270 }
271 Self::L2tpV3 {
272 session_id,
273 endpoints,
274 } => {
275 write!(
276 f,
277 "l2tpv3(sid:{} {}↔{})",
278 session_id, endpoints[0], endpoints[1]
279 )
280 }
281 Self::Pbb { isid, bvid } => {
282 write!(f, "pbb(isid:{}", isid)?;
283 if let Some(b) = bvid {
284 write!(f, " bvid:{}", b)?;
285 }
286 write!(f, ")")
287 }
288 Self::Stt {
289 context_id,
290 endpoints,
291 } => {
292 write!(
293 f,
294 "stt(ctx:0x{:016x} {}↔{})",
295 context_id, endpoints[0], endpoints[1]
296 )
297 }
298 Self::Pptp { call_id, endpoints } => {
299 write!(
300 f,
301 "pptp(call:{} {}↔{})",
302 call_id, endpoints[0], endpoints[1]
303 )
304 }
305 }
306 }
307}
308
309impl From<&LinkLayer<'_>> for SmallVec<[VniLayer; 2]> {
310 fn from(value: &LinkLayer<'_>) -> Self {
311 match value {
312 LinkLayer::Ethernet(EtherHeaderVlan::VLAN8021Q(_, eth8021q)) => {
313 let mut sv = SmallVec::<[VniLayer; 2]>::new();
314 sv.push(VniLayer::Vlan {
315 vid: eth8021q.vlan_id(),
316 });
317 sv
318 }
319 LinkLayer::Ethernet(EtherHeaderVlan::VLAN8021QNested(_, eth8021q, eth8021q_n)) => {
320 let mut sv = SmallVec::<[VniLayer; 2]>::new();
321 sv.push(VniLayer::Vlan {
322 vid: eth8021q.vlan_id(),
323 });
324 sv.push(VniLayer::Vlan {
325 vid: eth8021q_n.vlan_id(),
326 });
327 sv
328 }
329 _ => SmallVec::<[VniLayer; 2]>::new(),
330 }
331 }
332}
333
334impl TryFrom<&NetworkTunnelLayer<'_>> for VniLayer {
335 type Error = ();
336 fn try_from(ip_tunnel: &NetworkTunnelLayer<'_>) -> Result<Self, Self::Error> {
337 let endpoints: Option<[IpAddr; 2]> = ip_tunnel.outer().and_then(|outer| {
339 match outer {
340 NetworkLayer::Ipv4(ipv4) => Some([ipv4.src_ip().into(), ipv4.dst_ip().into()]),
341 NetworkLayer::Ipv6(ipv6) => Some([ipv6.src_ip().into(), ipv6.dst_ip().into()]),
342 NetworkLayer::Mpls(_) => None, }
344 });
345
346 match ip_tunnel.tunnel() {
348 TunnelLayer::Vxlan(vxlan) => endpoints.ok_or(()).map(|endpoints| VniLayer::Vxlan {
349 vni: vxlan.vni(),
350 group_id: 0,
351 endpoints,
352 }),
353 TunnelLayer::Geneve(geneve) => endpoints.ok_or(()).map(|endpoints| VniLayer::Geneve {
354 vni: geneve.header.vni(),
355 protocol_type: geneve.header.protocol_type_raw(),
356 endpoints,
357 }),
358 TunnelLayer::Gre(gre) => endpoints.ok_or(()).map(|endpoints| VniLayer::Gre {
359 protocol_type: gre.header.protocol_type().into(),
360 key: gre.key(),
361 endpoints,
362 }),
363 TunnelLayer::Teredo(_teredo) => endpoints
364 .ok_or(())
365 .map(|endpoints| VniLayer::Teredo { endpoints }),
366 TunnelLayer::Gtpv1(gtp) => endpoints.ok_or(()).map(|endpoints| VniLayer::GtpU {
367 teid: gtp.header.teid(),
368 endpoints,
369 }),
370 TunnelLayer::Gtpv2(_gtp) => {
371 Err(())
373 }
374 TunnelLayer::L2tpv2(l2tp) => endpoints.ok_or(()).map(|endpoints| VniLayer::L2tpV2 {
375 tunnel_id: l2tp.tunnel_id(),
376 session_id: l2tp.session_id(),
377 endpoints,
378 }),
379 TunnelLayer::L2tpv3(l2tp) => endpoints.ok_or(()).map(|endpoints| VniLayer::L2tpV3 {
380 session_id: l2tp.session_id(),
381 endpoints,
382 }),
383 TunnelLayer::Nvgre(nvgre) => endpoints.ok_or(()).map(|endpoints| VniLayer::NvGre {
384 protocol_type: nvgre.protocol_type_raw(),
385 vsid_flowid: nvgre.vsid() << 8 | nvgre.flow_id() as u32,
386 endpoints,
387 }),
388 TunnelLayer::Pbb(pbb) => {
389 Ok(VniLayer::Pbb {
391 isid: pbb.isid(),
392 bvid: pbb.bvid(),
393 })
394 }
395 TunnelLayer::Stt(stt) => endpoints.ok_or(()).map(|endpoints| VniLayer::Stt {
396 context_id: stt.context_id(),
397 endpoints,
398 }),
399 TunnelLayer::Pptp(pptp) => endpoints.ok_or(()).map(|endpoints| VniLayer::Pptp {
400 call_id: pptp.header.call_id(),
401 endpoints,
402 }),
403 TunnelLayer::Ipip(ipip) => {
404 match ipip.outer_header() {
406 crate::packet::tunnel::ipip::OuterIpHeader::V4(ipv4) => {
407 let src = ipv4.header.src_ip_raw();
408 let dst = ipv4.header.dst_ip_raw();
409 let mut endpoints = [
410 IpAddr::V4(Ipv4Addr::from(src)),
411 IpAddr::V4(Ipv4Addr::from(dst)),
412 ];
413 endpoints.sort();
414
415 match ipip.tunnel_type() {
416 crate::packet::tunnel::ipip::IpipType::Ipip => {
417 Ok(VniLayer::Ipip { endpoints })
418 }
419 crate::packet::tunnel::ipip::IpipType::Sit => {
420 Ok(VniLayer::Sit { endpoints })
421 }
422 _ => Err(()),
423 }
424 }
425 crate::packet::tunnel::ipip::OuterIpHeader::V6(ipv6) => {
426 let src = ipv6.header.src_ip_raw();
427 let dst = ipv6.header.dst_ip_raw();
428 let mut endpoints = [
429 IpAddr::V6(Ipv6Addr::from(dst)),
430 IpAddr::V6(Ipv6Addr::from(src)),
431 ];
432 endpoints.sort();
433
434 match ipip.tunnel_type() {
435 crate::packet::tunnel::ipip::IpipType::Ip4in6 => {
436 Ok(VniLayer::Ip4in6 { endpoints })
437 }
438 crate::packet::tunnel::ipip::IpipType::Ip6Tnl => {
439 Ok(VniLayer::Ip6Tnl { endpoints })
440 }
441 _ => Err(()),
442 }
443 }
444 }
445 }
446 }
447 }
448}
449
450impl TryFrom<&Packet<'_>> for SmallVec<[VniLayer; 4]> {
459 type Error = ();
460
461 fn try_from(packet: &Packet<'_>) -> Result<Self, Self::Error> {
462 let mut vni_stack: SmallVec<[VniLayer; 4]> = SmallVec::new();
463
464 match packet.link() {
467 LinkLayer::Ethernet(EtherHeaderVlan::VLAN8021Q(_, eth8021q)) => {
468 vni_stack.push(VniLayer::Vlan {
469 vid: eth8021q.vlan_id(),
470 });
471 }
472 LinkLayer::Ethernet(EtherHeaderVlan::VLAN8021QNested(_, eth8021q, eth8021q_n)) => {
473 vni_stack.push(VniLayer::Vlan {
474 vid: eth8021q.vlan_id(),
475 });
476 vni_stack.push(VniLayer::Vlan {
477 vid: eth8021q_n.vlan_id(),
478 });
479 }
480 _ => {
481 }
483 }
484
485 for network_tunnel in packet.tunnels() {
487 match VniLayer::try_from(network_tunnel) {
489 Ok(vni_layer) => vni_stack.push(vni_layer),
490 Err(_) => {
491 continue;
493 }
494 }
495 }
496
497 Ok(vni_stack)
498 }
499}
500
501#[derive(
506 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
507)]
508pub struct VniId(u32);
509
510impl VniId {
511 #[inline]
513 pub const fn as_u32(&self) -> u32 {
514 self.0
515 }
516
517 #[inline]
519 pub const fn from_u32(value: u32) -> Self {
520 Self(value)
521 }
522}
523
524impl fmt::Display for VniId {
525 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
526 write!(f, "VniId({})", self.0)
527 }
528}
529
530pub struct VniMapper {
588 forward: BTreeMap<SmallVec<[VniLayer; 4]>, VniId>,
590 reverse: BTreeMap<VniId, SmallVec<[VniLayer; 4]>>,
592 counter: u32,
594}
595
596impl VniMapper {
597 pub fn new() -> Self {
599 Self {
600 forward: BTreeMap::new(),
601 reverse: BTreeMap::new(),
602 counter: 0,
603 }
604 }
605
606 pub fn get_or_create_vni_id(&mut self, vni_stack: &[VniLayer]) -> VniId {
619 let stack_vec: SmallVec<[VniLayer; 4]> = vni_stack.iter().cloned().collect();
620
621 if let Some(&id) = self.forward.get(&stack_vec) {
622 return id;
623 }
624
625 self.counter += 1;
626 let id = VniId(self.counter);
627
628 self.forward.insert(stack_vec.clone(), id);
629 self.reverse.insert(id, stack_vec);
630
631 id
632 }
633
634 pub fn lookup_vni(&self, id: VniId) -> Option<&[VniLayer]> {
644 self.reverse.get(&id).map(|v| v.as_slice())
645 }
646
647 pub fn len(&self) -> usize {
649 self.reverse.len()
650 }
651
652 pub fn is_empty(&self) -> bool {
654 self.reverse.is_empty()
655 }
656
657 pub fn clear(&mut self) {
659 self.forward.clear();
660 self.reverse.clear();
661 self.counter = 0;
662 }
663
664 pub fn iter(&self) -> impl Iterator<Item = (VniId, &[VniLayer])> {
666 self.reverse
667 .iter()
668 .map(|(&id, stack)| (id, stack.as_slice()))
669 }
670}
671
672impl Default for VniMapper {
673 fn default() -> Self {
674 Self::new()
675 }
676}
677
678#[cfg(test)]
679mod tests {
680 use super::*;
681 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
682
683 #[test]
688 fn test_vni_error_display() {
689 let err1 = VniError::InvalidHeaderLength;
690 assert_eq!(err1.to_string(), "Invalid IP header length");
691
692 let err2 = VniError::InvalidIpVersion;
693 assert_eq!(err2.to_string(), "Invalid IP version");
694 }
695
696 #[test]
697 fn test_vni_error_clone_eq() {
698 let err1 = VniError::InvalidHeaderLength;
699 let err2 = err1.clone();
700 assert_eq!(err1, err2);
701
702 let err3 = VniError::InvalidIpVersion;
703 assert_ne!(err1, err3);
704 }
705
706 #[test]
715 fn test_vni_layer_equality() {
716 let vlan1 = VniLayer::Vlan { vid: 100 };
717 let vlan2 = VniLayer::Vlan { vid: 100 };
718 let vlan3 = VniLayer::Vlan { vid: 200 };
719
720 assert_eq!(vlan1, vlan2);
721 assert_ne!(vlan1, vlan3);
722
723 let mpls1 = VniLayer::Mpls { label: 100 };
724 assert_ne!(vlan1, mpls1); }
726
727 #[test]
728 fn test_vni_layer_ordering() {
729 let vlan1 = VniLayer::Vlan { vid: 100 };
730 let vlan2 = VniLayer::Vlan { vid: 200 };
731 let _mpls = VniLayer::Mpls { label: 100 };
732
733 assert!(vlan1 < vlan2);
734 }
736
737 #[test]
738 fn test_vni_layer_clone_hash() {
739 let endpoints = [
740 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
741 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
742 ];
743
744 let vxlan1 = VniLayer::Vxlan {
745 vni: 100,
746 group_id: 0,
747 endpoints,
748 };
749 let vxlan2 = vxlan1.clone();
750
751 assert_eq!(vxlan1, vxlan2);
752
753 use std::collections::HashSet;
755 let mut set = HashSet::new();
756 set.insert(vxlan1.clone());
757 assert!(set.contains(&vxlan2));
758 }
759
760 #[test]
765 fn test_vni_id_creation() {
766 let id = VniId::from_u32(42);
767 assert_eq!(id.as_u32(), 42);
768 }
769
770 #[test]
771 fn test_vni_id_display() {
772 let id = VniId::from_u32(100);
773 assert_eq!(format!("{}", id), "VniId(100)");
774 }
775
776 #[test]
777 fn test_vni_id_equality() {
778 let id1 = VniId::from_u32(42);
779 let id2 = VniId::from_u32(42);
780 let id3 = VniId::from_u32(43);
781
782 assert_eq!(id1, id2);
783 assert_ne!(id1, id3);
784 }
785
786 #[test]
791 fn test_vni_mapper_new() {
792 let mapper = VniMapper::new();
793 assert_eq!(mapper.len(), 0);
794 assert!(mapper.is_empty());
795 }
796
797 #[test]
798 fn test_vni_mapper_default() {
799 let mapper = VniMapper::default();
800 assert_eq!(mapper.len(), 0);
801 assert!(mapper.is_empty());
802 }
803
804 #[test]
805 fn test_vni_mapper_single_layer() {
806 let mut mapper = VniMapper::new();
807 let vlan = VniLayer::Vlan { vid: 100 };
808
809 let id = mapper.get_or_create_vni_id(std::slice::from_ref(&vlan));
810 assert_eq!(mapper.len(), 1);
811 assert!(!mapper.is_empty());
812
813 let id2 = mapper.get_or_create_vni_id(std::slice::from_ref(&vlan));
815 assert_eq!(id, id2);
816 assert_eq!(mapper.len(), 1); let stack = mapper.lookup_vni(id).unwrap();
820 assert_eq!(stack.len(), 1);
821 assert_eq!(stack[0], vlan);
822 }
823
824 #[test]
825 fn test_vni_mapper_multi_layer() {
826 let mut mapper = VniMapper::new();
827 let vlan1 = VniLayer::Vlan { vid: 100 };
828 let vlan2 = VniLayer::Vlan { vid: 200 };
829
830 let id = mapper.get_or_create_vni_id(&[vlan1.clone(), vlan2.clone()]);
831 assert_eq!(mapper.len(), 1);
832
833 let stack = mapper.lookup_vni(id).unwrap();
834 assert_eq!(stack.len(), 2);
835 assert_eq!(stack[0], vlan1);
836 assert_eq!(stack[1], vlan2);
837 }
838
839 #[test]
840 fn test_vni_mapper_different_stacks() {
841 let mut mapper = VniMapper::new();
842 let vlan100 = VniLayer::Vlan { vid: 100 };
843 let vlan200 = VniLayer::Vlan { vid: 200 };
844 let mpls = VniLayer::Mpls { label: 1000 };
845
846 let id1 = mapper.get_or_create_vni_id(std::slice::from_ref(&vlan100));
847 let id2 = mapper.get_or_create_vni_id(std::slice::from_ref(&vlan200));
848 let id3 = mapper.get_or_create_vni_id(&[vlan100.clone(), mpls.clone()]);
849
850 assert_ne!(id1, id2);
851 assert_ne!(id1, id3);
852 assert_ne!(id2, id3);
853 assert_eq!(mapper.len(), 3);
854 }
855
856 #[test]
857 fn test_vni_mapper_order_matters() {
858 let mut mapper = VniMapper::new();
859 let vlan = VniLayer::Vlan { vid: 100 };
860 let mpls = VniLayer::Mpls { label: 1000 };
861
862 let id1 = mapper.get_or_create_vni_id(&[vlan.clone(), mpls.clone()]);
863 let id2 = mapper.get_or_create_vni_id(&[mpls.clone(), vlan.clone()]);
864
865 assert_ne!(id1, id2);
867 assert_eq!(mapper.len(), 2);
868 }
869
870 #[test]
871 fn test_vni_mapper_lookup_nonexistent() {
872 let mapper = VniMapper::new();
873 let id = VniId::from_u32(999);
874
875 assert!(mapper.lookup_vni(id).is_none());
876 }
877
878 #[test]
879 fn test_vni_mapper_clear() {
880 let mut mapper = VniMapper::new();
881 let vlan = VniLayer::Vlan { vid: 100 };
882
883 let id1 = mapper.get_or_create_vni_id(std::slice::from_ref(&vlan));
884 assert_eq!(mapper.len(), 1);
885
886 mapper.clear();
887 assert_eq!(mapper.len(), 0);
888 assert!(mapper.is_empty());
889
890 assert!(mapper.lookup_vni(id1).is_none());
892
893 let id2 = mapper.get_or_create_vni_id(&[vlan]);
895 assert_eq!(id2.as_u32(), 1);
896 }
897
898 #[test]
899 fn test_vni_mapper_iter() {
900 let mut mapper = VniMapper::new();
901 let vlan1 = VniLayer::Vlan { vid: 100 };
902 let vlan2 = VniLayer::Vlan { vid: 200 };
903 let mpls = VniLayer::Mpls { label: 1000 };
904
905 mapper.get_or_create_vni_id(std::slice::from_ref(&vlan1));
906 mapper.get_or_create_vni_id(std::slice::from_ref(&vlan2));
907 mapper.get_or_create_vni_id(std::slice::from_ref(&mpls));
908
909 let entries: Vec<_> = mapper.iter().collect();
910 assert_eq!(entries.len(), 3);
911
912 let stacks: Vec<_> = entries.iter().map(|(_, stack)| stack).collect();
914 assert!(stacks.iter().any(|s| s.len() == 1 && s[0] == vlan1));
915 assert!(stacks.iter().any(|s| s.len() == 1 && s[0] == vlan2));
916 assert!(stacks.iter().any(|s| s.len() == 1 && s[0] == mpls));
917 }
918
919 #[test]
920 fn test_vni_mapper_counter_increment() {
921 let mut mapper = VniMapper::new();
922 let vlan1 = VniLayer::Vlan { vid: 100 };
923 let vlan2 = VniLayer::Vlan { vid: 200 };
924 let vlan3 = VniLayer::Vlan { vid: 300 };
925
926 let id1 = mapper.get_or_create_vni_id(&[vlan1]);
927 let id2 = mapper.get_or_create_vni_id(&[vlan2]);
928 let id3 = mapper.get_or_create_vni_id(&[vlan3]);
929
930 assert_eq!(id1.as_u32(), 1);
931 assert_eq!(id2.as_u32(), 2);
932 assert_eq!(id3.as_u32(), 3);
933 }
934
935 #[test]
940 fn test_complex_tunnel_stack() {
941 let mut mapper = VniMapper::new();
942 let endpoints = [
943 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
944 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
945 ];
946
947 let outer_vlan = VniLayer::Vlan { vid: 100 };
949 let vxlan = VniLayer::Vxlan {
950 vni: 5000,
951 group_id: 0,
952 endpoints,
953 };
954 let inner_vlan = VniLayer::Vlan { vid: 200 };
955
956 let id =
957 mapper.get_or_create_vni_id(&[outer_vlan.clone(), vxlan.clone(), inner_vlan.clone()]);
958
959 let stack = mapper.lookup_vni(id).unwrap();
960 assert_eq!(stack.len(), 3);
961 assert_eq!(stack[0], outer_vlan);
962 assert_eq!(stack[1], vxlan);
963 assert_eq!(stack[2], inner_vlan);
964 }
965
966 #[test]
967 fn test_multiple_tunnel_types() {
968 let mut mapper = VniMapper::new();
969 let endpoints_v4 = [
970 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)),
971 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 2)),
972 ];
973 let endpoints_v6 = [
974 IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)),
975 IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2)),
976 ];
977
978 let vxlan = VniLayer::Vxlan {
979 vni: 100,
980 group_id: 0,
981 endpoints: endpoints_v4,
982 };
983 let geneve = VniLayer::Geneve {
984 vni: 200,
985 protocol_type: 0x6558,
986 endpoints: endpoints_v6,
987 };
988 let gre = VniLayer::Gre {
989 protocol_type: 0x0800,
990 key: Some(300),
991 endpoints: endpoints_v4,
992 };
993
994 let id1 = mapper.get_or_create_vni_id(&[vxlan]);
995 let id2 = mapper.get_or_create_vni_id(&[geneve]);
996 let id3 = mapper.get_or_create_vni_id(&[gre]);
997
998 assert_eq!(mapper.len(), 3);
999 assert_ne!(id1, id2);
1000 assert_ne!(id2, id3);
1001 assert_ne!(id1, id3);
1002 }
1003
1004 #[test]
1005 fn test_empty_stack() {
1006 let mut mapper = VniMapper::new();
1007 let id = mapper.get_or_create_vni_id(&[]);
1008
1009 assert_eq!(mapper.len(), 1);
1010 let stack = mapper.lookup_vni(id).unwrap();
1011 assert_eq!(stack.len(), 0);
1012 }
1013
1014 #[test]
1015 fn test_vni_mapper_reuse_after_partial_clear() {
1016 let mut mapper = VniMapper::new();
1017 let vlan = VniLayer::Vlan { vid: 100 };
1018
1019 let id1 = mapper.get_or_create_vni_id(std::slice::from_ref(&vlan));
1020 assert_eq!(id1.as_u32(), 1);
1021
1022 mapper.clear();
1023
1024 let id2 = mapper.get_or_create_vni_id(&[vlan]);
1025 assert_eq!(id2.as_u32(), 1); }
1027
1028 #[test]
1033 fn test_max_vlan_id() {
1034 let vlan = VniLayer::Vlan { vid: 4095 }; assert_eq!(format!("{}", vlan), "vlan(4095)");
1036 }
1037
1038 #[test]
1039 fn test_max_mpls_label() {
1040 let mpls = VniLayer::Mpls { label: 0xFFFFF }; assert_eq!(format!("{}", mpls), "mpls(1048575)");
1042 }
1043
1044 #[test]
1045 fn test_vxlan_24bit_vni() {
1046 let endpoints = [
1047 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
1048 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
1049 ];
1050
1051 let vxlan = VniLayer::Vxlan {
1052 vni: 0xFFFFFF, group_id: 0,
1054 endpoints,
1055 };
1056 assert!(format!("{}", vxlan).contains("vni:16777215"));
1057 }
1058
1059 #[test]
1060 fn test_mixed_ipv4_ipv6_endpoints() {
1061 let endpoints1 = [
1063 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
1064 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
1065 ];
1066 let endpoints2 = [
1067 IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)),
1068 IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2)),
1069 ];
1070
1071 let ipip_v4 = VniLayer::Ipip {
1072 endpoints: endpoints1,
1073 };
1074 let ipip_v6 = VniLayer::Ip6Tnl {
1075 endpoints: endpoints2,
1076 };
1077
1078 assert_ne!(ipip_v4, ipip_v6);
1079 }
1080
1081 #[test]
1082 fn test_vni_layer_size() {
1083 use std::mem::size_of;
1085
1086 let size = size_of::<VniLayer>();
1088
1089 assert!(
1092 size <= 128,
1093 "VniLayer size is {}, expected <= 128 bytes",
1094 size
1095 );
1096 }
1097
1098 #[test]
1099 fn test_smallvec_inline_capacity() {
1100 let vlan1 = VniLayer::Vlan { vid: 100 };
1102 let vlan2 = VniLayer::Vlan { vid: 200 };
1103
1104 let mut sv = SmallVec::<[VniLayer; 4]>::new();
1105 sv.push(vlan1);
1106 sv.push(vlan2);
1107
1108 assert!(!sv.spilled());
1110 }
1111
1112 #[test]
1113 fn test_btreemap_ordering() {
1114 let mut mapper = VniMapper::new();
1115
1116 let vlan200 = VniLayer::Vlan { vid: 200 };
1118 let vlan100 = VniLayer::Vlan { vid: 100 };
1119 let vlan300 = VniLayer::Vlan { vid: 300 };
1120
1121 mapper.get_or_create_vni_id(&[vlan200]);
1122 mapper.get_or_create_vni_id(&[vlan100]);
1123 mapper.get_or_create_vni_id(&[vlan300]);
1124
1125 let entries: Vec<_> = mapper.iter().collect();
1127 assert_eq!(entries.len(), 3);
1128 }
1129
1130 #[test]
1144 fn test_vni_layer_debug_format() {
1145 let vlan = VniLayer::Vlan { vid: 100 };
1147 let debug_str = format!("{:?}", vlan);
1148 assert!(debug_str.contains("Vlan"));
1149 assert!(debug_str.contains("100"));
1150 }
1151
1152 #[test]
1153 fn test_multiple_identical_stacks() {
1154 let mut mapper = VniMapper::new();
1155 let endpoints = [
1156 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
1157 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
1158 ];
1159
1160 let vxlan1 = VniLayer::Vxlan {
1161 vni: 100,
1162 group_id: 0,
1163 endpoints,
1164 };
1165 let vxlan2 = VniLayer::Vxlan {
1166 vni: 100,
1167 group_id: 0,
1168 endpoints,
1169 };
1170
1171 let id1 = mapper.get_or_create_vni_id(&[vxlan1]);
1172 let id2 = mapper.get_or_create_vni_id(&[vxlan2]);
1173
1174 assert_eq!(id1, id2);
1176 assert_eq!(mapper.len(), 1);
1177 }
1178
1179 #[test]
1180 fn test_endpoint_ordering_consistency() {
1181 let endpoints1 = [
1182 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
1183 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
1184 ];
1185 let endpoints2 = [
1186 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
1187 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
1188 ];
1189
1190 let ipip1 = VniLayer::Ipip {
1191 endpoints: endpoints1,
1192 };
1193 let ipip2 = VniLayer::Ipip {
1194 endpoints: endpoints2,
1195 };
1196
1197 assert_ne!(ipip1, ipip2);
1199 }
1200
1201 #[test]
1202 fn test_gre_with_and_without_key() {
1203 let mut mapper = VniMapper::new();
1204 let endpoints = [
1205 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
1206 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
1207 ];
1208
1209 let gre_no_key = VniLayer::Gre {
1210 protocol_type: 0x0800,
1211 key: None,
1212 endpoints,
1213 };
1214 let gre_with_key = VniLayer::Gre {
1215 protocol_type: 0x0800,
1216 key: Some(100),
1217 endpoints,
1218 };
1219
1220 let id1 = mapper.get_or_create_vni_id(&[gre_no_key]);
1221 let id2 = mapper.get_or_create_vni_id(&[gre_with_key]);
1222
1223 assert_ne!(id1, id2);
1224 assert_eq!(mapper.len(), 2);
1225 }
1226
1227 #[test]
1228 fn test_vni_mapper_with_all_layer_types() {
1229 let mut mapper = VniMapper::new();
1230 let endpoints_v4 = [
1231 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
1232 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
1233 ];
1234 let endpoints_v6 = [
1235 IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)),
1236 IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2)),
1237 ];
1238
1239 let layers = vec![
1241 VniLayer::Vlan { vid: 100 },
1242 VniLayer::Mpls { label: 1000 },
1243 VniLayer::Gre {
1244 protocol_type: 0x0800,
1245 key: None,
1246 endpoints: endpoints_v4,
1247 },
1248 VniLayer::NvGre {
1249 protocol_type: 0x6558,
1250 vsid_flowid: 100,
1251 endpoints: endpoints_v4,
1252 },
1253 VniLayer::Vxlan {
1254 vni: 5000,
1255 group_id: 0,
1256 endpoints: endpoints_v4,
1257 },
1258 VniLayer::Geneve {
1259 vni: 1000,
1260 protocol_type: 0x6558,
1261 endpoints: endpoints_v6,
1262 },
1263 VniLayer::Ipip {
1264 endpoints: endpoints_v4,
1265 },
1266 VniLayer::Ip4in6 {
1267 endpoints: endpoints_v6,
1268 },
1269 VniLayer::Sit {
1270 endpoints: endpoints_v4,
1271 },
1272 VniLayer::Ip6Tnl {
1273 endpoints: endpoints_v6,
1274 },
1275 VniLayer::GtpU {
1276 teid: 0x12345678,
1277 endpoints: endpoints_v4,
1278 },
1279 VniLayer::Teredo {
1280 endpoints: endpoints_v4,
1281 },
1282 VniLayer::L2tpV2 {
1283 tunnel_id: 100,
1284 session_id: 200,
1285 endpoints: endpoints_v4,
1286 },
1287 VniLayer::L2tpV3 {
1288 session_id: 0xabcdef,
1289 endpoints: endpoints_v6,
1290 },
1291 VniLayer::Pbb {
1292 isid: 0x123456,
1293 bvid: Some(100),
1294 },
1295 VniLayer::Stt {
1296 context_id: 0x123456789abcdef0,
1297 endpoints: endpoints_v4,
1298 },
1299 VniLayer::Pptp {
1300 call_id: 1234,
1301 endpoints: endpoints_v4,
1302 },
1303 ];
1304
1305 let mut ids = Vec::new();
1307 for layer in &layers {
1308 let id = mapper.get_or_create_vni_id(std::slice::from_ref(layer));
1309 ids.push(id);
1310 }
1311
1312 assert_eq!(mapper.len(), layers.len());
1313
1314 for i in 0..ids.len() {
1316 for j in (i + 1)..ids.len() {
1317 assert_ne!(
1318 ids[i], ids[j],
1319 "IDs at positions {} and {} should be different",
1320 i, j
1321 );
1322 }
1323 }
1324 }
1325
1326 #[test]
1327 fn test_vni_id_ordering() {
1328 let id1 = VniId::from_u32(1);
1329 let id2 = VniId::from_u32(2);
1330 let id3 = VniId::from_u32(2);
1331
1332 assert!(id1 < id2);
1333 assert_eq!(id2, id3);
1334 assert!(id1 != id2);
1335 }
1336
1337 #[test]
1338 fn test_smallvec_spill_behavior() {
1339 let vlan1 = VniLayer::Vlan { vid: 100 };
1341 let vlan2 = VniLayer::Vlan { vid: 200 };
1342 let vlan3 = VniLayer::Vlan { vid: 300 };
1343 let vlan4 = VniLayer::Vlan { vid: 400 };
1344 let vlan5 = VniLayer::Vlan { vid: 500 };
1345
1346 let mut sv = SmallVec::<[VniLayer; 4]>::new();
1347 sv.push(vlan1);
1348 sv.push(vlan2);
1349 sv.push(vlan3);
1350 sv.push(vlan4);
1351
1352 assert!(!sv.spilled()); sv.push(vlan5);
1355 assert!(sv.spilled()); assert_eq!(sv.len(), 5);
1357 }
1358
1359 #[test]
1360 fn test_vni_mapper_consistency_after_many_insertions() {
1361 let mut mapper = VniMapper::new();
1362
1363 for i in 0..100 {
1365 let vlan = VniLayer::Vlan { vid: i };
1366 mapper.get_or_create_vni_id(&[vlan]);
1367 }
1368
1369 assert_eq!(mapper.len(), 100);
1370
1371 for i in 1..=100 {
1373 let id = VniId::from_u32(i);
1374 assert!(mapper.lookup_vni(id).is_some());
1375 }
1376 }
1377
1378 #[test]
1379 fn test_vni_error_is_error_trait() {
1380 use std::error::Error;
1381
1382 let err = VniError::InvalidHeaderLength;
1383 let _: &dyn Error = &err; assert!(err.source().is_none());
1387 }
1388
1389 #[test]
1394 fn test_regression_vni_mapper_id_stability() {
1395 let mut mapper = VniMapper::new();
1397 let endpoints = [
1398 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
1399 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
1400 ];
1401
1402 let vxlan = VniLayer::Vxlan {
1403 vni: 5000,
1404 group_id: 0,
1405 endpoints,
1406 };
1407
1408 let id1 = mapper.get_or_create_vni_id(std::slice::from_ref(&vxlan));
1409 let id2 = mapper.get_or_create_vni_id(std::slice::from_ref(&vxlan));
1410 let id3 = mapper.get_or_create_vni_id(std::slice::from_ref(&vxlan));
1411
1412 assert_eq!(id1, id2);
1413 assert_eq!(id2, id3);
1414 assert_eq!(mapper.len(), 1);
1415 }
1416
1417 #[test]
1418 fn test_regression_vni_layer_protocol_type_variations() {
1419 let endpoints = [
1421 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)),
1422 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 2)),
1423 ];
1424
1425 let gre_ipv4 = VniLayer::Gre {
1426 protocol_type: 0x0800, key: None,
1428 endpoints,
1429 };
1430
1431 let gre_ipv6 = VniLayer::Gre {
1432 protocol_type: 0x86DD, key: None,
1434 endpoints,
1435 };
1436
1437 assert_ne!(gre_ipv4, gre_ipv6);
1438 }
1439
1440 #[test]
1441 fn test_regression_vxlan_group_id_zero_vs_nonzero() {
1442 let endpoints = [
1444 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
1445 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
1446 ];
1447
1448 let vxlan1 = VniLayer::Vxlan {
1449 vni: 100,
1450 group_id: 0,
1451 endpoints,
1452 };
1453
1454 let vxlan2 = VniLayer::Vxlan {
1455 vni: 100,
1456 group_id: 1,
1457 endpoints,
1458 };
1459
1460 assert_ne!(vxlan1, vxlan2);
1461 }
1462
1463 #[test]
1464 fn test_regression_nvgre_vsid_flowid_encoding() {
1465 let endpoints = [
1467 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
1468 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
1469 ];
1470
1471 let vsid: u32 = 0x123456;
1473 let flow_id: u8 = 0xAB;
1474 let combined = (vsid << 8) | flow_id as u32;
1475
1476 let _nvgre = VniLayer::NvGre {
1477 protocol_type: 0x6558,
1478 vsid_flowid: combined,
1479 endpoints,
1480 };
1481 }
1482
1483 #[test]
1484 fn test_regression_pbb_with_optional_bvid() {
1485 let pbb1 = VniLayer::Pbb {
1487 isid: 0x123456,
1488 bvid: None,
1489 };
1490
1491 let pbb2 = VniLayer::Pbb {
1492 isid: 0x123456,
1493 bvid: Some(0),
1494 };
1495
1496 let pbb3 = VniLayer::Pbb {
1497 isid: 0x123456,
1498 bvid: Some(100),
1499 };
1500
1501 assert_ne!(pbb1, pbb2);
1502 assert_ne!(pbb2, pbb3);
1503 }
1504
1505 #[test]
1506 fn test_regression_l2tp_versions_distinct() {
1507 let endpoints = [
1509 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
1510 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
1511 ];
1512
1513 let l2tpv2 = VniLayer::L2tpV2 {
1514 tunnel_id: 100,
1515 session_id: 200,
1516 endpoints,
1517 };
1518
1519 let l2tpv3 = VniLayer::L2tpV3 {
1520 session_id: 200,
1521 endpoints,
1522 };
1523
1524 assert_ne!(format!("{:?}", l2tpv2), format!("{:?}", l2tpv3));
1526 }
1527
1528 #[test]
1529 fn test_regression_endpoint_ipv4_vs_ipv6() {
1530 let endpoints_v4 = [
1532 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
1533 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
1534 ];
1535
1536 let endpoints_v6 = [
1537 IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x0a00, 0x0001)),
1538 IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x0a00, 0x0002)),
1539 ];
1540
1541 let ipip_v4 = VniLayer::Ipip {
1542 endpoints: endpoints_v4,
1543 };
1544 let ipip_v6_as_ip6tnl = VniLayer::Ip6Tnl {
1545 endpoints: endpoints_v6,
1546 };
1547
1548 assert_ne!(format!("{:?}", ipip_v4), format!("{:?}", ipip_v6_as_ip6tnl));
1550 }
1551
1552 #[test]
1553 fn test_regression_vni_mapper_large_scale() {
1554 let mut mapper = VniMapper::new();
1556 let mut all_ids = Vec::new();
1557
1558 for i in 0..1000 {
1560 let vlan = VniLayer::Vlan { vid: i };
1561 let id = mapper.get_or_create_vni_id(&[vlan]);
1562 all_ids.push(id);
1563 }
1564
1565 assert_eq!(mapper.len(), 1000);
1566
1567 for i in 0..all_ids.len() {
1569 for j in (i + 1)..all_ids.len() {
1570 assert_ne!(all_ids[i], all_ids[j]);
1571 }
1572 }
1573
1574 for (idx, id) in all_ids.iter().enumerate() {
1576 let stack = mapper.lookup_vni(*id).unwrap();
1577 assert_eq!(stack.len(), 1);
1578 match &stack[0] {
1579 VniLayer::Vlan { vid } => {
1580 assert_eq!(*vid, idx as u16);
1581 }
1582 _ => panic!("Expected Vlan variant"),
1583 }
1584 }
1585 }
1586
1587 #[test]
1588 fn test_regression_deep_vni_stack() {
1589 let mut mapper = VniMapper::new();
1591 let endpoints = [
1592 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
1593 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
1594 ];
1595
1596 let layers = vec![
1597 VniLayer::Vlan { vid: 100 },
1598 VniLayer::Mpls { label: 1000 },
1599 VniLayer::Vlan { vid: 200 },
1600 VniLayer::Vxlan {
1601 vni: 5000,
1602 group_id: 0,
1603 endpoints,
1604 },
1605 VniLayer::Vlan { vid: 300 },
1606 VniLayer::Mpls { label: 2000 },
1607 ];
1608
1609 let id = mapper.get_or_create_vni_id(&layers);
1610 let retrieved = mapper.lookup_vni(id).unwrap();
1611
1612 assert_eq!(retrieved.len(), layers.len());
1613 for (i, layer) in layers.iter().enumerate() {
1614 assert_eq!(&retrieved[i], layer);
1615 }
1616 }
1617
1618 #[test]
1623 fn test_packet_to_vni_empty() {
1624 use crate::packet::iter::LinkType;
1625 use crate::packet::{Packet, ParseMode};
1626
1627 let packet_bytes = vec![
1629 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0x08, 0x00, 0x45, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, ];
1643
1644 let packet = Packet::from_bytes(&packet_bytes, LinkType::Ethernet, ParseMode::Outermost)
1645 .expect("Should parse packet");
1646
1647 let vni_stack: SmallVec<[VniLayer; 4]> =
1648 (&packet).try_into().expect("Should convert to VNI stack");
1649
1650 assert_eq!(vni_stack.len(), 0);
1652 }
1653
1654 #[test]
1655 fn test_packet_to_vni_vlan_only() {
1656 use crate::packet::iter::LinkType;
1657 use crate::packet::{Packet, ParseMode};
1658
1659 let packet_bytes = vec![
1661 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0x81, 0x00, 0x00, 0x64, 0x08, 0x00, 0x45, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x0a, 0x00,
1670 0x00, 0x01, 0x0a, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
1672 ];
1673
1674 let packet = Packet::from_bytes(&packet_bytes, LinkType::Ethernet, ParseMode::Outermost)
1675 .expect("Should parse packet");
1676
1677 let vni_stack: SmallVec<[VniLayer; 4]> =
1678 (&packet).try_into().expect("Should convert to VNI stack");
1679
1680 assert_eq!(vni_stack.len(), 1);
1682 assert!(matches!(vni_stack[0], VniLayer::Vlan { vid: 100 }));
1683 }
1684
1685 #[test]
1686 fn test_packet_to_vni_vxlan_tunnel() {
1687 use crate::packet::iter::LinkType;
1688 use crate::packet::{Packet, ParseMode};
1689
1690 let mut packet_bytes = Vec::new();
1692
1693 packet_bytes.extend_from_slice(&[
1695 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0x08, 0x00, ]);
1699
1700 packet_bytes.extend_from_slice(&[
1702 0x45, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0x00, 0x00, 10, 0, 0, 1, 10, 0, 0, 2, ]);
1708
1709 packet_bytes.extend_from_slice(&[
1711 0x30, 0x39, 0x12, 0xb5, 0x00, 0x28, 0x00, 0x00, ]);
1716
1717 packet_bytes.extend_from_slice(&[
1719 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf4, 0x00, ]);
1722
1723 packet_bytes.extend_from_slice(&[
1725 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x08,
1726 0x00, ]);
1728
1729 packet_bytes.extend_from_slice(&[
1731 0x45, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 192, 168, 1, 1,
1732 192, 168, 1, 2, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
1734 ]);
1735
1736 let packet = Packet::from_bytes(&packet_bytes, LinkType::Ethernet, ParseMode::Innermost)
1737 .expect("Should parse VXLAN packet");
1738
1739 let vni_stack: SmallVec<[VniLayer; 4]> =
1740 (&packet).try_into().expect("Should convert to VNI stack");
1741
1742 assert_eq!(vni_stack.len(), 1);
1744 match &vni_stack[0] {
1745 VniLayer::Vxlan { vni, endpoints, .. } => {
1746 assert_eq!(*vni, 500);
1747 assert!(endpoints.contains(&IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1))));
1749 assert!(endpoints.contains(&IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2))));
1750 }
1751 _ => panic!("Expected VXLAN layer"),
1752 }
1753 }
1754
1755 #[test]
1756 fn test_packet_to_vni_vlan_plus_vxlan() {
1757 use crate::packet::iter::LinkType;
1758 use crate::packet::{Packet, ParseMode};
1759
1760 let mut packet_bytes = Vec::new();
1762
1763 packet_bytes.extend_from_slice(&[
1765 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0x81,
1766 0x00, 0x00, 0xc8, 0x08, 0x00, ]);
1770
1771 packet_bytes.extend_from_slice(&[
1773 0x45, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0x00, 0x00, 172, 16, 0, 1,
1774 172, 16, 0, 2,
1775 ]);
1776
1777 packet_bytes.extend_from_slice(&[0x30, 0x39, 0x12, 0xb5, 0x00, 0x28, 0x00, 0x00]);
1779
1780 packet_bytes.extend_from_slice(&[
1782 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, ]);
1784
1785 packet_bytes.extend_from_slice(&[
1787 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x08, 0x00,
1788 ]);
1789
1790 packet_bytes.extend_from_slice(&[
1792 0x45, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 192, 168, 1, 1,
1793 192, 168, 1, 2, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
1795 ]);
1796
1797 let packet = Packet::from_bytes(&packet_bytes, LinkType::Ethernet, ParseMode::Innermost)
1798 .expect("Should parse packet");
1799
1800 let vni_stack: SmallVec<[VniLayer; 4]> =
1801 (&packet).try_into().expect("Should convert to VNI stack");
1802
1803 assert_eq!(
1806 vni_stack.len(),
1807 1,
1808 "Expected 1 layer (VXLAN only), got {}",
1809 vni_stack.len()
1810 );
1811
1812 match &vni_stack[0] {
1814 VniLayer::Vxlan { vni, endpoints, .. } => {
1815 assert_eq!(*vni, 10);
1816 assert!(endpoints.contains(&IpAddr::V4(Ipv4Addr::new(172, 16, 0, 1))));
1818 assert!(endpoints.contains(&IpAddr::V4(Ipv4Addr::new(172, 16, 0, 2))));
1819 }
1820 _ => panic!("Expected VXLAN layer"),
1821 }
1822 }
1823
1824 #[test]
1825 fn test_packet_to_vni_nested_vlan() {
1826 use crate::packet::iter::LinkType;
1827 use crate::packet::{Packet, ParseMode};
1828
1829 let packet_bytes = vec![
1831 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0x81,
1833 0x00, 0x00, 0x64, 0x81, 0x00, 0x00, 0xc8, 0x08, 0x00, 0x45, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x0a, 0x00,
1840 0x00, 0x01, 0x0a, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
1842 ];
1843
1844 let packet = Packet::from_bytes(&packet_bytes, LinkType::Ethernet, ParseMode::Outermost)
1845 .expect("Should parse packet");
1846
1847 let vni_stack: SmallVec<[VniLayer; 4]> =
1848 (&packet).try_into().expect("Should convert to VNI stack");
1849
1850 assert_eq!(vni_stack.len(), 2);
1852 assert!(matches!(vni_stack[0], VniLayer::Vlan { vid: 100 }));
1853 assert!(matches!(vni_stack[1], VniLayer::Vlan { vid: 200 }));
1854 }
1855
1856 #[test]
1857 fn test_packet_to_vni_with_vni_mapper() {
1858 use crate::packet::iter::LinkType;
1859 use crate::packet::{Packet, ParseMode};
1860
1861 let packet_bytes = vec![
1863 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0x81, 0x00,
1865 0x01, 0x2c, 0x08, 0x00, 0x45, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x0a, 0x00,
1868 0x00, 0x01, 0x0a, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
1870 ];
1871
1872 let packet = Packet::from_bytes(&packet_bytes, LinkType::Ethernet, ParseMode::Outermost)
1873 .expect("Should parse packet");
1874
1875 let vni_stack: SmallVec<[VniLayer; 4]> =
1876 (&packet).try_into().expect("Should convert to VNI stack");
1877
1878 let mut mapper = VniMapper::new();
1880 let vni_id = mapper.get_or_create_vni_id(&vni_stack);
1881
1882 let retrieved = mapper.lookup_vni(vni_id).unwrap();
1884 assert_eq!(retrieved.len(), 1);
1885 assert!(matches!(retrieved[0], VniLayer::Vlan { vid: 300 }));
1886 }
1887
1888 #[test]
1889 fn test_regression_vni_id_u32_boundary() {
1890 let id_zero = VniId::from_u32(0);
1892 let id_max = VniId::from_u32(u32::MAX);
1893 let id_mid = VniId::from_u32(u32::MAX / 2);
1894
1895 assert_eq!(id_zero.as_u32(), 0);
1896 assert_eq!(id_max.as_u32(), u32::MAX);
1897 assert_eq!(id_mid.as_u32(), u32::MAX / 2);
1898
1899 assert_ne!(id_zero, id_max);
1900 assert_ne!(id_mid, id_max);
1901 }
1902
1903 #[test]
1904 fn test_regression_mapper_clear_and_reuse() {
1905 let mut mapper = VniMapper::new();
1907 let vlan = VniLayer::Vlan { vid: 100 };
1908
1909 let id1 = mapper.get_or_create_vni_id(std::slice::from_ref(&vlan));
1911 assert_eq!(id1.as_u32(), 1);
1912 assert_eq!(mapper.len(), 1);
1913
1914 mapper.clear();
1916 assert_eq!(mapper.len(), 0);
1917 assert!(mapper.is_empty());
1918
1919 let id2 = mapper.get_or_create_vni_id(std::slice::from_ref(&vlan));
1921 assert_eq!(id2.as_u32(), 1); assert_eq!(mapper.len(), 1);
1923
1924 let vlan2 = VniLayer::Vlan { vid: 200 };
1926 let id3 = mapper.get_or_create_vni_id(&[vlan2]);
1927 assert_eq!(id3.as_u32(), 2);
1928 assert_eq!(mapper.len(), 2);
1929 }
1930
1931 #[test]
1932 fn test_regression_mixed_tunnel_stack_uniqueness() {
1933 let mut mapper = VniMapper::new();
1935 let endpoints = [
1936 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
1937 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
1938 ];
1939
1940 let vlan100 = VniLayer::Vlan { vid: 100 };
1941 let vlan200 = VniLayer::Vlan { vid: 200 };
1942 let vxlan = VniLayer::Vxlan {
1943 vni: 5000,
1944 group_id: 0,
1945 endpoints,
1946 };
1947
1948 let id1 = mapper.get_or_create_vni_id(&[vlan100.clone(), vxlan.clone()]);
1950 let id2 = mapper.get_or_create_vni_id(&[vxlan.clone(), vlan100.clone()]);
1951 let id3 = mapper.get_or_create_vni_id(&[vlan100.clone(), vlan200.clone(), vxlan.clone()]);
1952 let id4 = mapper.get_or_create_vni_id(&[vlan100.clone(), vxlan.clone(), vlan200.clone()]);
1953
1954 assert_ne!(id1, id2);
1956 assert_ne!(id1, id3);
1957 assert_ne!(id1, id4);
1958 assert_ne!(id2, id3);
1959 assert_ne!(id2, id4);
1960 assert_ne!(id3, id4);
1961
1962 assert_eq!(mapper.len(), 4);
1963 }
1964}