bgpkit_parser/parser/bmp/messages/
peer_down_notification.rs1use crate::parser::bmp::error::ParserBmpError;
2use crate::parser::ReadUtils;
3use bytes::{Buf, Bytes};
4use num_enum::{IntoPrimitive, TryFromPrimitive};
5
6#[derive(Debug, PartialEq, Clone)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub struct PeerDownNotification {
9 pub reason: PeerDownReason,
10 pub data: Option<Vec<u8>>,
11}
12
13#[derive(Debug, TryFromPrimitive, IntoPrimitive, PartialEq, Clone, Copy)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15#[repr(u8)]
16pub enum PeerDownReason {
17 Reserved = 0,
18 LocalSystemClosedNotificationPduFollows = 1,
19 LocalSystemClosedFsmEvenFollows = 2,
20 RemoteSystemClosedNotificationPduFollows = 3,
21 RemoteSystemsClosedNoData,
22 PeerDeConfigured = 5,
23 LocalSystemClosedTlvDataFollows = 6,
24}
25
26pub fn parse_peer_down_notification(
27 data: &mut Bytes,
28) -> Result<PeerDownNotification, ParserBmpError> {
29 let reason = PeerDownReason::try_from(data.read_u8()?)?;
30 let bytes_left = data.remaining();
31 let data: Option<Vec<u8>> = match reason {
32 PeerDownReason::Reserved => match bytes_left {
33 0 => None,
34 _ => Some(data.read_n_bytes(bytes_left)?),
35 },
36 PeerDownReason::LocalSystemClosedNotificationPduFollows => {
37 Some(data.read_n_bytes(bytes_left)?)
43 }
44 PeerDownReason::LocalSystemClosedFsmEvenFollows => {
45 Some(data.read_n_bytes(bytes_left)?)
54 }
55 PeerDownReason::RemoteSystemClosedNotificationPduFollows => {
56 Some(data.read_n_bytes(bytes_left)?)
62 }
63 PeerDownReason::RemoteSystemsClosedNoData => {
64 None
71 }
72 PeerDownReason::PeerDeConfigured => {
73 None
81 }
82 PeerDownReason::LocalSystemClosedTlvDataFollows => {
83 Some(data.read_n_bytes(bytes_left)?)
89 }
90 };
91 Ok(PeerDownNotification { reason, data })
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97 use bytes::BufMut;
98
99 #[test]
100 fn test_parse_peer_down_notification() {
101 let mut data = bytes::BytesMut::new();
103 data.put_u8(1);
104 data.put_slice(&[0u8; 10]);
105 let mut data = data.freeze();
106 let result = parse_peer_down_notification(&mut data);
107 assert!(result.is_ok());
108 let peer_down_notification = result.unwrap();
109 assert_eq!(
110 peer_down_notification.reason,
111 PeerDownReason::LocalSystemClosedNotificationPduFollows
112 );
113 assert_eq!(peer_down_notification.data.unwrap(), vec![0u8; 10]);
114
115 let mut data = bytes::BytesMut::new();
117 data.put_u8(2);
118 data.put_slice(&[0u8; 10]);
119 let mut data = data.freeze();
120 let result = parse_peer_down_notification(&mut data);
121 assert!(result.is_ok());
122 let peer_down_notification = result.unwrap();
123 assert_eq!(
124 peer_down_notification.reason,
125 PeerDownReason::LocalSystemClosedFsmEvenFollows
126 );
127 assert_eq!(peer_down_notification.data.unwrap(), vec![0u8; 10]);
128
129 let mut data = bytes::BytesMut::new();
131 data.put_u8(3);
132 data.put_slice(&[0u8; 10]);
133 let mut data = data.freeze();
134 let result = parse_peer_down_notification(&mut data);
135 assert!(result.is_ok());
136 let peer_down_notification = result.unwrap();
137 assert_eq!(
138 peer_down_notification.reason,
139 PeerDownReason::RemoteSystemClosedNotificationPduFollows
140 );
141 assert_eq!(peer_down_notification.data.unwrap(), vec![0u8; 10]);
142
143 let mut data = bytes::BytesMut::new();
145 data.put_u8(4);
146 let mut data = data.freeze();
147 let result = parse_peer_down_notification(&mut data);
148 assert!(result.is_ok());
149 let peer_down_notification = result.unwrap();
150 assert_eq!(
151 peer_down_notification.reason,
152 PeerDownReason::RemoteSystemsClosedNoData
153 );
154 assert!(peer_down_notification.data.is_none());
155
156 let mut data = bytes::BytesMut::new();
158 data.put_u8(5);
159 let mut data = data.freeze();
160 let result = parse_peer_down_notification(&mut data);
161 assert!(result.is_ok());
162 let peer_down_notification = result.unwrap();
163 assert_eq!(
164 peer_down_notification.reason,
165 PeerDownReason::PeerDeConfigured
166 );
167 assert!(peer_down_notification.data.is_none());
168
169 let mut data = bytes::BytesMut::new();
171 data.put_u8(6);
172 data.put_slice(&[0u8; 10]);
173 let mut data = data.freeze();
174 let result = parse_peer_down_notification(&mut data);
175 assert!(result.is_ok());
176 let peer_down_notification = result.unwrap();
177 assert_eq!(
178 peer_down_notification.reason,
179 PeerDownReason::LocalSystemClosedTlvDataFollows
180 );
181 assert_eq!(peer_down_notification.data.unwrap(), vec![0u8; 10]);
182
183 let mut data = bytes::BytesMut::new();
185 data.put_u8(7);
186 let mut data = data.freeze();
187 let result = parse_peer_down_notification(&mut data);
188 assert!(result.is_err());
189 }
190}