1use crate::error::ParserError;
2use crate::models::network::{Afi, Safi};
3#[cfg(feature = "parser")]
4use crate::parser::ReadUtils;
5#[cfg(feature = "parser")]
6use bytes::{BufMut, Bytes, BytesMut};
7use num_enum::{FromPrimitive, IntoPrimitive};
8#[cfg(feature = "parser")]
9use zerocopy::big_endian::{U16, U32};
10#[cfg(feature = "parser")]
11use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
12
13#[cfg(feature = "parser")]
15#[derive(IntoBytes, FromBytes, KnownLayout, Immutable)]
16#[repr(C)]
17struct RawMultiprotocolExtensions {
18 afi: U16,
19 reserved: u8,
20 safi: u8,
21}
22
23#[cfg(feature = "parser")]
25#[derive(IntoBytes, FromBytes, KnownLayout, Immutable)]
26#[repr(C)]
27struct RawFourOctetAs {
28 asn: U32,
29}
30
31#[allow(non_camel_case_types)]
32#[derive(Debug, FromPrimitive, IntoPrimitive, PartialEq, Eq, Hash, Copy, Clone)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34#[repr(u8)]
35pub enum BgpCapabilityType {
36 MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4 = 1,
37 ROUTE_REFRESH_CAPABILITY_FOR_BGP_4 = 2,
38 OUTBOUND_ROUTE_FILTERING_CAPABILITY = 3,
39 EXTENDED_NEXT_HOP_ENCODING = 5,
40 BGP_EXTENDED_MESSAGE = 6,
41 BGPSEC_CAPABILITY = 7,
42 MULTIPLE_LABELS_CAPABILITY = 8,
43 BGP_ROLE = 9,
44 GRACEFUL_RESTART_CAPABILITY = 64,
45 SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY = 65,
46 SUPPORT_FOR_DYNAMIC_CAPABILITY = 67,
47 MULTISESSION_BGP_CAPABILITY = 68,
48 ADD_PATH_CAPABILITY = 69,
49 ENHANCED_ROUTE_REFRESH_CAPABILITY = 70,
50 LONG_LIVED_GRACEFUL_RESTART_CAPABILITY = 71,
51 ROUTING_POLICY_DISTRIBUTION = 72,
52 FQDN_CAPABILITY = 73,
53
54 #[num_enum(catch_all)]
56 Unknown(u8),
57}
58
59impl BgpCapabilityType {
60 pub const fn is_deprecated(&self) -> bool {
61 matches!(
62 self,
63 BgpCapabilityType::Unknown(4 | 66 | 128 | 129 | 130 | 131 | 184 | 185)
64 )
65 }
66
67 pub const fn is_reserved(&self) -> bool {
68 matches!(self, BgpCapabilityType::Unknown(0 | 255))
69 }
70
71 pub const fn is_reserved_for_experimental_use(&self) -> bool {
72 matches!(self, BgpCapabilityType::Unknown(239..=254))
73 }
74}
75
76#[derive(Debug, Clone, PartialEq, Eq, Hash)]
79#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
80pub struct ExtendedNextHopEntry {
81 pub nlri_afi: Afi,
83 pub nlri_safi: Safi,
85 pub nexthop_afi: Afi,
87}
88
89#[derive(Debug, Clone, PartialEq, Eq)]
92#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
93pub struct ExtendedNextHopCapability {
94 pub entries: Vec<ExtendedNextHopEntry>,
96}
97
98impl ExtendedNextHopCapability {
99 pub fn new(entries: Vec<ExtendedNextHopEntry>) -> Self {
101 Self { entries }
102 }
103
104 pub fn supports(&self, nlri_afi: Afi, nlri_safi: Safi, nexthop_afi: Afi) -> bool {
106 self.entries.iter().any(|entry| {
107 entry.nlri_afi == nlri_afi
108 && entry.nlri_safi == nlri_safi
109 && entry.nexthop_afi == nexthop_afi
110 })
111 }
112
113 pub fn supported_nlri_for_nexthop(&self, nexthop_afi: Afi) -> Vec<(Afi, Safi)> {
115 self.entries
116 .iter()
117 .filter(|entry| entry.nexthop_afi == nexthop_afi)
118 .map(|entry| (entry.nlri_afi, entry.nlri_safi))
119 .collect()
120 }
121
122 #[cfg(feature = "parser")]
129 pub fn parse(mut data: Bytes) -> Result<Self, ParserError> {
130 let mut entries = Vec::new();
131
132 if !data.len().is_multiple_of(6) {
134 return Err(ParserError::ParseError(format!(
135 "Extended Next Hop capability length {} is not divisible by 6",
136 data.len()
137 )));
138 }
139
140 while data.len() >= 6 {
141 let nlri_afi = data.read_afi()?;
142 let nlri_safi_u16 = data.read_u16()?;
144 let nlri_safi = Safi::try_from(nlri_safi_u16 as u8).map_err(|_| {
145 ParserError::ParseError(format!("Unknown SAFI type: {}", nlri_safi_u16))
146 })?;
147 let nexthop_afi = data.read_afi()?;
148
149 entries.push(ExtendedNextHopEntry {
150 nlri_afi,
151 nlri_safi,
152 nexthop_afi,
153 });
154 }
155
156 Ok(ExtendedNextHopCapability::new(entries))
157 }
158
159 #[cfg(feature = "parser")]
161 pub fn encode(&self) -> Bytes {
162 let mut bytes = BytesMut::with_capacity(self.entries.len() * 6);
163
164 for entry in &self.entries {
165 bytes.put_u16(entry.nlri_afi as u16); bytes.put_u16(entry.nlri_safi as u8 as u16); bytes.put_u16(entry.nexthop_afi as u16); }
169
170 bytes.freeze()
171 }
172}
173
174#[derive(Debug, Clone, PartialEq, Eq, Hash)]
177#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
178pub struct MultiprotocolExtensionsCapability {
179 pub afi: Afi,
181 pub safi: Safi,
183}
184
185impl MultiprotocolExtensionsCapability {
186 pub fn new(afi: Afi, safi: Safi) -> Self {
188 Self { afi, safi }
189 }
190
191 #[cfg(feature = "parser")]
198 pub fn parse(data: Bytes) -> Result<Self, ParserError> {
199 let raw = RawMultiprotocolExtensions::ref_from_bytes(&data).map_err(|_| {
200 ParserError::ParseError(format!(
201 "Multiprotocol Extensions capability length {} is not 4",
202 data.len()
203 ))
204 })?;
205
206 let afi = Afi::try_from(raw.afi.get())?;
207 let safi = Safi::try_from(raw.safi)
208 .map_err(|_| ParserError::ParseError(format!("Unknown SAFI type: {}", raw.safi)))?;
209
210 Ok(MultiprotocolExtensionsCapability::new(afi, safi))
211 }
212
213 #[cfg(feature = "parser")]
215 pub fn encode(&self) -> Bytes {
216 let raw = RawMultiprotocolExtensions {
217 afi: U16::new(self.afi as u16),
218 reserved: 0,
219 safi: self.safi as u8,
220 };
221 Bytes::copy_from_slice(raw.as_bytes())
222 }
223}
224
225#[derive(Debug, Clone, PartialEq, Eq)]
227#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
228pub struct GracefulRestartCapability {
229 pub restart_state: bool,
231 pub restart_time: u16,
233 pub address_families: Vec<GracefulRestartAddressFamily>,
235}
236
237#[derive(Debug, Clone, PartialEq, Eq, Hash)]
239#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
240pub struct GracefulRestartAddressFamily {
241 pub afi: Afi,
243 pub safi: Safi,
245 pub forwarding_state: bool,
247}
248
249impl GracefulRestartCapability {
250 pub fn new(
252 restart_state: bool,
253 restart_time: u16,
254 address_families: Vec<GracefulRestartAddressFamily>,
255 ) -> Self {
256 Self {
257 restart_state,
258 restart_time,
259 address_families,
260 }
261 }
262
263 #[cfg(feature = "parser")]
269 pub fn parse(mut data: Bytes) -> Result<Self, ParserError> {
270 if data.len() < 2 {
271 return Err(ParserError::ParseError(format!(
272 "Graceful Restart capability length {} is less than minimum 2 bytes",
273 data.len()
274 )));
275 }
276
277 let restart_flags_and_time = data.read_u16()?;
279 let restart_state = (restart_flags_and_time & 0x8000) != 0; let restart_time = restart_flags_and_time & 0x0FFF; let mut address_families = Vec::new();
283
284 if !data.len().is_multiple_of(4) {
286 return Err(ParserError::ParseError(format!(
287 "Graceful Restart capability remaining length {} is not divisible by 4",
288 data.len()
289 )));
290 }
291
292 while data.len() >= 4 {
293 let afi = data.read_afi()?;
294 let safi_u8 = data.read_u8()?;
295 let safi = Safi::try_from(safi_u8)
296 .map_err(|_| ParserError::ParseError(format!("Unknown SAFI type: {}", safi_u8)))?;
297 let flags = data.read_u8()?;
298 let forwarding_state = (flags & 0x80) != 0; address_families.push(GracefulRestartAddressFamily {
301 afi,
302 safi,
303 forwarding_state,
304 });
305 }
306
307 Ok(GracefulRestartCapability::new(
308 restart_state,
309 restart_time,
310 address_families,
311 ))
312 }
313
314 #[cfg(feature = "parser")]
316 pub fn encode(&self) -> Bytes {
317 let mut bytes = BytesMut::with_capacity(2 + self.address_families.len() * 4);
318
319 let restart_flags_and_time = if self.restart_state {
321 0x8000 | (self.restart_time & 0x0FFF)
322 } else {
323 self.restart_time & 0x0FFF
324 };
325 bytes.put_u16(restart_flags_and_time);
326
327 for af in &self.address_families {
329 bytes.put_u16(af.afi as u16); bytes.put_u8(af.safi as u8); let flags = if af.forwarding_state { 0x80 } else { 0x00 };
332 bytes.put_u8(flags); }
334
335 bytes.freeze()
336 }
337}
338
339#[derive(Debug, Clone, PartialEq, Eq)]
341#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
342pub struct AddPathCapability {
343 pub address_families: Vec<AddPathAddressFamily>,
345}
346
347#[derive(Debug, Clone, PartialEq, Eq, Hash)]
349#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
350pub struct AddPathAddressFamily {
351 pub afi: Afi,
353 pub safi: Safi,
355 pub send_receive: AddPathSendReceive,
357}
358
359#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
361#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
362pub enum AddPathSendReceive {
363 Receive = 1,
365 Send = 2,
367 SendReceive = 3,
369}
370
371impl TryFrom<u8> for AddPathSendReceive {
372 type Error = ParserError;
373
374 fn try_from(value: u8) -> Result<Self, Self::Error> {
375 match value {
376 1 => Ok(AddPathSendReceive::Receive),
377 2 => Ok(AddPathSendReceive::Send),
378 3 => Ok(AddPathSendReceive::SendReceive),
379 _ => Err(ParserError::ParseError(format!(
380 "Invalid ADD-PATH Send/Receive value: {}",
381 value
382 ))),
383 }
384 }
385}
386
387impl AddPathCapability {
388 pub fn new(address_families: Vec<AddPathAddressFamily>) -> Self {
390 Self { address_families }
391 }
392
393 #[cfg(feature = "parser")]
400 pub fn parse(mut data: Bytes) -> Result<Self, ParserError> {
401 let mut address_families = Vec::new();
402
403 if !data.len().is_multiple_of(4) {
405 return Err(ParserError::ParseError(format!(
406 "ADD-PATH capability length {} is not divisible by 4",
407 data.len()
408 )));
409 }
410
411 while data.len() >= 4 {
412 let afi = data.read_afi()?;
413 let safi_u8 = data.read_u8()?;
414 let safi = Safi::try_from(safi_u8)
415 .map_err(|_| ParserError::ParseError(format!("Unknown SAFI type: {}", safi_u8)))?;
416 let send_receive_u8 = data.read_u8()?;
417 let send_receive = AddPathSendReceive::try_from(send_receive_u8)?;
418
419 address_families.push(AddPathAddressFamily {
420 afi,
421 safi,
422 send_receive,
423 });
424 }
425
426 Ok(AddPathCapability::new(address_families))
427 }
428
429 #[cfg(feature = "parser")]
431 pub fn encode(&self) -> Bytes {
432 let mut bytes = BytesMut::with_capacity(self.address_families.len() * 4);
433
434 for af in &self.address_families {
435 bytes.put_u16(af.afi as u16); bytes.put_u8(af.safi as u8); bytes.put_u8(af.send_receive as u8); }
439
440 bytes.freeze()
441 }
442}
443
444#[derive(Debug, Clone, PartialEq, Eq, Hash)]
447#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
448pub struct RouteRefreshCapability;
449
450impl RouteRefreshCapability {
451 pub fn new() -> Self {
453 Self
454 }
455
456 #[cfg(feature = "parser")]
459 pub fn parse(data: Bytes) -> Result<Self, ParserError> {
460 if !data.is_empty() {
461 return Err(ParserError::ParseError(format!(
462 "Route Refresh capability should have length 0, got {}",
463 data.len()
464 )));
465 }
466 Ok(RouteRefreshCapability::new())
467 }
468
469 #[cfg(feature = "parser")]
472 pub fn encode(&self) -> Bytes {
473 Bytes::new()
474 }
475}
476
477impl Default for RouteRefreshCapability {
478 fn default() -> Self {
479 Self::new()
480 }
481}
482
483#[derive(Debug, Clone, PartialEq, Eq, Hash)]
486#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
487pub struct BgpExtendedMessageCapability;
488
489impl BgpExtendedMessageCapability {
490 pub fn new() -> Self {
492 Self
493 }
494
495 #[cfg(feature = "parser")]
498 pub fn parse(data: Bytes) -> Result<Self, ParserError> {
499 if !data.is_empty() {
500 return Err(ParserError::ParseError(format!(
501 "BGP Extended Message capability should have length 0, got {}",
502 data.len()
503 )));
504 }
505 Ok(BgpExtendedMessageCapability::new())
506 }
507
508 #[cfg(feature = "parser")]
511 pub fn encode(&self) -> Bytes {
512 Bytes::new()
513 }
514}
515
516impl Default for BgpExtendedMessageCapability {
517 fn default() -> Self {
518 Self::new()
519 }
520}
521
522#[derive(Debug, Clone, PartialEq, Eq, Hash)]
524#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
525pub struct FourOctetAsCapability {
526 pub asn: u32,
528}
529
530impl FourOctetAsCapability {
531 pub fn new(asn: u32) -> Self {
533 Self { asn }
534 }
535
536 #[cfg(feature = "parser")]
539 pub fn parse(data: Bytes) -> Result<Self, ParserError> {
540 let raw = RawFourOctetAs::ref_from_bytes(&data).map_err(|_| {
541 ParserError::ParseError(format!(
542 "4-octet AS capability length {} is not 4",
543 data.len()
544 ))
545 })?;
546
547 Ok(FourOctetAsCapability::new(raw.asn.get()))
548 }
549
550 #[cfg(feature = "parser")]
552 pub fn encode(&self) -> Bytes {
553 let raw = RawFourOctetAs {
554 asn: U32::new(self.asn),
555 };
556 Bytes::copy_from_slice(raw.as_bytes())
557 }
558}
559
560#[derive(Debug, Clone, PartialEq, Eq, Hash)]
562#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
563pub struct BgpRoleCapability {
564 pub role: BgpRole,
566}
567
568#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
570#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
571pub enum BgpRole {
572 Provider = 0,
574 RouteServer = 1,
576 RouteServerClient = 2,
578 Customer = 3,
580 Peer = 4,
582}
583
584impl TryFrom<u8> for BgpRole {
585 type Error = ParserError;
586
587 fn try_from(value: u8) -> Result<Self, Self::Error> {
588 match value {
589 0 => Ok(BgpRole::Provider),
590 1 => Ok(BgpRole::RouteServer),
591 2 => Ok(BgpRole::RouteServerClient),
592 3 => Ok(BgpRole::Customer),
593 4 => Ok(BgpRole::Peer),
594 _ => Err(ParserError::ParseError(format!(
595 "Unknown BGP Role value: {}",
596 value
597 ))),
598 }
599 }
600}
601
602impl BgpRoleCapability {
603 pub fn new(role: BgpRole) -> Self {
605 Self { role }
606 }
607
608 #[cfg(feature = "parser")]
611 pub fn parse(mut data: Bytes) -> Result<Self, ParserError> {
612 if data.len() != 1 {
613 return Err(ParserError::ParseError(format!(
614 "BGP Role capability length {} is not 1",
615 data.len()
616 )));
617 }
618
619 let role_u8 = data.read_u8()?;
620 let role = BgpRole::try_from(role_u8)?;
621 Ok(BgpRoleCapability::new(role))
622 }
623
624 #[cfg(feature = "parser")]
626 pub fn encode(&self) -> Bytes {
627 let mut bytes = BytesMut::with_capacity(1);
628 bytes.put_u8(self.role as u8);
629 bytes.freeze()
630 }
631}
632
633#[cfg(all(test, feature = "parser"))]
634mod tests {
635 use super::*;
636
637 #[test]
638 fn test_parsing_capability() {
639 assert!(BgpCapabilityType::from(0).is_reserved());
641 assert!(BgpCapabilityType::from(255).is_reserved());
642
643 for code in [4, 66, 128, 129, 130, 131, 184, 185] {
645 assert!(BgpCapabilityType::from(code).is_deprecated());
646 }
647
648 let unassigned_ranges = [10..=63, 74..=127, 132..=183, 186..=238];
650 for code in <[_; 4]>::into_iter(unassigned_ranges).flatten() {
651 let ty = BgpCapabilityType::from(code);
652 assert_eq!(ty, BgpCapabilityType::Unknown(code));
653 assert!(!ty.is_deprecated() && !ty.is_reserved());
654 }
655
656 assert_eq!(
658 BgpCapabilityType::from(1),
659 BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4
660 );
661 assert_eq!(
662 BgpCapabilityType::from(2),
663 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4
664 );
665 assert_eq!(
666 BgpCapabilityType::from(3),
667 BgpCapabilityType::OUTBOUND_ROUTE_FILTERING_CAPABILITY
668 );
669 assert_eq!(
670 BgpCapabilityType::from(5),
671 BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING
672 );
673 assert_eq!(
674 BgpCapabilityType::from(6),
675 BgpCapabilityType::BGP_EXTENDED_MESSAGE
676 );
677 assert_eq!(
678 BgpCapabilityType::from(7),
679 BgpCapabilityType::BGPSEC_CAPABILITY
680 );
681 assert_eq!(
682 BgpCapabilityType::from(8),
683 BgpCapabilityType::MULTIPLE_LABELS_CAPABILITY
684 );
685 assert_eq!(BgpCapabilityType::from(9), BgpCapabilityType::BGP_ROLE);
686
687 assert_eq!(
688 BgpCapabilityType::from(64),
689 BgpCapabilityType::GRACEFUL_RESTART_CAPABILITY
690 );
691 assert_eq!(
692 BgpCapabilityType::from(65),
693 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
694 );
695 assert_eq!(
696 BgpCapabilityType::from(67),
697 BgpCapabilityType::SUPPORT_FOR_DYNAMIC_CAPABILITY
698 );
699 assert_eq!(
700 BgpCapabilityType::from(68),
701 BgpCapabilityType::MULTISESSION_BGP_CAPABILITY
702 );
703 assert_eq!(
704 BgpCapabilityType::from(69),
705 BgpCapabilityType::ADD_PATH_CAPABILITY
706 );
707 assert_eq!(
708 BgpCapabilityType::from(70),
709 BgpCapabilityType::ENHANCED_ROUTE_REFRESH_CAPABILITY
710 );
711 assert_eq!(
712 BgpCapabilityType::from(71),
713 BgpCapabilityType::LONG_LIVED_GRACEFUL_RESTART_CAPABILITY
714 );
715 assert_eq!(
716 BgpCapabilityType::from(72),
717 BgpCapabilityType::ROUTING_POLICY_DISTRIBUTION
718 );
719 assert_eq!(
720 BgpCapabilityType::from(73),
721 BgpCapabilityType::FQDN_CAPABILITY
722 );
723 }
724
725 #[test]
726 fn test_reserved_for_experimental() {
727 let experimental_ranges = [239..=254];
728 for code in <[_; 1]>::into_iter(experimental_ranges).flatten() {
729 let ty = BgpCapabilityType::from(code);
730 assert_eq!(ty, BgpCapabilityType::Unknown(code));
731 assert!(ty.is_reserved_for_experimental_use());
732 }
733 }
734
735 #[test]
736 #[cfg(feature = "serde")]
737 fn test_serde() {
738 let ty = BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4;
739 let serialized = serde_json::to_string(&ty).unwrap();
740 let deserialized: BgpCapabilityType = serde_json::from_str(&serialized).unwrap();
741 assert_eq!(ty, deserialized);
742 }
743
744 #[test]
745 fn test_extended_next_hop_capability() {
746 use crate::models::network::{Afi, Safi};
747
748 let entries = vec![
750 ExtendedNextHopEntry {
751 nlri_afi: Afi::Ipv4,
752 nlri_safi: Safi::Unicast,
753 nexthop_afi: Afi::Ipv6,
754 },
755 ExtendedNextHopEntry {
756 nlri_afi: Afi::Ipv4,
757 nlri_safi: Safi::MplsVpn,
758 nexthop_afi: Afi::Ipv6,
759 },
760 ];
761
762 let capability = ExtendedNextHopCapability::new(entries);
763
764 assert!(capability.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
766 assert!(capability.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
767 assert!(!capability.supports(Afi::Ipv4, Safi::Multicast, Afi::Ipv6));
768 assert!(!capability.supports(Afi::Ipv6, Safi::Unicast, Afi::Ipv6));
769
770 let supported = capability.supported_nlri_for_nexthop(Afi::Ipv6);
772 assert_eq!(supported.len(), 2);
773 assert!(supported.contains(&(Afi::Ipv4, Safi::Unicast)));
774 assert!(supported.contains(&(Afi::Ipv4, Safi::MplsVpn)));
775
776 let no_support = capability.supported_nlri_for_nexthop(Afi::Ipv4);
777 assert!(no_support.is_empty());
778 }
779
780 #[test]
781 fn test_extended_next_hop_capability_parsing() {
782 use crate::models::network::{Afi, Safi};
783
784 let capability_bytes = Bytes::from(vec![
788 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, 0x00, 0x02, ]);
795
796 let parsed = ExtendedNextHopCapability::parse(capability_bytes).unwrap();
797
798 assert_eq!(parsed.entries.len(), 2);
799
800 assert_eq!(parsed.entries[0].nlri_afi, Afi::Ipv4);
802 assert_eq!(parsed.entries[0].nlri_safi, Safi::Unicast);
803 assert_eq!(parsed.entries[0].nexthop_afi, Afi::Ipv6);
804
805 assert_eq!(parsed.entries[1].nlri_afi, Afi::Ipv4);
807 assert_eq!(parsed.entries[1].nlri_safi, Safi::MplsVpn);
808 assert_eq!(parsed.entries[1].nexthop_afi, Afi::Ipv6);
809
810 assert!(parsed.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
812 assert!(parsed.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
813 assert!(!parsed.supports(Afi::Ipv4, Safi::Multicast, Afi::Ipv6));
814 }
815
816 #[test]
817 fn test_extended_next_hop_capability_encoding() {
818 use crate::models::network::{Afi, Safi};
819
820 let entries = vec![
821 ExtendedNextHopEntry {
822 nlri_afi: Afi::Ipv4,
823 nlri_safi: Safi::Unicast,
824 nexthop_afi: Afi::Ipv6,
825 },
826 ExtendedNextHopEntry {
827 nlri_afi: Afi::Ipv4,
828 nlri_safi: Safi::MplsVpn,
829 nexthop_afi: Afi::Ipv6,
830 },
831 ];
832
833 let capability = ExtendedNextHopCapability::new(entries);
834 let encoded = capability.encode();
835
836 let expected = vec![
837 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, 0x00, 0x02, ];
844
845 assert_eq!(encoded.to_vec(), expected);
846 }
847
848 #[test]
849 fn test_extended_next_hop_capability_round_trip() {
850 use crate::models::network::{Afi, Safi};
851
852 let original_entries = vec![
853 ExtendedNextHopEntry {
854 nlri_afi: Afi::Ipv4,
855 nlri_safi: Safi::Unicast,
856 nexthop_afi: Afi::Ipv6,
857 },
858 ExtendedNextHopEntry {
859 nlri_afi: Afi::Ipv4,
860 nlri_safi: Safi::MulticastVpn,
861 nexthop_afi: Afi::Ipv6,
862 },
863 ];
864
865 let original = ExtendedNextHopCapability::new(original_entries);
866 let encoded = original.encode();
867 let parsed = ExtendedNextHopCapability::parse(encoded).unwrap();
868
869 assert_eq!(original, parsed);
870 }
871
872 #[test]
873 fn test_extended_next_hop_capability_invalid_length() {
874 let invalid_bytes = Bytes::from(vec![0x00, 0x01, 0x00, 0x01, 0x00]); let result = ExtendedNextHopCapability::parse(invalid_bytes);
877 assert!(result.is_err());
878
879 if let Err(ParserError::ParseError(msg)) = result {
880 assert!(msg.contains("not divisible by 6"));
881 } else {
882 panic!("Expected ParseError with divisibility message");
883 }
884 }
885
886 #[test]
887 fn test_extended_next_hop_capability_empty() {
888 let empty_bytes = Bytes::from(vec![]);
890 let parsed = ExtendedNextHopCapability::parse(empty_bytes).unwrap();
891 assert_eq!(parsed.entries.len(), 0);
892
893 let empty_capability = ExtendedNextHopCapability::new(vec![]);
895 let encoded = empty_capability.encode();
896 assert_eq!(encoded.len(), 0);
897 }
898
899 #[test]
900 fn test_multiprotocol_extensions_capability() {
901 use crate::models::network::{Afi, Safi};
902
903 let capability = MultiprotocolExtensionsCapability::new(Afi::Ipv4, Safi::Unicast);
905
906 let encoded = capability.encode();
908 assert_eq!(encoded.len(), 4);
909 assert_eq!(encoded[0], 0x00); assert_eq!(encoded[1], 0x01); assert_eq!(encoded[2], 0x00); assert_eq!(encoded[3], 0x01); let parsed = MultiprotocolExtensionsCapability::parse(encoded).unwrap();
916 assert_eq!(parsed.afi, Afi::Ipv4);
917 assert_eq!(parsed.safi, Safi::Unicast);
918 assert_eq!(parsed, capability);
919 }
920
921 #[test]
922 fn test_multiprotocol_extensions_capability_ipv6() {
923 use crate::models::network::{Afi, Safi};
924
925 let capability = MultiprotocolExtensionsCapability::new(Afi::Ipv6, Safi::Multicast);
927
928 let encoded = capability.encode();
929 let parsed = MultiprotocolExtensionsCapability::parse(encoded).unwrap();
930 assert_eq!(parsed.afi, Afi::Ipv6);
931 assert_eq!(parsed.safi, Safi::Multicast);
932 }
933
934 #[test]
935 fn test_multiprotocol_extensions_capability_invalid_length() {
936 let invalid_bytes = Bytes::from(vec![0x00, 0x01, 0x00]); let result = MultiprotocolExtensionsCapability::parse(invalid_bytes);
939 assert!(result.is_err());
940 }
941
942 #[test]
943 fn test_graceful_restart_capability() {
944 use crate::models::network::{Afi, Safi};
945
946 let address_families = vec![
948 GracefulRestartAddressFamily {
949 afi: Afi::Ipv4,
950 safi: Safi::Unicast,
951 forwarding_state: true,
952 },
953 GracefulRestartAddressFamily {
954 afi: Afi::Ipv6,
955 safi: Safi::Unicast,
956 forwarding_state: false,
957 },
958 ];
959
960 let capability = GracefulRestartCapability::new(true, 180, address_families);
961
962 let encoded = capability.encode();
964 assert_eq!(encoded.len(), 2 + 2 * 4); let parsed = GracefulRestartCapability::parse(encoded).unwrap();
968 assert!(parsed.restart_state);
969 assert_eq!(parsed.restart_time, 180);
970 assert_eq!(parsed.address_families.len(), 2);
971
972 assert_eq!(parsed.address_families[0].afi, Afi::Ipv4);
974 assert_eq!(parsed.address_families[0].safi, Safi::Unicast);
975 assert!(parsed.address_families[0].forwarding_state);
976
977 assert_eq!(parsed.address_families[1].afi, Afi::Ipv6);
979 assert_eq!(parsed.address_families[1].safi, Safi::Unicast);
980 assert!(!parsed.address_families[1].forwarding_state);
981 }
982
983 #[test]
984 fn test_graceful_restart_capability_no_restart_state() {
985 let capability = GracefulRestartCapability::new(false, 300, vec![]);
987
988 let encoded = capability.encode();
989 let parsed = GracefulRestartCapability::parse(encoded).unwrap();
990 assert!(!parsed.restart_state);
991 assert_eq!(parsed.restart_time, 300);
992 assert_eq!(parsed.address_families.len(), 0);
993 }
994
995 #[test]
996 fn test_graceful_restart_capability_invalid_length() {
997 let invalid_bytes = Bytes::from(vec![0x80, 0xB4, 0x00, 0x01, 0x01]); let result = GracefulRestartCapability::parse(invalid_bytes);
1000 assert!(result.is_err());
1001 }
1002
1003 #[test]
1004 fn test_add_path_capability() {
1005 use crate::models::network::{Afi, Safi};
1006
1007 let address_families = vec![
1009 AddPathAddressFamily {
1010 afi: Afi::Ipv4,
1011 safi: Safi::Unicast,
1012 send_receive: AddPathSendReceive::SendReceive,
1013 },
1014 AddPathAddressFamily {
1015 afi: Afi::Ipv6,
1016 safi: Safi::Unicast,
1017 send_receive: AddPathSendReceive::Receive,
1018 },
1019 ];
1020
1021 let capability = AddPathCapability::new(address_families);
1022
1023 let encoded = capability.encode();
1025 assert_eq!(encoded.len(), 2 * 4); let parsed = AddPathCapability::parse(encoded).unwrap();
1029 assert_eq!(parsed.address_families.len(), 2);
1030
1031 assert_eq!(parsed.address_families[0].afi, Afi::Ipv4);
1033 assert_eq!(parsed.address_families[0].safi, Safi::Unicast);
1034 assert_eq!(
1035 parsed.address_families[0].send_receive,
1036 AddPathSendReceive::SendReceive
1037 );
1038
1039 assert_eq!(parsed.address_families[1].afi, Afi::Ipv6);
1041 assert_eq!(parsed.address_families[1].safi, Safi::Unicast);
1042 assert_eq!(
1043 parsed.address_families[1].send_receive,
1044 AddPathSendReceive::Receive
1045 );
1046 }
1047
1048 #[test]
1049 fn test_add_path_send_receive_values() {
1050 use AddPathSendReceive::*;
1051
1052 assert_eq!(Receive as u8, 1);
1053 assert_eq!(Send as u8, 2);
1054 assert_eq!(SendReceive as u8, 3);
1055
1056 assert_eq!(AddPathSendReceive::try_from(1).unwrap(), Receive);
1057 assert_eq!(AddPathSendReceive::try_from(2).unwrap(), Send);
1058 assert_eq!(AddPathSendReceive::try_from(3).unwrap(), SendReceive);
1059
1060 assert!(AddPathSendReceive::try_from(4).is_err());
1062 }
1063
1064 #[test]
1065 fn test_add_path_capability_invalid_length() {
1066 let invalid_bytes = Bytes::from(vec![0x00, 0x01, 0x01]); let result = AddPathCapability::parse(invalid_bytes);
1069 assert!(result.is_err());
1070 }
1071
1072 #[test]
1073 fn test_add_path_capability_empty() {
1074 let empty_bytes = Bytes::from(vec![]);
1076 let parsed = AddPathCapability::parse(empty_bytes).unwrap();
1077 assert_eq!(parsed.address_families.len(), 0);
1078
1079 let empty_capability = AddPathCapability::new(vec![]);
1081 let encoded = empty_capability.encode();
1082 assert_eq!(encoded.len(), 0);
1083 }
1084
1085 #[test]
1086 fn test_route_refresh_capability() {
1087 let capability = RouteRefreshCapability::new();
1089
1090 let encoded = capability.encode();
1092 assert_eq!(encoded.len(), 0);
1093
1094 let parsed = RouteRefreshCapability::parse(encoded).unwrap();
1096 assert_eq!(parsed, capability);
1097 }
1098
1099 #[test]
1100 fn test_route_refresh_capability_invalid_length() {
1101 let invalid_bytes = Bytes::from(vec![0x01]);
1103 let result = RouteRefreshCapability::parse(invalid_bytes);
1104 assert!(result.is_err());
1105 }
1106
1107 #[test]
1108 fn test_four_octet_as_capability() {
1109 let test_cases = [0, 65535, 65536, 4294967295];
1111
1112 for asn in test_cases {
1113 let capability = FourOctetAsCapability::new(asn);
1114
1115 let encoded = capability.encode();
1117 assert_eq!(encoded.len(), 4);
1118
1119 let parsed = FourOctetAsCapability::parse(encoded).unwrap();
1121 assert_eq!(parsed.asn, asn);
1122 assert_eq!(parsed, capability);
1123 }
1124 }
1125
1126 #[test]
1127 fn test_four_octet_as_capability_invalid_length() {
1128 let invalid_bytes = Bytes::from(vec![0x00, 0x01, 0x00]); let result = FourOctetAsCapability::parse(invalid_bytes);
1131 assert!(result.is_err());
1132 }
1133
1134 #[test]
1135 fn test_bgp_role_capability() {
1136 use BgpRole::*;
1137
1138 let test_cases = [
1140 (Provider, 0),
1141 (RouteServer, 1),
1142 (RouteServerClient, 2),
1143 (Customer, 3),
1144 (Peer, 4),
1145 ];
1146
1147 for (role, expected_value) in test_cases {
1148 let capability = BgpRoleCapability::new(role);
1149
1150 let encoded = capability.encode();
1152 assert_eq!(encoded.len(), 1);
1153 assert_eq!(encoded[0], expected_value);
1154
1155 let parsed = BgpRoleCapability::parse(encoded).unwrap();
1157 assert_eq!(parsed.role, role);
1158 assert_eq!(parsed, capability);
1159 }
1160 }
1161
1162 #[test]
1163 fn test_bgp_role_values() {
1164 use BgpRole::*;
1165
1166 assert_eq!(Provider as u8, 0);
1168 assert_eq!(RouteServer as u8, 1);
1169 assert_eq!(RouteServerClient as u8, 2);
1170 assert_eq!(Customer as u8, 3);
1171 assert_eq!(Peer as u8, 4);
1172
1173 assert_eq!(BgpRole::try_from(0).unwrap(), Provider);
1175 assert_eq!(BgpRole::try_from(1).unwrap(), RouteServer);
1176 assert_eq!(BgpRole::try_from(2).unwrap(), RouteServerClient);
1177 assert_eq!(BgpRole::try_from(3).unwrap(), Customer);
1178 assert_eq!(BgpRole::try_from(4).unwrap(), Peer);
1179
1180 assert!(BgpRole::try_from(5).is_err());
1182 assert!(BgpRole::try_from(255).is_err());
1183 }
1184
1185 #[test]
1186 fn test_bgp_role_capability_invalid_length() {
1187 let invalid_bytes = Bytes::from(vec![0x00, 0x01]); let result = BgpRoleCapability::parse(invalid_bytes);
1190 assert!(result.is_err());
1191
1192 let empty_bytes = Bytes::from(vec![]);
1194 let result = BgpRoleCapability::parse(empty_bytes);
1195 assert!(result.is_err());
1196 }
1197
1198 #[test]
1199 fn test_bgp_role_capability_invalid_value() {
1200 let invalid_bytes = Bytes::from(vec![5]); let result = BgpRoleCapability::parse(invalid_bytes);
1203 assert!(result.is_err());
1204 }
1205
1206 #[test]
1207 fn test_bgp_extended_message_capability() {
1208 let capability = BgpExtendedMessageCapability::new();
1210
1211 let encoded = capability.encode();
1213 assert_eq!(encoded.len(), 0);
1214
1215 let parsed = BgpExtendedMessageCapability::parse(encoded).unwrap();
1217 assert_eq!(parsed, capability);
1218 }
1219
1220 #[test]
1221 fn test_bgp_extended_message_capability_invalid_length() {
1222 let invalid_bytes = Bytes::from(vec![0x01]);
1224 let result = BgpExtendedMessageCapability::parse(invalid_bytes);
1225 assert!(result.is_err());
1226 }
1227}