bgpkit_parser/parser/bmp/messages/
route_monitoring.rs1use crate::models::*;
2use crate::parser::bgp::messages::parse_bgp_message;
3use crate::parser::bmp::error::ParserBmpError;
4use crate::parser::bmp::messages::BmpPeerType;
5use bytes::Bytes;
6use log::warn;
7
8#[derive(Debug, PartialEq, Clone)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct RouteMonitoring {
11 pub bgp_message: BgpMessage,
12}
13
14pub fn parse_route_monitoring(
15 data: &mut Bytes,
16 asn_len: &AsnLength,
17 peer_type: Option<&BmpPeerType>,
18) -> Result<RouteMonitoring, ParserBmpError> {
19 if let Some(BmpPeerType::LocalRib) = peer_type {
21 if *asn_len != AsnLength::Bits32 {
22 warn!("RFC 9069 violation: Local RIB route monitoring MUST use 4-byte ASN encoding");
23 }
24 }
25
26 let bgp_update = parse_bgp_message(data, false, asn_len)?;
27 Ok(RouteMonitoring {
28 bgp_message: bgp_update,
29 })
30}
31
32impl RouteMonitoring {
33 pub fn is_end_of_rib(&self) -> bool {
35 if let BgpMessage::Update(u) = &self.bgp_message {
36 u.is_end_of_rib()
37 } else {
38 false
39 }
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn test_end_of_rib() {
49 let msg = BgpUpdateMessage {
50 withdrawn_prefixes: vec![],
51 attributes: Attributes::default(),
52 announced_prefixes: vec![],
53 };
54 assert!(msg.is_end_of_rib());
55
56 let mon_msg = RouteMonitoring {
57 bgp_message: BgpMessage::Update(msg),
58 };
59 assert!(mon_msg.is_end_of_rib());
60
61 let mon_msg = RouteMonitoring {
62 bgp_message: BgpMessage::KeepAlive,
63 };
64 assert!(!mon_msg.is_end_of_rib());
65 }
66
67 #[test]
68 fn test_debug() {
69 let msg = BgpUpdateMessage {
70 withdrawn_prefixes: vec![],
71 attributes: Attributes::default(),
72 announced_prefixes: vec![],
73 };
74 let mon_msg = RouteMonitoring {
75 bgp_message: BgpMessage::Update(msg),
76 };
77 #[cfg(feature = "parser")]
78 let expected = "RouteMonitoring { bgp_message: Update(BgpUpdateMessage { withdrawn_prefixes: [], attributes: Attributes { inner: [], validation_warnings: [] }, announced_prefixes: [] }) }";
79 #[cfg(not(feature = "parser"))]
80 let expected = "RouteMonitoring { bgp_message: Update(BgpUpdateMessage { withdrawn_prefixes: [], attributes: Attributes { inner: [] }, announced_prefixes: [] }) }";
81
82 assert_eq!(format!("{mon_msg:?}"), expected);
83 }
84
85 #[test]
91 fn test_local_rib_with_16bit_asn() {
92 let bgp_update = BgpMessage::Update(BgpUpdateMessage {
97 withdrawn_prefixes: vec![],
98 attributes: Attributes::default(),
99 announced_prefixes: vec![],
100 });
101 let bgp_bytes = bgp_update.encode(AsnLength::Bits16);
102
103 let mut data = bgp_bytes;
104 let asn_len = AsnLength::Bits16; let peer_type = crate::parser::bmp::messages::BmpPeerType::LocalRib;
106
107 let result = parse_route_monitoring(&mut data, &asn_len, Some(&peer_type));
108
109 assert!(result.is_ok(), "Parsing should succeed");
110 }
112
113 #[test]
114 fn test_local_rib_with_32bit_asn() {
115 let bgp_update = BgpMessage::Update(BgpUpdateMessage {
120 withdrawn_prefixes: vec![],
121 attributes: Attributes::default(),
122 announced_prefixes: vec![],
123 });
124 let bgp_bytes = bgp_update.encode(AsnLength::Bits32);
125
126 let mut data = bgp_bytes;
127 let asn_len = AsnLength::Bits32; let peer_type = crate::parser::bmp::messages::BmpPeerType::LocalRib;
129
130 let result = parse_route_monitoring(&mut data, &asn_len, Some(&peer_type));
131
132 assert!(result.is_ok(), "Parsing should succeed");
133 }
135
136 #[test]
137 fn test_non_local_rib_with_16bit_asn() {
138 let bgp_update = BgpMessage::Update(BgpUpdateMessage {
143 withdrawn_prefixes: vec![],
144 attributes: Attributes::default(),
145 announced_prefixes: vec![],
146 });
147 let bgp_bytes = bgp_update.encode(AsnLength::Bits16);
148
149 let mut data = bgp_bytes;
150 let asn_len = AsnLength::Bits16;
151 let peer_type = crate::parser::bmp::messages::BmpPeerType::Global; let result = parse_route_monitoring(&mut data, &asn_len, Some(&peer_type));
154
155 assert!(result.is_ok(), "Parsing should succeed");
156 }
158}