bgp_models/mrt/
mod.rs

1//! MRT message and relevant structs.
2
3pub mod bgp4mp;
4pub mod tabledump;
5
6pub use crate::mrt::bgp4mp::*;
7pub use crate::mrt::tabledump::*;
8use serde::Serialize;
9use std::io;
10use std::io::Write;
11
12/// MrtRecord is a wrapper struct that contains a header and a message.
13///
14/// A MRT record is constructed as the following:
15/// ```text
16///  0                   1                   2                   3
17///  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
18/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19/// |                      Header... (variable)                     |
20/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21/// |                      Message... (variable)
22/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23/// ```
24///
25/// See [CommonHeader] for the content in header, and [MrtMessage] for the
26/// message format.
27#[derive(Debug, Serialize, PartialEq, Clone)]
28pub struct MrtRecord {
29    pub common_header: CommonHeader,
30    pub message: MrtMessage,
31}
32
33/// MRT common header.
34///
35/// A CommonHeader ([RFC6396 section 2][header-link]) is constructed as the following:
36/// ```text
37///  0                   1                   2                   3
38///  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
39/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40/// |                           Timestamp                           |
41/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42/// |             Type              |            Subtype            |
43/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44/// |                             Length                            |
45/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46/// ```
47///
48/// Or with extended timestamp:
49/// ```text
50///  0                   1                   2                   3
51///  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
52/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53/// |                           Timestamp                           |
54/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55/// |             Type              |            Subtype            |
56/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57/// |                             Length                            |
58/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59/// |                      Microsecond Timestamp                    |
60/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61/// ```
62///
63/// The headers include the following:
64/// - timestamp: 32 bits
65/// - entry_type: [EntryType] enum
66/// - entry_subtype: entry subtype
67/// - length: length of the message in octets
68/// - (`ET` type only) microsecond_timestamp: microsecond part of the timestamp.
69///   only applicable to the MRT message type with `_ET` suffix, such as
70///   `BGP4MP_ET`
71///
72/// [header-link]: https://datatracker.ietf.org/doc/html/rfc6396#section-2
73#[derive(Debug, Copy, Clone, Serialize, PartialEq, Eq)]
74pub struct CommonHeader {
75    pub timestamp: u32,
76    pub microsecond_timestamp: Option<u32>,
77    pub entry_type: EntryType,
78    pub entry_subtype: u16,
79    pub length: u32,
80}
81
82impl CommonHeader {
83    /// Writes the binary representation of the header to the given writer.
84    pub fn write_header<W: Write>(&self, writer: &mut W) -> io::Result<()> {
85        writer.write_all(&self.timestamp.to_be_bytes())?;
86        writer.write_all(&(self.entry_type as u16).to_be_bytes())?;
87        writer.write_all(&self.entry_subtype.to_be_bytes())?;
88
89        match self.microsecond_timestamp {
90            None => writer.write_all(&self.length.to_be_bytes()),
91            Some(microseconds) => {
92                // When the microsecond timestamp is present, the length must be adjusted to account
93                // for the stace used by the extra timestamp data.
94                writer.write_all(&(self.length + 4).to_be_bytes())?;
95                writer.write_all(&microseconds.to_be_bytes())
96            }
97        }
98    }
99}
100
101#[derive(Debug, Serialize, PartialEq, Eq, Clone)]
102pub enum MrtMessage {
103    TableDumpMessage(TableDumpMessage),
104    TableDumpV2Message(TableDumpV2Message),
105    Bgp4Mp(Bgp4Mp),
106}
107
108/// MRT entry type.
109///
110/// EntryType indicates the type of the current MRT record. Type 0 to 10 are deprecated.
111///
112/// Excerpt from [RFC6396 section 4](https://datatracker.ietf.org/doc/html/rfc6396#section-4):
113/// ```text
114/// The following MRT Types are currently defined for the MRT format.
115/// The MRT Types that contain the "_ET" suffix in their names identify
116/// those types that use an Extended Timestamp MRT Header.  The Subtype
117/// and Message fields in these types remain as defined for the MRT Types
118/// of the same name without the "_ET" suffix.
119///
120///     11   OSPFv2
121///     12   TABLE_DUMP
122///     13   TABLE_DUMP_V2
123///     16   BGP4MP
124///     17   BGP4MP_ET
125///     32   ISIS
126///     33   ISIS_ET
127///     48   OSPFv3
128///     49   OSPFv3_ET
129/// ```
130#[derive(Debug, Primitive, Copy, Clone, Serialize, PartialEq, Eq)]
131#[allow(non_camel_case_types)]
132#[repr(u16)]
133pub enum EntryType {
134    // START DEPRECATED
135    NULL = 0,
136    START = 1,
137    DIE = 2,
138    I_AM_DEAD = 3,
139    PEER_DOWN = 4,
140    BGP = 5,
141    RIP = 6,
142    IDRP = 7,
143    RIPNG = 8,
144    BGP4PLUS = 9,
145    BGP4PLUS_01 = 10,
146    // END DEPRECATED
147    OSPFv2 = 11,
148    TABLE_DUMP = 12,
149    TABLE_DUMP_V2 = 13,
150    BGP4MP = 16,
151    BGP4MP_ET = 17,
152    ISIS = 32,
153    ISIS_ET = 33,
154    OSPFv3 = 48,
155    OSPFv3_ET = 49,
156}