bgpkit_parser/models/mrt/
table_dump_v2.rs1use crate::models::*;
3use bitflags::bitflags;
4use num_enum::{IntoPrimitive, TryFromPrimitive};
5use std::collections::HashMap;
6use std::net::{IpAddr, Ipv4Addr};
7use std::str::FromStr;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12pub enum TableDumpV2Message {
13 PeerIndexTable(PeerIndexTable),
14 RibAfi(RibAfiEntries),
15 RibGeneric(RibGenericEntries),
17}
18
19impl TableDumpV2Message {
20 pub const fn dump_type(&self) -> TableDumpV2Type {
21 match self {
22 TableDumpV2Message::PeerIndexTable(_) => TableDumpV2Type::PeerIndexTable,
23 TableDumpV2Message::RibAfi(x) => x.rib_type,
24 TableDumpV2Message::RibGeneric(_) => TableDumpV2Type::RibGeneric,
25 }
26 }
27}
28
29#[derive(Debug, TryFromPrimitive, IntoPrimitive, Copy, Clone, PartialEq, Eq, Hash)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34#[repr(u16)]
35pub enum TableDumpV2Type {
36 PeerIndexTable = 1,
37 RibIpv4Unicast = 2,
38 RibIpv4Multicast = 3,
39 RibIpv6Unicast = 4,
40 RibIpv6Multicast = 5,
41 RibGeneric = 6,
42 GeoPeerTable = 7,
43 RibIpv4UnicastAddPath = 8,
44 RibIpv4MulticastAddPath = 9,
45 RibIpv6UnicastAddPath = 10,
46 RibIpv6MulticastAddPath = 11,
47 RibGenericAddPath = 12,
48}
49
50#[derive(Debug, Clone, PartialEq, Eq)]
79#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
80pub struct RibAfiEntries {
81 pub rib_type: TableDumpV2Type,
82 pub sequence_number: u32,
83 pub prefix: NetworkPrefix,
84 pub rib_entries: Vec<RibEntry>,
85}
86
87#[derive(Debug, Clone, PartialEq, Eq)]
109#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
110pub struct RibGenericEntries {
111 pub sequence_number: u32,
112 pub afi: Afi,
113 pub safi: Safi,
114 pub nlri: NetworkPrefix,
115 pub rib_entries: Vec<RibEntry>,
116}
117
118#[derive(Debug, Clone, PartialEq, Eq)]
140#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
141pub struct RibEntry {
142 pub peer_index: u16,
143 pub originated_time: u32,
144 pub attributes: Attributes,
145}
146
147#[derive(Debug, Clone, PartialEq, Eq)]
159#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
160pub struct PeerIndexTable {
161 pub collector_bgp_id: BgpIdentifier,
162 pub view_name: String,
163 pub id_peer_map: HashMap<u16, Peer>,
164 pub peer_addr_id_map: HashMap<IpAddr, u16>,
165}
166
167impl Default for PeerIndexTable {
168 fn default() -> Self {
169 PeerIndexTable {
170 collector_bgp_id: Ipv4Addr::from_str("0.0.0.0").unwrap(),
171 view_name: "".to_string(),
172 id_peer_map: HashMap::new(),
173 peer_addr_id_map: HashMap::new(),
174 }
175 }
176}
177
178bitflags! {
179 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
180 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
181 pub struct PeerType: u8 {
182 const AS_SIZE_32BIT = 0x2;
183 const ADDRESS_FAMILY_IPV6 = 0x1;
184 }
185}
186
187#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
189#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
190pub struct Peer {
191 pub peer_type: PeerType,
192 pub peer_bgp_id: BgpIdentifier,
193 pub peer_address: IpAddr,
194 pub peer_asn: Asn,
195}
196
197impl Peer {
198 pub fn new(peer_bgp_id: BgpIdentifier, peer_address: IpAddr, peer_asn: Asn) -> Self {
199 let mut peer_type = PeerType::empty();
200
201 if peer_asn.is_four_byte() {
202 peer_type.insert(PeerType::AS_SIZE_32BIT);
203 }
204
205 if peer_address.is_ipv6() {
206 peer_type.insert(PeerType::ADDRESS_FAMILY_IPV6);
207 }
208
209 Peer {
210 peer_type,
211 peer_bgp_id,
212 peer_address,
213 peer_asn,
214 }
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 use super::*;
221
222 fn create_peer() -> Peer {
224 let bgp_id = Ipv4Addr::from_str("1.1.1.1").unwrap();
225 let peer_address: IpAddr = Ipv4Addr::from_str("2.2.2.2").unwrap().into();
226 let asn = Asn::new_32bit(65000);
228 Peer::new(bgp_id, peer_address, asn)
229 }
230
231 #[test]
232 fn test_peer_new() {
233 let peer = create_peer();
234 assert_eq!(peer.peer_type, PeerType::AS_SIZE_32BIT);
235 assert_eq!(peer.peer_bgp_id, Ipv4Addr::from_str("1.1.1.1").unwrap());
236 assert_eq!(
237 peer.peer_address,
238 IpAddr::V4(Ipv4Addr::from_str("2.2.2.2").unwrap())
239 );
240 assert_eq!(peer.peer_asn, Asn::new_32bit(65000));
241 }
242
243 #[test]
244 fn test_default_peer_index_table() {
245 let peer_index_table = PeerIndexTable::default();
246 assert_eq!(
247 peer_index_table.collector_bgp_id,
248 Ipv4Addr::from_str("0.0.0.0").unwrap()
249 );
250 assert_eq!(peer_index_table.view_name, "".to_string());
251 assert_eq!(peer_index_table.id_peer_map, HashMap::new());
252 assert_eq!(peer_index_table.peer_addr_id_map, HashMap::new());
253 }
254
255 #[test]
256 fn test_peer_type_flags() {
257 let mut peer_type = PeerType::empty();
258 assert_eq!(peer_type, PeerType::empty());
259
260 peer_type.insert(PeerType::AS_SIZE_32BIT);
261 assert_eq!(peer_type, PeerType::AS_SIZE_32BIT);
262
263 peer_type.insert(PeerType::ADDRESS_FAMILY_IPV6);
264 assert_eq!(
265 peer_type,
266 PeerType::AS_SIZE_32BIT | PeerType::ADDRESS_FAMILY_IPV6
267 );
268
269 peer_type.remove(PeerType::AS_SIZE_32BIT);
270 assert_eq!(peer_type, PeerType::ADDRESS_FAMILY_IPV6);
271
272 peer_type.remove(PeerType::ADDRESS_FAMILY_IPV6);
273 assert_eq!(peer_type, PeerType::empty());
274 }
275
276 #[test]
277 fn test_dump_type() {
278 let peer_index_table = TableDumpV2Message::PeerIndexTable(PeerIndexTable::default());
279 assert_eq!(
280 peer_index_table.dump_type(),
281 TableDumpV2Type::PeerIndexTable
282 );
283
284 let rib_afi = TableDumpV2Message::RibAfi(RibAfiEntries {
285 rib_type: TableDumpV2Type::RibIpv4Unicast,
286 sequence_number: 1,
287 prefix: NetworkPrefix::from_str("10.0.0.0/24").unwrap(),
288 rib_entries: vec![],
289 });
290 assert_eq!(rib_afi.dump_type(), TableDumpV2Type::RibIpv4Unicast);
291
292 let rib_generic = TableDumpV2Message::RibGeneric(RibGenericEntries {
293 sequence_number: 1,
294 afi: Afi::Ipv4,
295 safi: Safi::Unicast,
296 nlri: NetworkPrefix::from_str("10.0.0.0/24").unwrap(),
297 rib_entries: vec![],
298 });
299 assert_eq!(rib_generic.dump_type(), TableDumpV2Type::RibGeneric);
300 }
301
302 #[test]
303 #[cfg(feature = "serde")]
304 fn test_serialization() {
305 let peer_index_table = TableDumpV2Message::PeerIndexTable(PeerIndexTable::default());
306 let serialized = serde_json::to_string(&peer_index_table).unwrap();
307 let deserialized: TableDumpV2Message = serde_json::from_str(&serialized).unwrap();
308 assert_eq!(deserialized, peer_index_table);
309
310 let rib_entry = RibEntry {
311 peer_index: 1,
312 originated_time: 1,
313 attributes: Attributes::default(),
314 };
315 let rib_afi = TableDumpV2Message::RibAfi(RibAfiEntries {
316 rib_type: TableDumpV2Type::RibIpv4Unicast,
317 sequence_number: 1,
318 prefix: NetworkPrefix::from_str("10.0.0.0/24").unwrap(),
319 rib_entries: vec![rib_entry],
320 });
321 let serialized = serde_json::to_string(&rib_afi).unwrap();
322 let deserialized: TableDumpV2Message = serde_json::from_str(&serialized).unwrap();
323 assert_eq!(deserialized, rib_afi);
324
325 let rib_generic = TableDumpV2Message::RibGeneric(RibGenericEntries {
326 sequence_number: 1,
327 afi: Afi::Ipv4,
328 safi: Safi::Unicast,
329 nlri: NetworkPrefix::from_str("10.0.0.0/24").unwrap(),
330 rib_entries: vec![],
331 });
332 let serialized = serde_json::to_string(&rib_generic).unwrap();
333 let deserialized: TableDumpV2Message = serde_json::from_str(&serialized).unwrap();
334 assert_eq!(deserialized, rib_generic);
335 }
336}