bgpkit_parser/parser/bmp/messages/
route_mirroring.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::bgp::parse_bgp_message;
use crate::models::*;
use crate::parser::bmp::error::ParserBmpError;
use crate::parser::ReadUtils;
use bytes::{Buf, Bytes};
use num_enum::{IntoPrimitive, TryFromPrimitive};
use std::convert::TryFrom;

#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct RouteMirroring {
    pub tlvs: Vec<RouteMirroringTlv>,
}

#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct RouteMirroringTlv {
    pub info_len: u16,
    pub value: RouteMirroringValue,
}

#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum RouteMirroringValue {
    BgpMessage(BgpMessage),
    Information(RouteMirroringInfo),
}

#[derive(Debug, TryFromPrimitive, IntoPrimitive, PartialEq, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(u16)]
pub enum RouteMirroringInfo {
    ErroredPdu = 0,
    MessageLost = 1,
}

pub fn parse_route_mirroring(
    data: &mut Bytes,
    asn_len: &AsnLength,
) -> Result<RouteMirroring, ParserBmpError> {
    let mut tlvs = vec![];
    while data.remaining() > 4 {
        match data.read_u16()? {
            0 => {
                let info_len = data.read_u16()?;
                data.has_n_remaining(info_len as usize)?;
                let mut bytes = data.split_to(info_len as usize);
                let value = parse_bgp_message(&mut bytes, false, asn_len)?;
                tlvs.push(RouteMirroringTlv {
                    info_len,
                    value: RouteMirroringValue::BgpMessage(value),
                });
            }
            1 => {
                let info_len = data.read_u16()?;
                let value = RouteMirroringInfo::try_from(data.read_u16()?)?;
                tlvs.push(RouteMirroringTlv {
                    info_len,
                    value: RouteMirroringValue::Information(value),
                });
            }
            _ => return Err(ParserBmpError::CorruptedBmpMessage),
        }
    }
    Ok(RouteMirroring { tlvs })
}

#[cfg(test)]
mod tests {
    use super::*;
    use bytes::{BufMut, BytesMut};
    use std::net::Ipv4Addr;

    #[test]
    fn test_route_mirroring_bgp_messsage() {
        let bgp_message = BgpMessage::Open(BgpOpenMessage {
            version: 4,
            asn: Asn::new_32bit(1),
            hold_time: 180,
            sender_ip: Ipv4Addr::new(192, 0, 2, 1),
            extended_length: false,
            opt_params: vec![],
        });
        let bgp_message_bytes = bgp_message.encode(false, AsnLength::Bits32);
        let expected_asn_len = AsnLength::Bits32;
        let actual_info_len = bgp_message_bytes.len() as u16;

        let mut message = BytesMut::new();
        message.put_u16(0);
        message.put_u16(actual_info_len);
        message.put_slice(&bgp_message_bytes);
        let mut data = message.freeze();
        let result = parse_route_mirroring(&mut data, &expected_asn_len);

        match result {
            Ok(route_mirroring) => {
                assert_eq!(route_mirroring.tlvs.len(), 1);
                let tlv = &route_mirroring.tlvs[0];
                assert_eq!(tlv.info_len, actual_info_len);
            }
            Err(_) => panic!("Error parsing route mirroring"),
        }
    }

    #[test]
    fn route_mirroring_information() {
        let mut message = BytesMut::new();
        message.put_u16(1);
        message.put_u16(2);
        message.put_u16(0);
        let mut data = message.freeze();
        let result = parse_route_mirroring(&mut data, &AsnLength::Bits32).unwrap();
        assert_eq!(result.tlvs.len(), 1);
        let tlv = &result.tlvs[0];
        assert_eq!(tlv.info_len, 2);
        match &tlv.value {
            RouteMirroringValue::Information(info) => {
                assert_eq!(info, &RouteMirroringInfo::ErroredPdu)
            }
            _ => panic!("Expected RouteMirroringValue::Information"),
        }
    }
}