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