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(µseconds.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}