bgpkit_parser/models/bgp/
capabilities.rs1use num_enum::{FromPrimitive, IntoPrimitive};
2
3#[allow(non_camel_case_types)]
4#[derive(Debug, FromPrimitive, IntoPrimitive, PartialEq, Eq, Hash, Copy, Clone)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6#[repr(u8)]
7pub enum BgpCapabilityType {
8 MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4 = 1,
9 ROUTE_REFRESH_CAPABILITY_FOR_BGP_4 = 2,
10 OUTBOUND_ROUTE_FILTERING_CAPABILITY = 3,
11 EXTENDED_NEXT_HOP_ENCODING = 5,
12 BGP_EXTENDED_MESSAGE = 6,
13 BGPSEC_CAPABILITY = 7,
14 MULTIPLE_LABELS_CAPABILITY = 8,
15 BGP_ROLE = 9,
16 GRACEFUL_RESTART_CAPABILITY = 64,
17 SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY = 65,
18 SUPPORT_FOR_DYNAMIC_CAPABILITY = 67,
19 MULTISESSION_BGP_CAPABILITY = 68,
20 ADD_PATH_CAPABILITY = 69,
21 ENHANCED_ROUTE_REFRESH_CAPABILITY = 70,
22 LONG_LIVED_GRACEFUL_RESTART_CAPABILITY = 71,
23 ROUTING_POLICY_DISTRIBUTION = 72,
24 FQDN_CAPABILITY = 73,
25
26 #[num_enum(catch_all)]
28 Unknown(u8),
29}
30
31impl BgpCapabilityType {
32 pub const fn is_deprecated(&self) -> bool {
33 matches!(
34 self,
35 BgpCapabilityType::Unknown(4 | 66 | 128 | 129 | 130 | 131 | 184 | 185)
36 )
37 }
38
39 pub const fn is_reserved(&self) -> bool {
40 matches!(self, BgpCapabilityType::Unknown(0 | 255))
41 }
42
43 pub const fn is_reserved_for_experimental_use(&self) -> bool {
44 matches!(self, BgpCapabilityType::Unknown(239..=254))
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn test_parsing_capability() {
54 assert!(BgpCapabilityType::from(0).is_reserved());
56 assert!(BgpCapabilityType::from(255).is_reserved());
57
58 for code in [4, 66, 128, 129, 130, 131, 184, 185] {
60 assert!(BgpCapabilityType::from(code).is_deprecated());
61 }
62
63 let unassigned_ranges = [10..=63, 74..=127, 132..=183, 186..=238];
65 for code in <[_; 4]>::into_iter(unassigned_ranges).flatten() {
66 let ty = BgpCapabilityType::from(code);
67 assert_eq!(ty, BgpCapabilityType::Unknown(code));
68 assert!(!ty.is_deprecated() && !ty.is_reserved());
69 }
70
71 assert_eq!(
73 BgpCapabilityType::from(1),
74 BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4
75 );
76 assert_eq!(
77 BgpCapabilityType::from(2),
78 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4
79 );
80 assert_eq!(
81 BgpCapabilityType::from(3),
82 BgpCapabilityType::OUTBOUND_ROUTE_FILTERING_CAPABILITY
83 );
84 assert_eq!(
85 BgpCapabilityType::from(5),
86 BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING
87 );
88 assert_eq!(
89 BgpCapabilityType::from(6),
90 BgpCapabilityType::BGP_EXTENDED_MESSAGE
91 );
92 assert_eq!(
93 BgpCapabilityType::from(7),
94 BgpCapabilityType::BGPSEC_CAPABILITY
95 );
96 assert_eq!(
97 BgpCapabilityType::from(8),
98 BgpCapabilityType::MULTIPLE_LABELS_CAPABILITY
99 );
100 assert_eq!(BgpCapabilityType::from(9), BgpCapabilityType::BGP_ROLE);
101
102 assert_eq!(
103 BgpCapabilityType::from(64),
104 BgpCapabilityType::GRACEFUL_RESTART_CAPABILITY
105 );
106 assert_eq!(
107 BgpCapabilityType::from(65),
108 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
109 );
110 assert_eq!(
111 BgpCapabilityType::from(67),
112 BgpCapabilityType::SUPPORT_FOR_DYNAMIC_CAPABILITY
113 );
114 assert_eq!(
115 BgpCapabilityType::from(68),
116 BgpCapabilityType::MULTISESSION_BGP_CAPABILITY
117 );
118 assert_eq!(
119 BgpCapabilityType::from(69),
120 BgpCapabilityType::ADD_PATH_CAPABILITY
121 );
122 assert_eq!(
123 BgpCapabilityType::from(70),
124 BgpCapabilityType::ENHANCED_ROUTE_REFRESH_CAPABILITY
125 );
126 assert_eq!(
127 BgpCapabilityType::from(71),
128 BgpCapabilityType::LONG_LIVED_GRACEFUL_RESTART_CAPABILITY
129 );
130 assert_eq!(
131 BgpCapabilityType::from(72),
132 BgpCapabilityType::ROUTING_POLICY_DISTRIBUTION
133 );
134 assert_eq!(
135 BgpCapabilityType::from(73),
136 BgpCapabilityType::FQDN_CAPABILITY
137 );
138 }
139
140 #[test]
141 fn test_reserved_for_experimental() {
142 let experimental_ranges = [239..=254];
143 for code in <[_; 1]>::into_iter(experimental_ranges).flatten() {
144 let ty = BgpCapabilityType::from(code);
145 assert_eq!(ty, BgpCapabilityType::Unknown(code));
146 assert!(ty.is_reserved_for_experimental_use());
147 }
148 }
149
150 #[test]
151 #[cfg(feature = "serde")]
152 fn test_serde() {
153 let ty = BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4;
154 let serialized = serde_json::to_string(&ty).unwrap();
155 let deserialized: BgpCapabilityType = serde_json::from_str(&serialized).unwrap();
156 assert_eq!(ty, deserialized);
157 }
158}