bgp_models/bgp/
capabilities.rs1use num_traits::FromPrimitive;
2use serde::Serialize;
3use std::error::Error;
4use std::fmt::{Display, Formatter};
5
6#[derive(Debug, PartialEq, Eq, Clone, Serialize)]
8pub enum BgpCapabilityParsingError {
9 Unassigned(u8),
10 DeprecatedCode(u8),
11 ReservedCode(u8),
12 ReservedExperimentalCode(u8),
13}
14
15impl Display for BgpCapabilityParsingError {
16 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
17 match self {
18 BgpCapabilityParsingError::Unassigned(v) => {
19 write!(f, "unassigned BGP capability code: {}", v)
20 }
21 BgpCapabilityParsingError::DeprecatedCode(v) => {
22 write!(f, "deprecated BGP capability code: {}", v)
23 }
24 BgpCapabilityParsingError::ReservedCode(v) => {
25 write!(f, "reserved BGP capability code: {}", v)
26 }
27 BgpCapabilityParsingError::ReservedExperimentalCode(v) => {
28 write!(
29 f,
30 "reserved BGP capability code for experimental use: {}",
31 v
32 )
33 }
34 }
35 }
36}
37
38impl Error for BgpCapabilityParsingError {}
39
40#[allow(non_camel_case_types)]
41#[derive(Debug, Primitive, PartialEq, Eq, Hash, Copy, Clone, Serialize)]
42pub enum BgpCapabilityType {
43 MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4 = 1,
44 ROUTE_REFRESH_CAPABILITY_FOR_BGP_4 = 2,
45 OUTBOUND_ROUTE_FILTERING_CAPABILITY = 3,
46 EXTENDED_NEXT_HOP_ENCODING = 5,
47 BGP_EXTENDED_MESSAGE = 6,
48 BGPSEC_CAPABILITY = 7,
49 MULTIPLE_LABELS_CAPABILITY = 8,
50 BGP_ROLE = 9,
51 GRACEFUL_RESTART_CAPABILITY = 64,
52 SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY = 65,
53 SUPPORT_FOR_DYNAMIC_CAPABILITY = 67,
54 MULTISESSION_BGP_CAPABILITY = 68,
55 ADD_PATH_CAPABILITY = 69,
56 ENHANCED_ROUTE_REFRESH_CAPABILITY = 70,
57 LONG_LIVED_GRACEFUL_RESTART_CAPABILITY = 71,
58 ROUTING_POLICY_DISTRIBUTION = 72,
59 FQDN_CAPABILITY = 73,
60}
61
62pub fn parse_capability(
63 capability_code: &u8,
64) -> Result<BgpCapabilityType, BgpCapabilityParsingError> {
65 match BgpCapabilityType::from_u8(*capability_code) {
66 Some(v) => Ok(v),
67 None => {
68 if [4, 66, 128, 129, 130, 131, 184, 185].contains(capability_code) {
69 Err(BgpCapabilityParsingError::DeprecatedCode(*capability_code))
70 } else if *capability_code == 0 || *capability_code == 255 {
71 Err(BgpCapabilityParsingError::ReservedCode(*capability_code))
72 } else if *capability_code >= 239 && *capability_code <= 254 {
73 Err(BgpCapabilityParsingError::ReservedExperimentalCode(
74 *capability_code,
75 ))
76 } else {
77 Err(BgpCapabilityParsingError::Unassigned(*capability_code))
78 }
79 }
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn test_parsing_capability() {
89 let mut code;
90
91 code = 0;
93 assert_eq!(
94 parse_capability(&code),
95 Err(BgpCapabilityParsingError::ReservedCode(code))
96 );
97 code = 255;
98 assert_eq!(
99 parse_capability(&code),
100 Err(BgpCapabilityParsingError::ReservedCode(code))
101 );
102
103 for code in [4, 66, 128, 129, 130, 131, 184, 185] {
105 assert_eq!(
106 parse_capability(&code),
107 Err(BgpCapabilityParsingError::DeprecatedCode(code))
108 );
109 }
110
111 for code in 10..=63 {
113 assert_eq!(
114 parse_capability(&code),
115 Err(BgpCapabilityParsingError::Unassigned(code))
116 );
117 }
118 for code in 74..=127 {
119 assert_eq!(
120 parse_capability(&code),
121 Err(BgpCapabilityParsingError::Unassigned(code))
122 );
123 }
124 for code in 132..=183 {
125 assert_eq!(
126 parse_capability(&code),
127 Err(BgpCapabilityParsingError::Unassigned(code))
128 );
129 }
130 for code in 186..=238 {
131 assert_eq!(
132 parse_capability(&code),
133 Err(BgpCapabilityParsingError::Unassigned(code))
134 );
135 }
136
137 code = 1;
139 assert_eq!(
140 parse_capability(&code),
141 Ok(BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4)
142 );
143 code = 2;
144 assert_eq!(
145 parse_capability(&code),
146 Ok(BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4)
147 );
148 code = 3;
149 assert_eq!(
150 parse_capability(&code),
151 Ok(BgpCapabilityType::OUTBOUND_ROUTE_FILTERING_CAPABILITY)
152 );
153 code = 5;
154 assert_eq!(
155 parse_capability(&code),
156 Ok(BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING)
157 );
158 code = 6;
159 assert_eq!(
160 parse_capability(&code),
161 Ok(BgpCapabilityType::BGP_EXTENDED_MESSAGE)
162 );
163 code = 7;
164 assert_eq!(
165 parse_capability(&code),
166 Ok(BgpCapabilityType::BGPSEC_CAPABILITY)
167 );
168 code = 8;
169 assert_eq!(
170 parse_capability(&code),
171 Ok(BgpCapabilityType::MULTIPLE_LABELS_CAPABILITY)
172 );
173 code = 9;
174 assert_eq!(parse_capability(&code), Ok(BgpCapabilityType::BGP_ROLE));
175
176 code = 64;
177 assert_eq!(
178 parse_capability(&code),
179 Ok(BgpCapabilityType::GRACEFUL_RESTART_CAPABILITY)
180 );
181 code = 65;
182 assert_eq!(
183 parse_capability(&code),
184 Ok(BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY)
185 );
186 code = 67;
187 assert_eq!(
188 parse_capability(&code),
189 Ok(BgpCapabilityType::SUPPORT_FOR_DYNAMIC_CAPABILITY)
190 );
191 code = 68;
192 assert_eq!(
193 parse_capability(&code),
194 Ok(BgpCapabilityType::MULTISESSION_BGP_CAPABILITY)
195 );
196 code = 69;
197 assert_eq!(
198 parse_capability(&code),
199 Ok(BgpCapabilityType::ADD_PATH_CAPABILITY)
200 );
201 code = 70;
202 assert_eq!(
203 parse_capability(&code),
204 Ok(BgpCapabilityType::ENHANCED_ROUTE_REFRESH_CAPABILITY)
205 );
206 code = 71;
207 assert_eq!(
208 parse_capability(&code),
209 Ok(BgpCapabilityType::LONG_LIVED_GRACEFUL_RESTART_CAPABILITY)
210 );
211 code = 72;
212 assert_eq!(
213 parse_capability(&code),
214 Ok(BgpCapabilityType::ROUTING_POLICY_DISTRIBUTION)
215 );
216 code = 73;
217 assert_eq!(
218 parse_capability(&code),
219 Ok(BgpCapabilityType::FQDN_CAPABILITY)
220 );
221 }
222}