bgpkit_parser/models/mrt/
bgp4mp.rs1use crate::models::*;
3use num_enum::{IntoPrimitive, TryFromPrimitive};
4use std::net::IpAddr;
5
6#[derive(Debug, TryFromPrimitive, IntoPrimitive, Copy, Clone, PartialEq, Eq, Hash)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[repr(u16)]
10pub enum BgpState {
11 Idle = 1,
12 Connect = 2,
13 Active = 3,
14 OpenSent = 4,
15 OpenConfirm = 5,
16 Established = 6,
17}
18
19#[derive(Debug, Clone, PartialEq, Eq)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22pub enum Bgp4MpEnum {
23 StateChange(Bgp4MpStateChange),
24 Message(Bgp4MpMessage),
25}
26
27impl Bgp4MpEnum {
28 pub const fn msg_type(&self) -> Bgp4MpType {
29 match self {
30 Bgp4MpEnum::StateChange(x) => x.msg_type,
31 Bgp4MpEnum::Message(x) => x.msg_type,
32 }
33 }
34}
35
36#[derive(Debug, TryFromPrimitive, IntoPrimitive, Copy, Clone, PartialEq, Eq, Hash)]
38#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
39#[repr(u16)]
40pub enum Bgp4MpType {
41 StateChange = 0,
42 Message = 1,
43 MessageAs4 = 4,
44 StateChangeAs4 = 5,
45 MessageLocal = 6,
46 MessageAs4Local = 7,
47 MessageAddpath = 8,
48 MessageAs4Addpath = 9,
49 MessageLocalAddpath = 10,
50 MessageLocalAs4Addpath = 11,
51}
52
53#[derive(Debug, Clone, PartialEq, Eq)]
55#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
56pub struct Bgp4MpStateChange {
57 pub msg_type: Bgp4MpType,
58 pub peer_asn: Asn,
59 pub local_asn: Asn,
60 pub interface_index: u16,
61 pub peer_ip: IpAddr,
62 pub local_addr: IpAddr,
63 pub old_state: BgpState,
64 pub new_state: BgpState,
65}
66
67#[derive(Debug, Clone, PartialEq, Eq)]
69#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
70pub struct Bgp4MpMessage {
71 pub msg_type: Bgp4MpType,
72 pub peer_asn: Asn,
73 pub local_asn: Asn,
74 pub interface_index: u16,
75 pub peer_ip: IpAddr,
76 pub local_ip: IpAddr,
77 pub bgp_message: BgpMessage,
78}
79
80impl Bgp4MpMessage {
81 pub const fn is_local(&self) -> bool {
82 matches!(
83 self.msg_type,
84 Bgp4MpType::MessageLocal
85 | Bgp4MpType::MessageAs4Local
86 | Bgp4MpType::MessageLocalAddpath
87 | Bgp4MpType::MessageLocalAs4Addpath
88 )
89 }
90}
91
92pub const fn address_family(ip: &IpAddr) -> u16 {
93 match ip {
94 IpAddr::V4(_) => 1,
95 IpAddr::V6(_) => 2,
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102 use std::str::FromStr;
103
104 #[test]
105 fn test_msg_type() {
106 let state_change = Bgp4MpEnum::StateChange(Bgp4MpStateChange {
107 msg_type: Bgp4MpType::StateChange,
108 peer_asn: Asn::new_32bit(0),
109 local_asn: Asn::new_32bit(0),
110 interface_index: 1,
111 peer_ip: IpAddr::from_str("10.0.0.0").unwrap(),
112 local_addr: IpAddr::from_str("10.0.0.1").unwrap(),
113 old_state: BgpState::Idle,
114 new_state: BgpState::Connect,
115 });
116 assert_eq!(state_change.msg_type(), Bgp4MpType::StateChange);
117
118 let message = Bgp4MpEnum::Message(Bgp4MpMessage {
119 msg_type: Bgp4MpType::Message,
120 peer_asn: Asn::new_32bit(0),
121 local_asn: Asn::new_32bit(0),
122 interface_index: 1,
123 peer_ip: IpAddr::from_str("10.0.0.0").unwrap(),
124 local_ip: IpAddr::from_str("10.0.0.1").unwrap(),
125 bgp_message: BgpMessage::Update(Default::default()),
126 });
127 assert_eq!(message.msg_type(), Bgp4MpType::Message);
128 }
129
130 #[test]
131 fn test_is_local() {
132 let mut message = Bgp4MpMessage {
133 msg_type: Bgp4MpType::Message,
134 peer_asn: Asn::new_32bit(0),
135 local_asn: Asn::new_32bit(0),
136 interface_index: 1,
137 peer_ip: IpAddr::from_str("10.0.0.0").unwrap(),
138 local_ip: IpAddr::from_str("10.0.0.1").unwrap(),
139 bgp_message: BgpMessage::Update(Default::default()),
140 };
141 assert!(!message.is_local());
142
143 message.msg_type = Bgp4MpType::MessageLocal;
144 assert!(message.is_local());
145
146 message.msg_type = Bgp4MpType::MessageAs4Local;
147 assert!(message.is_local());
148
149 message.msg_type = Bgp4MpType::MessageLocalAddpath;
150 assert!(message.is_local());
151
152 message.msg_type = Bgp4MpType::MessageLocalAs4Addpath;
153 assert!(message.is_local());
154
155 message.msg_type = Bgp4MpType::MessageAs4;
156 assert!(!message.is_local());
157 }
158
159 #[test]
160 #[cfg(feature = "serde")]
161 fn test_serialization() {
162 let state_change = Bgp4MpEnum::StateChange(Bgp4MpStateChange {
163 msg_type: Bgp4MpType::StateChange,
164 peer_asn: Asn::new_32bit(0),
165 local_asn: Asn::new_32bit(0),
166 interface_index: 1,
167 peer_ip: IpAddr::from_str("10.0.0.0").unwrap(),
168 local_addr: IpAddr::from_str("10.0.0.1").unwrap(),
169 old_state: BgpState::Idle,
170 new_state: BgpState::Connect,
171 });
172 let serialized = serde_json::to_string(&state_change).unwrap();
173 let deserialized: Bgp4MpEnum = serde_json::from_str(&serialized).unwrap();
174 assert_eq!(deserialized, state_change);
175
176 let message = Bgp4MpEnum::Message(Bgp4MpMessage {
177 msg_type: Bgp4MpType::Message,
178 peer_asn: Asn::new_32bit(0),
179 local_asn: Asn::new_32bit(0),
180 interface_index: 1,
181 peer_ip: IpAddr::from_str("10.0.0.0").unwrap(),
182 local_ip: IpAddr::from_str("10.0.0.1").unwrap(),
183 bgp_message: BgpMessage::Update(Default::default()),
184 });
185 let serialized = serde_json::to_string(&message).unwrap();
186 let deserialized: Bgp4MpEnum = serde_json::from_str(&serialized).unwrap();
187 assert_eq!(deserialized, message);
188 }
189}