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
9#[allow(non_camel_case_types)]
10#[derive(Debug, FromPrimitive, IntoPrimitive, PartialEq, Eq, Hash, Copy, Clone)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12#[repr(u8)]
13pub enum BgpCapabilityType {
14 MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4 = 1,
15 ROUTE_REFRESH_CAPABILITY_FOR_BGP_4 = 2,
16 OUTBOUND_ROUTE_FILTERING_CAPABILITY = 3,
17 EXTENDED_NEXT_HOP_ENCODING = 5,
18 BGP_EXTENDED_MESSAGE = 6,
19 BGPSEC_CAPABILITY = 7,
20 MULTIPLE_LABELS_CAPABILITY = 8,
21 BGP_ROLE = 9,
22 GRACEFUL_RESTART_CAPABILITY = 64,
23 SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY = 65,
24 SUPPORT_FOR_DYNAMIC_CAPABILITY = 67,
25 MULTISESSION_BGP_CAPABILITY = 68,
26 ADD_PATH_CAPABILITY = 69,
27 ENHANCED_ROUTE_REFRESH_CAPABILITY = 70,
28 LONG_LIVED_GRACEFUL_RESTART_CAPABILITY = 71,
29 ROUTING_POLICY_DISTRIBUTION = 72,
30 FQDN_CAPABILITY = 73,
31
32 #[num_enum(catch_all)]
34 Unknown(u8),
35}
36
37impl BgpCapabilityType {
38 pub const fn is_deprecated(&self) -> bool {
39 matches!(
40 self,
41 BgpCapabilityType::Unknown(4 | 66 | 128 | 129 | 130 | 131 | 184 | 185)
42 )
43 }
44
45 pub const fn is_reserved(&self) -> bool {
46 matches!(self, BgpCapabilityType::Unknown(0 | 255))
47 }
48
49 pub const fn is_reserved_for_experimental_use(&self) -> bool {
50 matches!(self, BgpCapabilityType::Unknown(239..=254))
51 }
52}
53
54#[derive(Debug, Clone, PartialEq, Eq, Hash)]
57#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
58pub struct ExtendedNextHopEntry {
59 pub nlri_afi: Afi,
61 pub nlri_safi: Safi,
63 pub nexthop_afi: Afi,
65}
66
67#[derive(Debug, Clone, PartialEq, Eq)]
70#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
71pub struct ExtendedNextHopCapability {
72 pub entries: Vec<ExtendedNextHopEntry>,
74}
75
76impl ExtendedNextHopCapability {
77 pub fn new(entries: Vec<ExtendedNextHopEntry>) -> Self {
79 Self { entries }
80 }
81
82 pub fn supports(&self, nlri_afi: Afi, nlri_safi: Safi, nexthop_afi: Afi) -> bool {
84 self.entries.iter().any(|entry| {
85 entry.nlri_afi == nlri_afi
86 && entry.nlri_safi == nlri_safi
87 && entry.nexthop_afi == nexthop_afi
88 })
89 }
90
91 pub fn supported_nlri_for_nexthop(&self, nexthop_afi: Afi) -> Vec<(Afi, Safi)> {
93 self.entries
94 .iter()
95 .filter(|entry| entry.nexthop_afi == nexthop_afi)
96 .map(|entry| (entry.nlri_afi, entry.nlri_safi))
97 .collect()
98 }
99
100 #[cfg(feature = "parser")]
107 pub fn parse(mut data: Bytes) -> Result<Self, ParserError> {
108 let mut entries = Vec::new();
109
110 if !data.len().is_multiple_of(6) {
112 return Err(ParserError::ParseError(format!(
113 "Extended Next Hop capability length {} is not divisible by 6",
114 data.len()
115 )));
116 }
117
118 while data.len() >= 6 {
119 let nlri_afi = data.read_afi()?;
120 let nlri_safi_u16 = data.read_u16()?;
122 let nlri_safi = Safi::try_from(nlri_safi_u16 as u8).map_err(|_| {
123 ParserError::ParseError(format!("Unknown SAFI type: {}", nlri_safi_u16))
124 })?;
125 let nexthop_afi = data.read_afi()?;
126
127 entries.push(ExtendedNextHopEntry {
128 nlri_afi,
129 nlri_safi,
130 nexthop_afi,
131 });
132 }
133
134 Ok(ExtendedNextHopCapability::new(entries))
135 }
136
137 #[cfg(feature = "parser")]
139 pub fn encode(&self) -> Bytes {
140 let mut bytes = BytesMut::with_capacity(self.entries.len() * 6);
141
142 for entry in &self.entries {
143 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); }
147
148 bytes.freeze()
149 }
150}
151
152#[derive(Debug, Clone, PartialEq, Eq, Hash)]
155#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
156pub struct MultiprotocolExtensionsCapability {
157 pub afi: Afi,
159 pub safi: Safi,
161}
162
163impl MultiprotocolExtensionsCapability {
164 pub fn new(afi: Afi, safi: Safi) -> Self {
166 Self { afi, safi }
167 }
168
169 #[cfg(feature = "parser")]
176 pub fn parse(mut data: Bytes) -> Result<Self, ParserError> {
177 if data.len() != 4 {
178 return Err(ParserError::ParseError(format!(
179 "Multiprotocol Extensions capability length {} is not 4",
180 data.len()
181 )));
182 }
183
184 let afi = data.read_afi()?;
185 let _reserved = data.read_u8()?; let safi_u8 = data.read_u8()?;
187 let safi = Safi::try_from(safi_u8)
188 .map_err(|_| ParserError::ParseError(format!("Unknown SAFI type: {}", safi_u8)))?;
189
190 Ok(MultiprotocolExtensionsCapability::new(afi, safi))
191 }
192
193 #[cfg(feature = "parser")]
195 pub fn encode(&self) -> Bytes {
196 let mut bytes = BytesMut::with_capacity(4);
197 bytes.put_u16(self.afi as u16); bytes.put_u8(0); bytes.put_u8(self.safi as u8); bytes.freeze()
201 }
202}
203
204#[derive(Debug, Clone, PartialEq, Eq)]
206#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
207pub struct GracefulRestartCapability {
208 pub restart_state: bool,
210 pub restart_time: u16,
212 pub address_families: Vec<GracefulRestartAddressFamily>,
214}
215
216#[derive(Debug, Clone, PartialEq, Eq, Hash)]
218#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
219pub struct GracefulRestartAddressFamily {
220 pub afi: Afi,
222 pub safi: Safi,
224 pub forwarding_state: bool,
226}
227
228impl GracefulRestartCapability {
229 pub fn new(
231 restart_state: bool,
232 restart_time: u16,
233 address_families: Vec<GracefulRestartAddressFamily>,
234 ) -> Self {
235 Self {
236 restart_state,
237 restart_time,
238 address_families,
239 }
240 }
241
242 #[cfg(feature = "parser")]
248 pub fn parse(mut data: Bytes) -> Result<Self, ParserError> {
249 if data.len() < 2 {
250 return Err(ParserError::ParseError(format!(
251 "Graceful Restart capability length {} is less than minimum 2 bytes",
252 data.len()
253 )));
254 }
255
256 let restart_flags_and_time = data.read_u16()?;
258 let restart_state = (restart_flags_and_time & 0x8000) != 0; let restart_time = restart_flags_and_time & 0x0FFF; let mut address_families = Vec::new();
262
263 if !data.len().is_multiple_of(4) {
265 return Err(ParserError::ParseError(format!(
266 "Graceful Restart capability remaining length {} is not divisible by 4",
267 data.len()
268 )));
269 }
270
271 while data.len() >= 4 {
272 let afi = data.read_afi()?;
273 let safi_u8 = data.read_u8()?;
274 let safi = Safi::try_from(safi_u8)
275 .map_err(|_| ParserError::ParseError(format!("Unknown SAFI type: {}", safi_u8)))?;
276 let flags = data.read_u8()?;
277 let forwarding_state = (flags & 0x80) != 0; address_families.push(GracefulRestartAddressFamily {
280 afi,
281 safi,
282 forwarding_state,
283 });
284 }
285
286 Ok(GracefulRestartCapability::new(
287 restart_state,
288 restart_time,
289 address_families,
290 ))
291 }
292
293 #[cfg(feature = "parser")]
295 pub fn encode(&self) -> Bytes {
296 let mut bytes = BytesMut::with_capacity(2 + self.address_families.len() * 4);
297
298 let restart_flags_and_time = if self.restart_state {
300 0x8000 | (self.restart_time & 0x0FFF)
301 } else {
302 self.restart_time & 0x0FFF
303 };
304 bytes.put_u16(restart_flags_and_time);
305
306 for af in &self.address_families {
308 bytes.put_u16(af.afi as u16); bytes.put_u8(af.safi as u8); let flags = if af.forwarding_state { 0x80 } else { 0x00 };
311 bytes.put_u8(flags); }
313
314 bytes.freeze()
315 }
316}
317
318#[derive(Debug, Clone, PartialEq, Eq)]
320#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
321pub struct AddPathCapability {
322 pub address_families: Vec<AddPathAddressFamily>,
324}
325
326#[derive(Debug, Clone, PartialEq, Eq, Hash)]
328#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
329pub struct AddPathAddressFamily {
330 pub afi: Afi,
332 pub safi: Safi,
334 pub send_receive: AddPathSendReceive,
336}
337
338#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
340#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
341pub enum AddPathSendReceive {
342 Receive = 1,
344 Send = 2,
346 SendReceive = 3,
348}
349
350impl TryFrom<u8> for AddPathSendReceive {
351 type Error = ParserError;
352
353 fn try_from(value: u8) -> Result<Self, Self::Error> {
354 match value {
355 1 => Ok(AddPathSendReceive::Receive),
356 2 => Ok(AddPathSendReceive::Send),
357 3 => Ok(AddPathSendReceive::SendReceive),
358 _ => Err(ParserError::ParseError(format!(
359 "Invalid ADD-PATH Send/Receive value: {}",
360 value
361 ))),
362 }
363 }
364}
365
366impl AddPathCapability {
367 pub fn new(address_families: Vec<AddPathAddressFamily>) -> Self {
369 Self { address_families }
370 }
371
372 #[cfg(feature = "parser")]
379 pub fn parse(mut data: Bytes) -> Result<Self, ParserError> {
380 let mut address_families = Vec::new();
381
382 if !data.len().is_multiple_of(4) {
384 return Err(ParserError::ParseError(format!(
385 "ADD-PATH capability length {} is not divisible by 4",
386 data.len()
387 )));
388 }
389
390 while data.len() >= 4 {
391 let afi = data.read_afi()?;
392 let safi_u8 = data.read_u8()?;
393 let safi = Safi::try_from(safi_u8)
394 .map_err(|_| ParserError::ParseError(format!("Unknown SAFI type: {}", safi_u8)))?;
395 let send_receive_u8 = data.read_u8()?;
396 let send_receive = AddPathSendReceive::try_from(send_receive_u8)?;
397
398 address_families.push(AddPathAddressFamily {
399 afi,
400 safi,
401 send_receive,
402 });
403 }
404
405 Ok(AddPathCapability::new(address_families))
406 }
407
408 #[cfg(feature = "parser")]
410 pub fn encode(&self) -> Bytes {
411 let mut bytes = BytesMut::with_capacity(self.address_families.len() * 4);
412
413 for af in &self.address_families {
414 bytes.put_u16(af.afi as u16); bytes.put_u8(af.safi as u8); bytes.put_u8(af.send_receive as u8); }
418
419 bytes.freeze()
420 }
421}
422
423#[derive(Debug, Clone, PartialEq, Eq, Hash)]
426#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
427pub struct RouteRefreshCapability;
428
429impl RouteRefreshCapability {
430 pub fn new() -> Self {
432 Self
433 }
434
435 #[cfg(feature = "parser")]
438 pub fn parse(data: Bytes) -> Result<Self, ParserError> {
439 if !data.is_empty() {
440 return Err(ParserError::ParseError(format!(
441 "Route Refresh capability should have length 0, got {}",
442 data.len()
443 )));
444 }
445 Ok(RouteRefreshCapability::new())
446 }
447
448 #[cfg(feature = "parser")]
451 pub fn encode(&self) -> Bytes {
452 Bytes::new()
453 }
454}
455
456impl Default for RouteRefreshCapability {
457 fn default() -> Self {
458 Self::new()
459 }
460}
461
462#[derive(Debug, Clone, PartialEq, Eq, Hash)]
465#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
466pub struct BgpExtendedMessageCapability;
467
468impl BgpExtendedMessageCapability {
469 pub fn new() -> Self {
471 Self
472 }
473
474 #[cfg(feature = "parser")]
477 pub fn parse(data: Bytes) -> Result<Self, ParserError> {
478 if !data.is_empty() {
479 return Err(ParserError::ParseError(format!(
480 "BGP Extended Message capability should have length 0, got {}",
481 data.len()
482 )));
483 }
484 Ok(BgpExtendedMessageCapability::new())
485 }
486
487 #[cfg(feature = "parser")]
490 pub fn encode(&self) -> Bytes {
491 Bytes::new()
492 }
493}
494
495impl Default for BgpExtendedMessageCapability {
496 fn default() -> Self {
497 Self::new()
498 }
499}
500
501#[derive(Debug, Clone, PartialEq, Eq, Hash)]
503#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
504pub struct FourOctetAsCapability {
505 pub asn: u32,
507}
508
509impl FourOctetAsCapability {
510 pub fn new(asn: u32) -> Self {
512 Self { asn }
513 }
514
515 #[cfg(feature = "parser")]
518 pub fn parse(mut data: Bytes) -> Result<Self, ParserError> {
519 if data.len() != 4 {
520 return Err(ParserError::ParseError(format!(
521 "4-octet AS capability length {} is not 4",
522 data.len()
523 )));
524 }
525
526 let asn = data.read_u32()?;
527 Ok(FourOctetAsCapability::new(asn))
528 }
529
530 #[cfg(feature = "parser")]
532 pub fn encode(&self) -> Bytes {
533 let mut bytes = BytesMut::with_capacity(4);
534 bytes.put_u32(self.asn);
535 bytes.freeze()
536 }
537}
538
539#[derive(Debug, Clone, PartialEq, Eq, Hash)]
541#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
542pub struct BgpRoleCapability {
543 pub role: BgpRole,
545}
546
547#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
549#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
550pub enum BgpRole {
551 Provider = 0,
553 RouteServer = 1,
555 RouteServerClient = 2,
557 Customer = 3,
559 Peer = 4,
561}
562
563impl TryFrom<u8> for BgpRole {
564 type Error = ParserError;
565
566 fn try_from(value: u8) -> Result<Self, Self::Error> {
567 match value {
568 0 => Ok(BgpRole::Provider),
569 1 => Ok(BgpRole::RouteServer),
570 2 => Ok(BgpRole::RouteServerClient),
571 3 => Ok(BgpRole::Customer),
572 4 => Ok(BgpRole::Peer),
573 _ => Err(ParserError::ParseError(format!(
574 "Unknown BGP Role value: {}",
575 value
576 ))),
577 }
578 }
579}
580
581impl BgpRoleCapability {
582 pub fn new(role: BgpRole) -> Self {
584 Self { role }
585 }
586
587 #[cfg(feature = "parser")]
590 pub fn parse(mut data: Bytes) -> Result<Self, ParserError> {
591 if data.len() != 1 {
592 return Err(ParserError::ParseError(format!(
593 "BGP Role capability length {} is not 1",
594 data.len()
595 )));
596 }
597
598 let role_u8 = data.read_u8()?;
599 let role = BgpRole::try_from(role_u8)?;
600 Ok(BgpRoleCapability::new(role))
601 }
602
603 #[cfg(feature = "parser")]
605 pub fn encode(&self) -> Bytes {
606 let mut bytes = BytesMut::with_capacity(1);
607 bytes.put_u8(self.role as u8);
608 bytes.freeze()
609 }
610}
611
612#[cfg(all(test, feature = "parser"))]
613mod tests {
614 use super::*;
615
616 #[test]
617 fn test_parsing_capability() {
618 assert!(BgpCapabilityType::from(0).is_reserved());
620 assert!(BgpCapabilityType::from(255).is_reserved());
621
622 for code in [4, 66, 128, 129, 130, 131, 184, 185] {
624 assert!(BgpCapabilityType::from(code).is_deprecated());
625 }
626
627 let unassigned_ranges = [10..=63, 74..=127, 132..=183, 186..=238];
629 for code in <[_; 4]>::into_iter(unassigned_ranges).flatten() {
630 let ty = BgpCapabilityType::from(code);
631 assert_eq!(ty, BgpCapabilityType::Unknown(code));
632 assert!(!ty.is_deprecated() && !ty.is_reserved());
633 }
634
635 assert_eq!(
637 BgpCapabilityType::from(1),
638 BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4
639 );
640 assert_eq!(
641 BgpCapabilityType::from(2),
642 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4
643 );
644 assert_eq!(
645 BgpCapabilityType::from(3),
646 BgpCapabilityType::OUTBOUND_ROUTE_FILTERING_CAPABILITY
647 );
648 assert_eq!(
649 BgpCapabilityType::from(5),
650 BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING
651 );
652 assert_eq!(
653 BgpCapabilityType::from(6),
654 BgpCapabilityType::BGP_EXTENDED_MESSAGE
655 );
656 assert_eq!(
657 BgpCapabilityType::from(7),
658 BgpCapabilityType::BGPSEC_CAPABILITY
659 );
660 assert_eq!(
661 BgpCapabilityType::from(8),
662 BgpCapabilityType::MULTIPLE_LABELS_CAPABILITY
663 );
664 assert_eq!(BgpCapabilityType::from(9), BgpCapabilityType::BGP_ROLE);
665
666 assert_eq!(
667 BgpCapabilityType::from(64),
668 BgpCapabilityType::GRACEFUL_RESTART_CAPABILITY
669 );
670 assert_eq!(
671 BgpCapabilityType::from(65),
672 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
673 );
674 assert_eq!(
675 BgpCapabilityType::from(67),
676 BgpCapabilityType::SUPPORT_FOR_DYNAMIC_CAPABILITY
677 );
678 assert_eq!(
679 BgpCapabilityType::from(68),
680 BgpCapabilityType::MULTISESSION_BGP_CAPABILITY
681 );
682 assert_eq!(
683 BgpCapabilityType::from(69),
684 BgpCapabilityType::ADD_PATH_CAPABILITY
685 );
686 assert_eq!(
687 BgpCapabilityType::from(70),
688 BgpCapabilityType::ENHANCED_ROUTE_REFRESH_CAPABILITY
689 );
690 assert_eq!(
691 BgpCapabilityType::from(71),
692 BgpCapabilityType::LONG_LIVED_GRACEFUL_RESTART_CAPABILITY
693 );
694 assert_eq!(
695 BgpCapabilityType::from(72),
696 BgpCapabilityType::ROUTING_POLICY_DISTRIBUTION
697 );
698 assert_eq!(
699 BgpCapabilityType::from(73),
700 BgpCapabilityType::FQDN_CAPABILITY
701 );
702 }
703
704 #[test]
705 fn test_reserved_for_experimental() {
706 let experimental_ranges = [239..=254];
707 for code in <[_; 1]>::into_iter(experimental_ranges).flatten() {
708 let ty = BgpCapabilityType::from(code);
709 assert_eq!(ty, BgpCapabilityType::Unknown(code));
710 assert!(ty.is_reserved_for_experimental_use());
711 }
712 }
713
714 #[test]
715 #[cfg(feature = "serde")]
716 fn test_serde() {
717 let ty = BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4;
718 let serialized = serde_json::to_string(&ty).unwrap();
719 let deserialized: BgpCapabilityType = serde_json::from_str(&serialized).unwrap();
720 assert_eq!(ty, deserialized);
721 }
722
723 #[test]
724 fn test_extended_next_hop_capability() {
725 use crate::models::network::{Afi, Safi};
726
727 let entries = vec![
729 ExtendedNextHopEntry {
730 nlri_afi: Afi::Ipv4,
731 nlri_safi: Safi::Unicast,
732 nexthop_afi: Afi::Ipv6,
733 },
734 ExtendedNextHopEntry {
735 nlri_afi: Afi::Ipv4,
736 nlri_safi: Safi::MplsVpn,
737 nexthop_afi: Afi::Ipv6,
738 },
739 ];
740
741 let capability = ExtendedNextHopCapability::new(entries);
742
743 assert!(capability.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
745 assert!(capability.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
746 assert!(!capability.supports(Afi::Ipv4, Safi::Multicast, Afi::Ipv6));
747 assert!(!capability.supports(Afi::Ipv6, Safi::Unicast, Afi::Ipv6));
748
749 let supported = capability.supported_nlri_for_nexthop(Afi::Ipv6);
751 assert_eq!(supported.len(), 2);
752 assert!(supported.contains(&(Afi::Ipv4, Safi::Unicast)));
753 assert!(supported.contains(&(Afi::Ipv4, Safi::MplsVpn)));
754
755 let no_support = capability.supported_nlri_for_nexthop(Afi::Ipv4);
756 assert!(no_support.is_empty());
757 }
758
759 #[test]
760 fn test_extended_next_hop_capability_parsing() {
761 use crate::models::network::{Afi, Safi};
762
763 let capability_bytes = Bytes::from(vec![
767 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, 0x00, 0x02, ]);
774
775 let parsed = ExtendedNextHopCapability::parse(capability_bytes).unwrap();
776
777 assert_eq!(parsed.entries.len(), 2);
778
779 assert_eq!(parsed.entries[0].nlri_afi, Afi::Ipv4);
781 assert_eq!(parsed.entries[0].nlri_safi, Safi::Unicast);
782 assert_eq!(parsed.entries[0].nexthop_afi, Afi::Ipv6);
783
784 assert_eq!(parsed.entries[1].nlri_afi, Afi::Ipv4);
786 assert_eq!(parsed.entries[1].nlri_safi, Safi::MplsVpn);
787 assert_eq!(parsed.entries[1].nexthop_afi, Afi::Ipv6);
788
789 assert!(parsed.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
791 assert!(parsed.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
792 assert!(!parsed.supports(Afi::Ipv4, Safi::Multicast, Afi::Ipv6));
793 }
794
795 #[test]
796 fn test_extended_next_hop_capability_encoding() {
797 use crate::models::network::{Afi, Safi};
798
799 let entries = vec![
800 ExtendedNextHopEntry {
801 nlri_afi: Afi::Ipv4,
802 nlri_safi: Safi::Unicast,
803 nexthop_afi: Afi::Ipv6,
804 },
805 ExtendedNextHopEntry {
806 nlri_afi: Afi::Ipv4,
807 nlri_safi: Safi::MplsVpn,
808 nexthop_afi: Afi::Ipv6,
809 },
810 ];
811
812 let capability = ExtendedNextHopCapability::new(entries);
813 let encoded = capability.encode();
814
815 let expected = vec![
816 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, 0x00, 0x02, ];
823
824 assert_eq!(encoded.to_vec(), expected);
825 }
826
827 #[test]
828 fn test_extended_next_hop_capability_round_trip() {
829 use crate::models::network::{Afi, Safi};
830
831 let original_entries = vec![
832 ExtendedNextHopEntry {
833 nlri_afi: Afi::Ipv4,
834 nlri_safi: Safi::Unicast,
835 nexthop_afi: Afi::Ipv6,
836 },
837 ExtendedNextHopEntry {
838 nlri_afi: Afi::Ipv4,
839 nlri_safi: Safi::MulticastVpn,
840 nexthop_afi: Afi::Ipv6,
841 },
842 ];
843
844 let original = ExtendedNextHopCapability::new(original_entries);
845 let encoded = original.encode();
846 let parsed = ExtendedNextHopCapability::parse(encoded).unwrap();
847
848 assert_eq!(original, parsed);
849 }
850
851 #[test]
852 fn test_extended_next_hop_capability_invalid_length() {
853 let invalid_bytes = Bytes::from(vec![0x00, 0x01, 0x00, 0x01, 0x00]); let result = ExtendedNextHopCapability::parse(invalid_bytes);
856 assert!(result.is_err());
857
858 if let Err(ParserError::ParseError(msg)) = result {
859 assert!(msg.contains("not divisible by 6"));
860 } else {
861 panic!("Expected ParseError with divisibility message");
862 }
863 }
864
865 #[test]
866 fn test_extended_next_hop_capability_empty() {
867 let empty_bytes = Bytes::from(vec![]);
869 let parsed = ExtendedNextHopCapability::parse(empty_bytes).unwrap();
870 assert_eq!(parsed.entries.len(), 0);
871
872 let empty_capability = ExtendedNextHopCapability::new(vec![]);
874 let encoded = empty_capability.encode();
875 assert_eq!(encoded.len(), 0);
876 }
877
878 #[test]
879 fn test_multiprotocol_extensions_capability() {
880 use crate::models::network::{Afi, Safi};
881
882 let capability = MultiprotocolExtensionsCapability::new(Afi::Ipv4, Safi::Unicast);
884
885 let encoded = capability.encode();
887 assert_eq!(encoded.len(), 4);
888 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();
895 assert_eq!(parsed.afi, Afi::Ipv4);
896 assert_eq!(parsed.safi, Safi::Unicast);
897 assert_eq!(parsed, capability);
898 }
899
900 #[test]
901 fn test_multiprotocol_extensions_capability_ipv6() {
902 use crate::models::network::{Afi, Safi};
903
904 let capability = MultiprotocolExtensionsCapability::new(Afi::Ipv6, Safi::Multicast);
906
907 let encoded = capability.encode();
908 let parsed = MultiprotocolExtensionsCapability::parse(encoded).unwrap();
909 assert_eq!(parsed.afi, Afi::Ipv6);
910 assert_eq!(parsed.safi, Safi::Multicast);
911 }
912
913 #[test]
914 fn test_multiprotocol_extensions_capability_invalid_length() {
915 let invalid_bytes = Bytes::from(vec![0x00, 0x01, 0x00]); let result = MultiprotocolExtensionsCapability::parse(invalid_bytes);
918 assert!(result.is_err());
919 }
920
921 #[test]
922 fn test_graceful_restart_capability() {
923 use crate::models::network::{Afi, Safi};
924
925 let address_families = vec![
927 GracefulRestartAddressFamily {
928 afi: Afi::Ipv4,
929 safi: Safi::Unicast,
930 forwarding_state: true,
931 },
932 GracefulRestartAddressFamily {
933 afi: Afi::Ipv6,
934 safi: Safi::Unicast,
935 forwarding_state: false,
936 },
937 ];
938
939 let capability = GracefulRestartCapability::new(true, 180, address_families);
940
941 let encoded = capability.encode();
943 assert_eq!(encoded.len(), 2 + 2 * 4); let parsed = GracefulRestartCapability::parse(encoded).unwrap();
947 assert!(parsed.restart_state);
948 assert_eq!(parsed.restart_time, 180);
949 assert_eq!(parsed.address_families.len(), 2);
950
951 assert_eq!(parsed.address_families[0].afi, Afi::Ipv4);
953 assert_eq!(parsed.address_families[0].safi, Safi::Unicast);
954 assert!(parsed.address_families[0].forwarding_state);
955
956 assert_eq!(parsed.address_families[1].afi, Afi::Ipv6);
958 assert_eq!(parsed.address_families[1].safi, Safi::Unicast);
959 assert!(!parsed.address_families[1].forwarding_state);
960 }
961
962 #[test]
963 fn test_graceful_restart_capability_no_restart_state() {
964 let capability = GracefulRestartCapability::new(false, 300, vec![]);
966
967 let encoded = capability.encode();
968 let parsed = GracefulRestartCapability::parse(encoded).unwrap();
969 assert!(!parsed.restart_state);
970 assert_eq!(parsed.restart_time, 300);
971 assert_eq!(parsed.address_families.len(), 0);
972 }
973
974 #[test]
975 fn test_graceful_restart_capability_invalid_length() {
976 let invalid_bytes = Bytes::from(vec![0x80, 0xB4, 0x00, 0x01, 0x01]); let result = GracefulRestartCapability::parse(invalid_bytes);
979 assert!(result.is_err());
980 }
981
982 #[test]
983 fn test_add_path_capability() {
984 use crate::models::network::{Afi, Safi};
985
986 let address_families = vec![
988 AddPathAddressFamily {
989 afi: Afi::Ipv4,
990 safi: Safi::Unicast,
991 send_receive: AddPathSendReceive::SendReceive,
992 },
993 AddPathAddressFamily {
994 afi: Afi::Ipv6,
995 safi: Safi::Unicast,
996 send_receive: AddPathSendReceive::Receive,
997 },
998 ];
999
1000 let capability = AddPathCapability::new(address_families);
1001
1002 let encoded = capability.encode();
1004 assert_eq!(encoded.len(), 2 * 4); let parsed = AddPathCapability::parse(encoded).unwrap();
1008 assert_eq!(parsed.address_families.len(), 2);
1009
1010 assert_eq!(parsed.address_families[0].afi, Afi::Ipv4);
1012 assert_eq!(parsed.address_families[0].safi, Safi::Unicast);
1013 assert_eq!(
1014 parsed.address_families[0].send_receive,
1015 AddPathSendReceive::SendReceive
1016 );
1017
1018 assert_eq!(parsed.address_families[1].afi, Afi::Ipv6);
1020 assert_eq!(parsed.address_families[1].safi, Safi::Unicast);
1021 assert_eq!(
1022 parsed.address_families[1].send_receive,
1023 AddPathSendReceive::Receive
1024 );
1025 }
1026
1027 #[test]
1028 fn test_add_path_send_receive_values() {
1029 use AddPathSendReceive::*;
1030
1031 assert_eq!(Receive as u8, 1);
1032 assert_eq!(Send as u8, 2);
1033 assert_eq!(SendReceive as u8, 3);
1034
1035 assert_eq!(AddPathSendReceive::try_from(1).unwrap(), Receive);
1036 assert_eq!(AddPathSendReceive::try_from(2).unwrap(), Send);
1037 assert_eq!(AddPathSendReceive::try_from(3).unwrap(), SendReceive);
1038
1039 assert!(AddPathSendReceive::try_from(4).is_err());
1041 }
1042
1043 #[test]
1044 fn test_add_path_capability_invalid_length() {
1045 let invalid_bytes = Bytes::from(vec![0x00, 0x01, 0x01]); let result = AddPathCapability::parse(invalid_bytes);
1048 assert!(result.is_err());
1049 }
1050
1051 #[test]
1052 fn test_add_path_capability_empty() {
1053 let empty_bytes = Bytes::from(vec![]);
1055 let parsed = AddPathCapability::parse(empty_bytes).unwrap();
1056 assert_eq!(parsed.address_families.len(), 0);
1057
1058 let empty_capability = AddPathCapability::new(vec![]);
1060 let encoded = empty_capability.encode();
1061 assert_eq!(encoded.len(), 0);
1062 }
1063
1064 #[test]
1065 fn test_route_refresh_capability() {
1066 let capability = RouteRefreshCapability::new();
1068
1069 let encoded = capability.encode();
1071 assert_eq!(encoded.len(), 0);
1072
1073 let parsed = RouteRefreshCapability::parse(encoded).unwrap();
1075 assert_eq!(parsed, capability);
1076 }
1077
1078 #[test]
1079 fn test_route_refresh_capability_invalid_length() {
1080 let invalid_bytes = Bytes::from(vec![0x01]);
1082 let result = RouteRefreshCapability::parse(invalid_bytes);
1083 assert!(result.is_err());
1084 }
1085
1086 #[test]
1087 fn test_four_octet_as_capability() {
1088 let test_cases = [0, 65535, 65536, 4294967295];
1090
1091 for asn in test_cases {
1092 let capability = FourOctetAsCapability::new(asn);
1093
1094 let encoded = capability.encode();
1096 assert_eq!(encoded.len(), 4);
1097
1098 let parsed = FourOctetAsCapability::parse(encoded).unwrap();
1100 assert_eq!(parsed.asn, asn);
1101 assert_eq!(parsed, capability);
1102 }
1103 }
1104
1105 #[test]
1106 fn test_four_octet_as_capability_invalid_length() {
1107 let invalid_bytes = Bytes::from(vec![0x00, 0x01, 0x00]); let result = FourOctetAsCapability::parse(invalid_bytes);
1110 assert!(result.is_err());
1111 }
1112
1113 #[test]
1114 fn test_bgp_role_capability() {
1115 use BgpRole::*;
1116
1117 let test_cases = [
1119 (Provider, 0),
1120 (RouteServer, 1),
1121 (RouteServerClient, 2),
1122 (Customer, 3),
1123 (Peer, 4),
1124 ];
1125
1126 for (role, expected_value) in test_cases {
1127 let capability = BgpRoleCapability::new(role);
1128
1129 let encoded = capability.encode();
1131 assert_eq!(encoded.len(), 1);
1132 assert_eq!(encoded[0], expected_value);
1133
1134 let parsed = BgpRoleCapability::parse(encoded).unwrap();
1136 assert_eq!(parsed.role, role);
1137 assert_eq!(parsed, capability);
1138 }
1139 }
1140
1141 #[test]
1142 fn test_bgp_role_values() {
1143 use BgpRole::*;
1144
1145 assert_eq!(Provider as u8, 0);
1147 assert_eq!(RouteServer as u8, 1);
1148 assert_eq!(RouteServerClient as u8, 2);
1149 assert_eq!(Customer as u8, 3);
1150 assert_eq!(Peer as u8, 4);
1151
1152 assert_eq!(BgpRole::try_from(0).unwrap(), Provider);
1154 assert_eq!(BgpRole::try_from(1).unwrap(), RouteServer);
1155 assert_eq!(BgpRole::try_from(2).unwrap(), RouteServerClient);
1156 assert_eq!(BgpRole::try_from(3).unwrap(), Customer);
1157 assert_eq!(BgpRole::try_from(4).unwrap(), Peer);
1158
1159 assert!(BgpRole::try_from(5).is_err());
1161 assert!(BgpRole::try_from(255).is_err());
1162 }
1163
1164 #[test]
1165 fn test_bgp_role_capability_invalid_length() {
1166 let invalid_bytes = Bytes::from(vec![0x00, 0x01]); let result = BgpRoleCapability::parse(invalid_bytes);
1169 assert!(result.is_err());
1170
1171 let empty_bytes = Bytes::from(vec![]);
1173 let result = BgpRoleCapability::parse(empty_bytes);
1174 assert!(result.is_err());
1175 }
1176
1177 #[test]
1178 fn test_bgp_role_capability_invalid_value() {
1179 let invalid_bytes = Bytes::from(vec![5]); let result = BgpRoleCapability::parse(invalid_bytes);
1182 assert!(result.is_err());
1183 }
1184
1185 #[test]
1186 fn test_bgp_extended_message_capability() {
1187 let capability = BgpExtendedMessageCapability::new();
1189
1190 let encoded = capability.encode();
1192 assert_eq!(encoded.len(), 0);
1193
1194 let parsed = BgpExtendedMessageCapability::parse(encoded).unwrap();
1196 assert_eq!(parsed, capability);
1197 }
1198
1199 #[test]
1200 fn test_bgp_extended_message_capability_invalid_length() {
1201 let invalid_bytes = Bytes::from(vec![0x01]);
1203 let result = BgpExtendedMessageCapability::parse(invalid_bytes);
1204 assert!(result.is_err());
1205 }
1206}