bgpkit_parser/models/bgp/
mod.rs1pub mod attributes;
4pub mod capabilities;
5pub mod community;
6pub mod elem;
7pub mod error;
8pub mod flowspec;
9pub mod linkstate;
10pub mod role;
11pub mod tunnel_encap;
12
13pub use attributes::*;
14pub use community::*;
15pub use elem::*;
16pub use error::*;
17pub use flowspec::*;
18pub use linkstate::*;
19pub use role::*;
20pub use tunnel_encap::*;
21
22use crate::models::network::*;
23use capabilities::{
24 AddPathCapability, BgpCapabilityType, BgpExtendedMessageCapability, BgpRoleCapability,
25 ExtendedNextHopCapability, FourOctetAsCapability, GracefulRestartCapability,
26 MultiprotocolExtensionsCapability, RouteRefreshCapability,
27};
28use num_enum::{IntoPrimitive, TryFromPrimitive};
29use std::net::Ipv4Addr;
30
31pub type BgpIdentifier = Ipv4Addr;
32
33#[allow(non_camel_case_types)]
34#[derive(Debug, TryFromPrimitive, IntoPrimitive, Copy, Clone, PartialEq, Hash)]
35#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
36#[repr(u8)]
37pub enum BgpMessageType {
38 OPEN = 1,
39 UPDATE = 2,
40 NOTIFICATION = 3,
41 KEEPALIVE = 4,
42 ROUTE_REFRESH = 5,
43}
44
45#[derive(Debug, Clone, PartialEq, Eq)]
47#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
48pub enum BgpMessage {
49 Open(BgpOpenMessage),
50 Update(BgpUpdateMessage),
51 Notification(BgpNotificationMessage),
52 KeepAlive,
53 RouteRefresh(BgpRouteRefreshMessage),
54}
55
56impl BgpMessage {
57 pub const fn msg_type(&self) -> BgpMessageType {
58 match self {
59 BgpMessage::Open(_) => BgpMessageType::OPEN,
60 BgpMessage::Update(_) => BgpMessageType::UPDATE,
61 BgpMessage::Notification(_) => BgpMessageType::NOTIFICATION,
62 BgpMessage::KeepAlive => BgpMessageType::KEEPALIVE,
63 BgpMessage::RouteRefresh(_) => BgpMessageType::ROUTE_REFRESH,
64 }
65 }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq)]
81#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
82pub struct BgpRouteRefreshMessage {
83 pub afi: u16,
84 pub subtype: u8,
87 pub safi: u8,
88 pub data: Vec<u8>,
90}
91
92impl BgpRouteRefreshMessage {
93 pub fn afi(&self) -> Option<Afi> {
95 Afi::try_from(self.afi).ok()
96 }
97
98 pub fn safi(&self) -> Option<Safi> {
100 Safi::try_from(self.safi).ok()
101 }
102
103 pub fn validation_warnings(&self) -> Vec<crate::error::BgpValidationWarning> {
112 use crate::error::BgpValidationWarning;
113 let mut warnings = Vec::new();
114 match self.subtype {
115 0 => {}
116 1 | 2 => {
117 if !self.data.is_empty() {
118 warnings.push(BgpValidationWarning::InvalidRouteRefreshLength {
119 subtype: self.subtype,
120 length: 4 + self.data.len(),
121 });
122 }
123 }
124 subtype => {
125 warnings.push(BgpValidationWarning::UnknownRouteRefreshSubtype { subtype });
126 }
127 }
128 warnings
129 }
130}
131
132#[derive(Debug, Clone, PartialEq, Eq)]
154#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
155pub struct BgpOpenMessage {
156 pub version: u8,
157 pub asn: Asn,
158 pub hold_time: u16,
159 pub bgp_identifier: BgpIdentifier,
160 pub extended_length: bool,
161 pub opt_params: Vec<OptParam>,
162}
163
164#[derive(Debug, Clone, PartialEq, Eq)]
165#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
166pub struct OptParam {
167 pub param_type: u8,
168 pub param_value: ParamValue,
169}
170
171#[derive(Debug, Clone, PartialEq, Eq)]
172#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
173pub enum ParamValue {
174 Raw(Vec<u8>),
175 Capacities(Vec<Capability>),
176}
177
178#[derive(Debug, Clone, PartialEq, Eq)]
183#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
184pub struct Capability {
185 pub ty: BgpCapabilityType,
186 pub value: CapabilityValue,
187}
188
189#[derive(Debug, Clone, PartialEq, Eq)]
191#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
192pub enum CapabilityValue {
193 Raw(Vec<u8>),
195 MultiprotocolExtensions(MultiprotocolExtensionsCapability),
197 RouteRefresh(RouteRefreshCapability),
199 ExtendedNextHop(ExtendedNextHopCapability),
201 GracefulRestart(GracefulRestartCapability),
203 FourOctetAs(FourOctetAsCapability),
205 AddPath(AddPathCapability),
207 BgpRole(BgpRoleCapability),
209 BgpExtendedMessage(BgpExtendedMessageCapability),
211}
212
213#[derive(Debug, Clone, PartialEq, Default, Eq)]
214#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
215pub struct BgpUpdateMessage {
219 pub withdrawn_prefixes: Vec<NetworkPrefix>,
233
234 pub attributes: Attributes,
236
237 pub announced_prefixes: Vec<NetworkPrefix>,
252}
253
254#[derive(Debug, Clone, PartialEq, Eq)]
255#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
256pub struct BgpNotificationMessage {
257 pub error: BgpError,
258 pub data: Vec<u8>,
259}
260
261#[cfg(test)]
262mod tests {
263 use super::*;
264 use crate::error::BgpValidationWarning;
265
266 fn route_refresh(subtype: u8, data: Vec<u8>) -> BgpRouteRefreshMessage {
267 BgpRouteRefreshMessage {
268 afi: 1,
269 subtype,
270 safi: 1,
271 data,
272 }
273 }
274
275 #[test]
276 fn test_route_refresh_validation_warnings() {
277 assert!(route_refresh(0, vec![]).validation_warnings().is_empty());
279 assert!(route_refresh(0, vec![0x01])
280 .validation_warnings()
281 .is_empty());
282
283 assert!(route_refresh(1, vec![]).validation_warnings().is_empty());
285 assert!(route_refresh(2, vec![]).validation_warnings().is_empty());
286
287 assert_eq!(
289 route_refresh(2, vec![0xDE, 0xAD, 0xBE]).validation_warnings(),
290 vec![BgpValidationWarning::InvalidRouteRefreshLength {
291 subtype: 2,
292 length: 7
293 }]
294 );
295
296 assert_eq!(
298 route_refresh(3, vec![]).validation_warnings(),
299 vec![BgpValidationWarning::UnknownRouteRefreshSubtype { subtype: 3 }]
300 );
301 }
302
303 #[test]
304 fn test_message_type() {
305 let open = BgpMessage::Open(BgpOpenMessage {
306 version: 4,
307 asn: Asn::new_32bit(1),
308 hold_time: 180,
309 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
310 extended_length: false,
311 opt_params: vec![],
312 });
313 assert_eq!(open.msg_type(), BgpMessageType::OPEN);
314
315 let update = BgpMessage::Update(BgpUpdateMessage::default());
316 assert_eq!(update.msg_type(), BgpMessageType::UPDATE);
317
318 let notification = BgpMessage::Notification(BgpNotificationMessage {
319 error: BgpError::Unknown(0, 0),
320 data: vec![],
321 });
322 assert_eq!(notification.msg_type(), BgpMessageType::NOTIFICATION);
323
324 let keepalive = BgpMessage::KeepAlive;
325 assert_eq!(keepalive.msg_type(), BgpMessageType::KEEPALIVE);
326 }
327
328 #[test]
329 #[cfg(feature = "serde")]
330 fn test_serde() {
331 let open = BgpMessage::Open(BgpOpenMessage {
332 version: 4,
333 asn: Asn::new_32bit(1),
334 hold_time: 180,
335 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
336 extended_length: false,
337 opt_params: vec![],
338 });
339 let serialized = serde_json::to_string(&open).unwrap();
340 let deserialized: BgpMessage = serde_json::from_str(&serialized).unwrap();
341 assert_eq!(open, deserialized);
342
343 let update = BgpMessage::Update(BgpUpdateMessage::default());
344 let serialized = serde_json::to_string(&update).unwrap();
345 let deserialized: BgpMessage = serde_json::from_str(&serialized).unwrap();
346 assert_eq!(update, deserialized);
347
348 let notification = BgpMessage::Notification(BgpNotificationMessage {
349 error: BgpError::Unknown(0, 0),
350 data: vec![],
351 });
352 let serialized = serde_json::to_string(¬ification).unwrap();
353 let deserialized: BgpMessage = serde_json::from_str(&serialized).unwrap();
354 assert_eq!(notification, deserialized);
355
356 let keepalive = BgpMessage::KeepAlive;
357 let serialized = serde_json::to_string(&keepalive).unwrap();
358 let deserialized: BgpMessage = serde_json::from_str(&serialized).unwrap();
359 assert_eq!(keepalive, deserialized);
360 }
361}