1use std::fmt::{self, Formatter};
73
74use zerocopy::byteorder::{BigEndian, U32};
75use zerocopy::{FromBytes, IntoBytes, Unaligned};
76
77use crate::packet::{HeaderParser, PacketHeader};
78
79pub const MPLS_ETHERTYPE_UNICAST: u16 = 0x8847;
81
82pub const MPLS_ETHERTYPE_MULTICAST: u16 = 0x8848;
84
85#[inline]
87pub fn is_mpls_ethertype(ethertype: u16) -> bool {
88 ethertype == MPLS_ETHERTYPE_UNICAST || ethertype == MPLS_ETHERTYPE_MULTICAST
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93#[repr(u32)]
94pub enum MplsReservedLabel {
95 Ipv4ExplicitNull = 0,
97 RouterAlert = 1,
99 Ipv6ExplicitNull = 2,
101 ImplicitNull = 3,
103 EntropyLabelIndicator = 7,
105 Gal = 13,
107 OamAlert = 14,
109 Extension = 15,
111}
112
113impl MplsReservedLabel {
114 #[inline]
116 pub fn is_reserved(label: u32) -> bool {
117 label <= 15
118 }
119
120 pub fn from_label(label: u32) -> Option<Self> {
122 match label {
123 0 => Some(MplsReservedLabel::Ipv4ExplicitNull),
124 1 => Some(MplsReservedLabel::RouterAlert),
125 2 => Some(MplsReservedLabel::Ipv6ExplicitNull),
126 3 => Some(MplsReservedLabel::ImplicitNull),
127 7 => Some(MplsReservedLabel::EntropyLabelIndicator),
128 13 => Some(MplsReservedLabel::Gal),
129 14 => Some(MplsReservedLabel::OamAlert),
130 15 => Some(MplsReservedLabel::Extension),
131 _ => None,
132 }
133 }
134}
135
136impl fmt::Display for MplsReservedLabel {
137 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
138 match self {
139 MplsReservedLabel::Ipv4ExplicitNull => write!(f, "IPv4 Explicit NULL"),
140 MplsReservedLabel::RouterAlert => write!(f, "Router Alert"),
141 MplsReservedLabel::Ipv6ExplicitNull => write!(f, "IPv6 Explicit NULL"),
142 MplsReservedLabel::ImplicitNull => write!(f, "Implicit NULL"),
143 MplsReservedLabel::EntropyLabelIndicator => write!(f, "Entropy Label Indicator"),
144 MplsReservedLabel::Gal => write!(f, "GAL"),
145 MplsReservedLabel::OamAlert => write!(f, "OAM Alert"),
146 MplsReservedLabel::Extension => write!(f, "Extension"),
147 }
148 }
149}
150
151#[repr(C, packed)]
161#[derive(
162 FromBytes, IntoBytes, Unaligned, Debug, Clone, Copy, zerocopy::KnownLayout, zerocopy::Immutable,
163)]
164pub struct MplsLabel {
165 label_tc_s_ttl: U32<BigEndian>,
166}
167
168impl MplsLabel {
169 pub const LABEL_MASK: u32 = 0xFFFFF000;
171 pub const LABEL_SHIFT: u32 = 12;
172
173 pub const TC_MASK: u32 = 0x00000E00;
175 pub const TC_SHIFT: u32 = 9;
176
177 pub const BOS_MASK: u32 = 0x00000100;
179 pub const BOS_SHIFT: u32 = 8;
180
181 pub const TTL_MASK: u32 = 0x000000FF;
183
184 pub const MAX_LABEL: u32 = 0xFFFFF;
186
187 pub const MAX_TC: u8 = 7;
189
190 #[allow(unused)]
191 const NAME: &'static str = "MplsLabel";
192
193 #[inline]
195 pub fn raw(&self) -> u32 {
196 self.label_tc_s_ttl.get()
197 }
198
199 #[inline]
201 pub fn label(&self) -> u32 {
202 (self.raw() & Self::LABEL_MASK) >> Self::LABEL_SHIFT
203 }
204
205 #[inline]
210 pub fn traffic_class(&self) -> u8 {
211 ((self.raw() & Self::TC_MASK) >> Self::TC_SHIFT) as u8
212 }
213
214 #[inline]
216 pub fn exp(&self) -> u8 {
217 self.traffic_class()
218 }
219
220 #[inline]
222 pub fn is_bottom_of_stack(&self) -> bool {
223 self.raw() & Self::BOS_MASK != 0
224 }
225
226 #[inline]
228 pub fn ttl(&self) -> u8 {
229 (self.raw() & Self::TTL_MASK) as u8
230 }
231
232 #[inline]
234 pub fn is_reserved(&self) -> bool {
235 MplsReservedLabel::is_reserved(self.label())
236 }
237
238 #[inline]
240 pub fn reserved_label(&self) -> Option<MplsReservedLabel> {
241 MplsReservedLabel::from_label(self.label())
242 }
243
244 #[inline]
246 pub fn is_ipv4_explicit_null(&self) -> bool {
247 self.label() == 0
248 }
249
250 #[inline]
252 pub fn is_ipv6_explicit_null(&self) -> bool {
253 self.label() == 2
254 }
255
256 #[inline]
258 pub fn is_implicit_null(&self) -> bool {
259 self.label() == 3
260 }
261
262 #[inline]
264 pub fn is_router_alert(&self) -> bool {
265 self.label() == 1
266 }
267
268 #[inline]
273 fn is_valid(&self) -> bool {
274 true
277 }
278}
279
280impl PacketHeader for MplsLabel {
281 const NAME: &'static str = "MplsLabel";
282 type InnerType = u32;
284
285 #[inline]
286 fn inner_type(&self) -> Self::InnerType {
287 self.label()
288 }
289
290 #[inline]
292 fn total_len(&self, _buf: &[u8]) -> usize {
293 Self::FIXED_LEN }
295
296 #[inline]
298 fn is_valid(&self) -> bool {
299 self.is_valid()
300 }
301}
302
303impl HeaderParser for MplsLabel {
304 type Output<'a> = &'a MplsLabel;
305
306 #[inline]
307 fn into_view<'a>(header: &'a Self, _options: &'a [u8]) -> Self::Output<'a> {
308 header
309 }
310}
311
312impl fmt::Display for MplsLabel {
313 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
314 write!(
315 f,
316 "MPLS label={} tc={} s={} ttl={}",
317 self.label(),
318 self.traffic_class(),
319 if self.is_bottom_of_stack() { 1 } else { 0 },
320 self.ttl()
321 )?;
322
323 if let Some(reserved) = self.reserved_label() {
324 write!(f, " ({})", reserved)?;
325 }
326
327 Ok(())
328 }
329}
330
331pub struct MplsLabelStackIter<'a> {
336 data: &'a [u8],
337 finished: bool,
338}
339
340impl<'a> MplsLabelStackIter<'a> {
341 pub fn new(data: &'a [u8]) -> Self {
343 Self {
344 data,
345 finished: false,
346 }
347 }
348
349 pub fn remaining(&self) -> &'a [u8] {
353 self.data
354 }
355
356 pub fn skip_to_payload(mut self) -> &'a [u8] {
361 while self.next().is_some() {}
362 self.data
363 }
364
365 pub fn collect_labels(self) -> Vec<MplsLabel> {
367 self.copied().collect()
368 }
369}
370
371impl<'a> Iterator for MplsLabelStackIter<'a> {
372 type Item = &'a MplsLabel;
373
374 fn next(&mut self) -> Option<Self::Item> {
375 if self.finished || self.data.len() < 4 {
376 return None;
377 }
378
379 let (label_ref, rest) = zerocopy::Ref::<_, MplsLabel>::from_prefix(self.data).ok()?;
381
382 let label = zerocopy::Ref::into_ref(label_ref);
383
384 if label.is_bottom_of_stack() {
386 self.finished = true;
387 }
388
389 self.data = rest;
390
391 Some(label)
392 }
393}
394
395#[derive(Debug, Clone)]
397pub struct MplsLabelStack<'a> {
398 pub data: &'a [u8],
400 pub count: usize,
402 pub total_size: usize,
404}
405
406impl<'a> MplsLabelStack<'a> {
407 pub fn parse(data: &'a [u8]) -> Option<(Self, &'a [u8])> {
411 let mut offset = 0;
412 let mut count = 0;
413
414 loop {
415 if data.len() < offset + 4 {
416 return None; }
418
419 let label_data = &data[offset..offset + 4];
420 let raw =
421 u32::from_be_bytes([label_data[0], label_data[1], label_data[2], label_data[3]]);
422
423 count += 1;
424 offset += 4;
425
426 if raw & MplsLabel::BOS_MASK != 0 {
428 break;
429 }
430
431 if count > 16 {
433 return None;
434 }
435 }
436
437 Some((
438 MplsLabelStack {
439 data: &data[..offset],
440 count,
441 total_size: offset,
442 },
443 &data[offset..],
444 ))
445 }
446
447 pub fn iter(&self) -> MplsLabelStackIter<'a> {
449 MplsLabelStackIter::new(self.data)
450 }
451
452 pub fn first(&self) -> Option<&'a MplsLabel> {
454 self.iter().next()
455 }
456
457 pub fn last(&self) -> Option<&'a MplsLabel> {
459 self.iter().last()
460 }
461}
462
463impl<'a> IntoIterator for &'a MplsLabelStack<'a> {
464 type Item = &'a MplsLabel;
465 type IntoIter = MplsLabelStackIter<'a>;
466
467 fn into_iter(self) -> Self::IntoIter {
468 self.iter()
469 }
470}
471
472impl fmt::Display for MplsLabelStack<'_> {
473 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
474 write!(f, "MPLS[")?;
475 let mut first = true;
476 for label in self.iter() {
477 if !first {
478 write!(f, " -> ")?;
479 }
480 write!(f, "{}", label.label())?;
481 first = false;
482 }
483 write!(f, "]")
484 }
485}
486
487#[cfg(test)]
488mod tests {
489 use super::*;
490
491 #[test]
492 fn test_mpls_label_size() {
493 assert_eq!(std::mem::size_of::<MplsLabel>(), 4);
494 assert_eq!(MplsLabel::FIXED_LEN, 4);
495 }
496
497 #[test]
498 fn test_mpls_single_label() {
499 let packet = vec![0x00, 0x01, 0x01, 0x40, 0x45, 0x00, 0x00, 0x00];
501
502 let (label, payload) = MplsLabel::from_bytes(&packet).unwrap();
503 assert_eq!(label.label(), 16);
504 assert_eq!(label.traffic_class(), 0);
505 assert!(label.is_bottom_of_stack());
506 assert_eq!(label.ttl(), 64);
507 assert_eq!(payload.len(), 4);
508 }
509
510 #[test]
511 fn test_mpls_label_max_value() {
512 let packet = vec![0xFF, 0xFF, 0xFF, 0xFF];
514
515 let (label, _) = MplsLabel::from_bytes(&packet).unwrap();
516 assert_eq!(label.label(), 0xFFFFF);
517 assert_eq!(label.traffic_class(), 7);
518 assert!(label.is_bottom_of_stack());
519 assert_eq!(label.ttl(), 255);
520 }
521
522 #[test]
523 fn test_mpls_label_zero() {
524 let packet = vec![0x00, 0x00, 0x01, 0x01];
526
527 let (label, _) = MplsLabel::from_bytes(&packet).unwrap();
528 assert_eq!(label.label(), 0);
529 assert!(label.is_ipv4_explicit_null());
530 assert!(label.is_reserved());
531 assert_eq!(
532 label.reserved_label(),
533 Some(MplsReservedLabel::Ipv4ExplicitNull)
534 );
535 }
536
537 #[test]
538 fn test_mpls_label_ipv6_explicit_null() {
539 let packet = vec![0x00, 0x00, 0x21, 0x40];
541
542 let (label, _) = MplsLabel::from_bytes(&packet).unwrap();
543 assert_eq!(label.label(), 2);
544 assert!(label.is_ipv6_explicit_null());
545 assert!(label.is_reserved());
546 }
547
548 #[test]
549 fn test_mpls_label_router_alert() {
550 let packet = vec![0x00, 0x00, 0x11, 0x40];
552
553 let (label, _) = MplsLabel::from_bytes(&packet).unwrap();
554 assert_eq!(label.label(), 1);
555 assert!(label.is_router_alert());
556 }
557
558 #[test]
559 fn test_mpls_label_implicit_null() {
560 let packet = vec![0x00, 0x00, 0x31, 0x40];
562
563 let (label, _) = MplsLabel::from_bytes(&packet).unwrap();
564 assert_eq!(label.label(), 3);
565 assert!(label.is_implicit_null());
566 }
567
568 #[test]
569 fn test_mpls_label_not_bos() {
570 let packet = vec![0x00, 0x06, 0x46, 0x80];
572
573 let (label, _) = MplsLabel::from_bytes(&packet).unwrap();
574 assert_eq!(label.label(), 100);
575 assert_eq!(label.traffic_class(), 3);
576 assert!(!label.is_bottom_of_stack());
577 assert_eq!(label.ttl(), 128);
578 }
579
580 #[test]
581 fn test_mpls_label_stack_iterator() {
582 let packet = vec![
584 0x00, 0x01, 0x00, 0x40, 0x00, 0x02, 0x01, 0x3F, 0x45, 0x00, 0x00, 0x00, ];
588
589 let mut iter = MplsLabelStackIter::new(&packet);
590
591 let first = iter.next().unwrap();
592 assert_eq!(first.label(), 16);
593 assert!(!first.is_bottom_of_stack());
594
595 let second = iter.next().unwrap();
596 assert_eq!(second.label(), 32);
597 assert!(second.is_bottom_of_stack());
598
599 assert!(iter.next().is_none());
600 assert_eq!(iter.remaining().len(), 4);
601 }
602
603 #[test]
604 fn test_mpls_label_stack_three_labels() {
605 let packet = vec![
607 0x00, 0x00, 0xC0, 0x40, 0x00, 0x01, 0x80, 0x3F, 0x00, 0x02, 0x41, 0x3E, 0x45, 0x00, ];
612
613 let mut iter = MplsLabelStackIter::new(&packet);
614
615 let first = iter.next().unwrap();
616 assert_eq!(first.label(), 12);
617 assert!(!first.is_bottom_of_stack());
618
619 let second = iter.next().unwrap();
620 assert_eq!(second.label(), 24);
621 assert!(!second.is_bottom_of_stack());
622
623 let third = iter.next().unwrap();
624 assert_eq!(third.label(), 36);
625 assert!(third.is_bottom_of_stack());
626
627 assert!(iter.next().is_none());
628 }
629
630 #[test]
631 fn test_mpls_label_stack_skip_to_payload() {
632 let packet = vec![
633 0x00, 0x01, 0x00, 0x40, 0x00, 0x02, 0x01, 0x3F, 0x45, 0x00, 0x00, 0x14, ];
637
638 let iter = MplsLabelStackIter::new(&packet);
639 let payload = iter.skip_to_payload();
640 assert_eq!(payload.len(), 4);
641 assert_eq!(payload[0], 0x45); }
643
644 #[test]
645 fn test_mpls_label_stack_collect() {
646 let packet = vec![
647 0x00, 0x01, 0x00, 0x40, 0x00, 0x02, 0x01, 0x3F, ];
650
651 let iter = MplsLabelStackIter::new(&packet);
652 let labels: Vec<MplsLabel> = iter.collect_labels();
653
654 assert_eq!(labels.len(), 2);
655 assert_eq!(labels[0].label(), 16);
656 assert_eq!(labels[1].label(), 32);
657 }
658
659 #[test]
660 fn test_mpls_label_stack_parse() {
661 let packet = vec![
662 0x00, 0x01, 0x00, 0x40, 0x00, 0x02, 0x01, 0x3F, 0x45, 0x00, 0x00, 0x14,
665 ];
666
667 let (stack, payload) = MplsLabelStack::parse(&packet).unwrap();
668 assert_eq!(stack.count, 2);
669 assert_eq!(stack.total_size, 8);
670 assert_eq!(payload.len(), 4);
671
672 let first = stack.first().unwrap();
673 assert_eq!(first.label(), 16);
674
675 let last = stack.last().unwrap();
676 assert_eq!(last.label(), 32);
677 }
678
679 #[test]
680 fn test_mpls_label_stack_single() {
681 let packet = vec![
682 0x00, 0x01, 0x01, 0x40, 0x45, 0x00,
684 ];
685
686 let (stack, payload) = MplsLabelStack::parse(&packet).unwrap();
687 assert_eq!(stack.count, 1);
688 assert_eq!(stack.total_size, 4);
689 assert_eq!(payload.len(), 2);
690 }
691
692 #[test]
693 fn test_mpls_label_too_small() {
694 let packet = vec![0x00, 0x01, 0x01]; let result = MplsLabel::from_bytes(&packet);
696 assert!(result.is_err());
697 }
698
699 #[test]
700 fn test_mpls_label_stack_empty() {
701 let packet: Vec<u8> = vec![];
702 let result = MplsLabelStack::parse(&packet);
703 assert!(result.is_none());
704 }
705
706 #[test]
707 fn test_mpls_display() {
708 let packet = vec![0x00, 0x01, 0x01, 0x40];
709 let (label, _) = MplsLabel::from_bytes(&packet).unwrap();
710 let display = format!("{}", label);
711 assert!(display.contains("label=16"));
712 assert!(display.contains("ttl=64"));
713 }
714
715 #[test]
716 fn test_mpls_display_reserved() {
717 let packet = vec![0x00, 0x00, 0x01, 0x40]; let (label, _) = MplsLabel::from_bytes(&packet).unwrap();
719 let display = format!("{}", label);
720 assert!(display.contains("IPv4 Explicit NULL"));
721 }
722
723 #[test]
724 fn test_mpls_label_stack_display() {
725 let packet = vec![
726 0x00, 0x01, 0x00, 0x40, 0x00, 0x02, 0x01, 0x3F, ];
729
730 let (stack, _) = MplsLabelStack::parse(&packet).unwrap();
731 let display = format!("{}", stack);
732 assert!(display.contains("MPLS["));
733 assert!(display.contains("16"));
734 assert!(display.contains("32"));
735 }
736
737 #[test]
738 fn test_mpls_reserved_labels() {
739 assert!(MplsReservedLabel::is_reserved(0));
740 assert!(MplsReservedLabel::is_reserved(15));
741 assert!(!MplsReservedLabel::is_reserved(16));
742
743 assert_eq!(
744 MplsReservedLabel::from_label(0),
745 Some(MplsReservedLabel::Ipv4ExplicitNull)
746 );
747 assert_eq!(
748 MplsReservedLabel::from_label(1),
749 Some(MplsReservedLabel::RouterAlert)
750 );
751 assert_eq!(
752 MplsReservedLabel::from_label(13),
753 Some(MplsReservedLabel::Gal)
754 );
755 assert_eq!(MplsReservedLabel::from_label(16), None);
756 }
757
758 #[test]
759 fn test_mpls_exp_alias() {
760 let packet = vec![0x00, 0x06, 0x47, 0x40]; let (label, _) = MplsLabel::from_bytes(&packet).unwrap();
762 assert_eq!(label.exp(), label.traffic_class());
763 assert_eq!(label.exp(), 3);
764 }
765
766 #[test]
767 fn test_mpls_ethertype() {
768 assert!(is_mpls_ethertype(0x8847));
769 assert!(is_mpls_ethertype(0x8848));
770 assert!(!is_mpls_ethertype(0x0800));
771 }
772
773 #[test]
774 fn test_mpls_inner_type() {
775 let packet = vec![0x00, 0x10, 0x01, 0x40]; let (label, _) = MplsLabel::from_bytes(&packet).unwrap();
777 assert_eq!(label.inner_type(), 256);
778 }
779
780 #[test]
781 fn test_mpls_label_into_iter() {
782 let packet = vec![0x00, 0x01, 0x00, 0x40, 0x00, 0x02, 0x01, 0x3F];
783
784 let (stack, _) = MplsLabelStack::parse(&packet).unwrap();
785 let labels: Vec<u32> = (&stack).into_iter().map(|l| l.label()).collect();
786 assert_eq!(labels, vec![16, 32]);
787 }
788}