bgpkit_parser/parser/bmp/messages/
route_mirroring.rs

1use crate::bgp::parse_bgp_message;
2use crate::models::*;
3use crate::parser::bmp::error::ParserBmpError;
4use crate::parser::ReadUtils;
5use bytes::{Buf, Bytes};
6use num_enum::{IntoPrimitive, TryFromPrimitive};
7use std::convert::TryFrom;
8
9#[derive(Debug, PartialEq, Clone)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct RouteMirroring {
12    pub tlvs: Vec<RouteMirroringTlv>,
13}
14
15#[derive(Debug, PartialEq, Clone)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17pub struct RouteMirroringTlv {
18    pub info_len: u16,
19    pub value: RouteMirroringValue,
20}
21
22#[derive(Debug, PartialEq, Clone)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub enum RouteMirroringValue {
25    BgpMessage(BgpMessage),
26    Information(RouteMirroringInfo),
27}
28
29#[derive(Debug, TryFromPrimitive, IntoPrimitive, PartialEq, Clone, Copy)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31#[repr(u16)]
32pub enum RouteMirroringInfo {
33    ErroredPdu = 0,
34    MessageLost = 1,
35}
36
37pub fn parse_route_mirroring(
38    data: &mut Bytes,
39    asn_len: &AsnLength,
40) -> Result<RouteMirroring, ParserBmpError> {
41    let mut tlvs = vec![];
42    while data.remaining() > 4 {
43        match data.read_u16()? {
44            0 => {
45                let info_len = data.read_u16()?;
46                data.has_n_remaining(info_len as usize)?;
47                let mut bytes = data.split_to(info_len as usize);
48                let value = parse_bgp_message(&mut bytes, false, asn_len)?;
49                tlvs.push(RouteMirroringTlv {
50                    info_len,
51                    value: RouteMirroringValue::BgpMessage(value),
52                });
53            }
54            1 => {
55                let info_len = data.read_u16()?;
56                let value = RouteMirroringInfo::try_from(data.read_u16()?)?;
57                tlvs.push(RouteMirroringTlv {
58                    info_len,
59                    value: RouteMirroringValue::Information(value),
60                });
61            }
62            _ => return Err(ParserBmpError::CorruptedBmpMessage),
63        }
64    }
65    Ok(RouteMirroring { tlvs })
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71    use bytes::{BufMut, BytesMut};
72    use std::net::Ipv4Addr;
73
74    #[test]
75    fn test_route_mirroring_bgp_messsage() {
76        let bgp_message = BgpMessage::Open(BgpOpenMessage {
77            version: 4,
78            asn: Asn::new_32bit(1),
79            hold_time: 180,
80            sender_ip: Ipv4Addr::new(192, 0, 2, 1),
81            extended_length: false,
82            opt_params: vec![],
83        });
84        let bgp_message_bytes = bgp_message.encode(false, AsnLength::Bits32);
85        let expected_asn_len = AsnLength::Bits32;
86        let actual_info_len = bgp_message_bytes.len() as u16;
87
88        let mut message = BytesMut::new();
89        message.put_u16(0);
90        message.put_u16(actual_info_len);
91        message.put_slice(&bgp_message_bytes);
92        let mut data = message.freeze();
93        let result = parse_route_mirroring(&mut data, &expected_asn_len);
94
95        match result {
96            Ok(route_mirroring) => {
97                assert_eq!(route_mirroring.tlvs.len(), 1);
98                let tlv = &route_mirroring.tlvs[0];
99                assert_eq!(tlv.info_len, actual_info_len);
100            }
101            Err(_) => panic!("Error parsing route mirroring"),
102        }
103    }
104
105    #[test]
106    fn route_mirroring_information() {
107        let mut message = BytesMut::new();
108        message.put_u16(1);
109        message.put_u16(2);
110        message.put_u16(0);
111        let mut data = message.freeze();
112        let result = parse_route_mirroring(&mut data, &AsnLength::Bits32).unwrap();
113        assert_eq!(result.tlvs.len(), 1);
114        let tlv = &result.tlvs[0];
115        assert_eq!(tlv.info_len, 2);
116        match &tlv.value {
117            RouteMirroringValue::Information(info) => {
118                assert_eq!(info, &RouteMirroringInfo::ErroredPdu)
119            }
120            _ => panic!("Expected RouteMirroringValue::Information"),
121        }
122    }
123}