bgpkit_parser/parser/mrt/messages/
table_dump.rs1use crate::error::*;
2use crate::models::*;
3use crate::parser::bgp::attributes::parse_attributes;
4use crate::parser::ReadUtils;
5use bytes::{BufMut, Bytes, BytesMut};
6use ipnet::IpNet;
7use std::net::IpAddr;
8
9pub fn parse_table_dump_message(
39 sub_type: u16,
40 mut data: Bytes,
41) -> Result<TableDumpMessage, ParserError> {
42 let afi = match sub_type {
50 1 => Afi::Ipv4,
51 2 => Afi::Ipv6,
52 _ => {
53 return Err(ParserError::ParseError(format!(
54 "Invalid subtype found for TABLE_DUMP (V1) message: {}",
55 sub_type
56 )))
57 }
58 };
59
60 let view_number = data.read_u16()?;
73 let sequence_number = data.read_u16()?;
74 let prefix = match &afi {
75 Afi::Ipv4 => data.read_ipv4_prefix().map(ipnet::IpNet::V4),
76 Afi::Ipv6 => data.read_ipv6_prefix().map(ipnet::IpNet::V6),
77 }?;
78
79 let status = data.read_u8()?;
80 let time = data.read_u32()? as u64;
81
82 let peer_address: IpAddr = data.read_address(&afi)?;
83 let peer_asn = Asn::new_16bit(data.read_u16()?);
84
85 let attribute_length = data.read_u16()? as usize;
86
87 data.has_n_remaining(attribute_length)?;
93 let attr_data_slice = data.split_to(attribute_length);
94
95 let attributes =
97 parse_attributes(attr_data_slice, &AsnLength::Bits16, false, None, None, None)?;
98
99 Ok(TableDumpMessage {
100 view_number,
101 sequence_number,
102 prefix: NetworkPrefix::new(prefix, 0),
103 status,
104 originated_time: time,
105 peer_address,
106 peer_asn,
107 attributes,
108 })
109}
110
111impl TableDumpMessage {
112 pub fn encode(&self) -> Bytes {
113 let mut bytes = BytesMut::new();
114 bytes.put_u16(self.view_number);
115 bytes.put_u16(self.sequence_number);
116 match &self.prefix.prefix {
117 IpNet::V4(p) => {
118 bytes.put_u32(p.addr().into());
119 bytes.put_u8(p.prefix_len());
120 }
121 IpNet::V6(p) => {
122 bytes.put_u128(p.addr().into());
123 bytes.put_u8(p.prefix_len());
124 }
125 }
126 bytes.put_u8(self.status);
127 bytes.put_u32(self.originated_time as u32);
128
129 match self.peer_address {
131 IpAddr::V4(a) => {
132 bytes.put_u32(a.into());
133 }
134 IpAddr::V6(a) => {
135 bytes.put_u128(a.into());
136 }
137 }
138 bytes.put_u16(self.peer_asn.into());
139
140 let mut attr_bytes = BytesMut::new();
142 for attr in &self.attributes.inner {
143 attr_bytes.extend(attr.encode(false, AsnLength::Bits16));
146 }
147
148 bytes.put_u16(attr_bytes.len() as u16);
149 bytes.put_slice(&attr_bytes);
150
151 bytes.freeze()
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158 use bytes::{BufMut, BytesMut};
159 use std::net::{Ipv4Addr, Ipv6Addr};
160
161 const VIEW_NUMBER: u16 = 0;
162 const SEQUENCE_NUMBER: u16 = 0;
163 const IPV4_PREFIX: Ipv4Addr = Ipv4Addr::new(0, 0, 0, 0);
164 const IPV6_PREFIX: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
165 const PREFIX_LEN: u8 = 0;
166 const STATUS: u8 = 0;
167 const TIME: u64 = 0;
168 const PEER_IPV4: Ipv4Addr = Ipv4Addr::new(0, 0, 0, 0);
169 const PEER_IPV6: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
170 const PEER_ASN_16BIT: u16 = 0;
171 const ATTRIBUTE_LENGTH: usize = 0;
172 const DUMMY_ATTRIBUTES: &[u8] = &[];
173
174 #[test]
175 fn test_parse_table_dump_message_ipv4() {
176 let mut bytes_mut = BytesMut::new();
177 bytes_mut.put_u16(VIEW_NUMBER);
179 bytes_mut.put_u16(SEQUENCE_NUMBER);
180 bytes_mut.put_u32(IPV4_PREFIX.into());
181 bytes_mut.put_u8(PREFIX_LEN);
182 bytes_mut.put_u8(STATUS);
183 bytes_mut.put_u32(TIME as u32);
184 bytes_mut.put_u32(PEER_IPV4.into());
185 bytes_mut.put_u16(PEER_ASN_16BIT);
186 bytes_mut.put_u16(ATTRIBUTE_LENGTH as u16);
187 bytes_mut.put_slice(DUMMY_ATTRIBUTES);
188
189 let bytes = bytes_mut.freeze();
191
192 let table_dump_message_res = parse_table_dump_message(1, bytes.clone());
193 assert!(
194 table_dump_message_res.is_ok(),
195 "Failed to parse TABLE_DUMP_V1 message"
196 );
197
198 let table_dump_message = table_dump_message_res.unwrap();
199 assert_eq!(
200 table_dump_message.view_number, VIEW_NUMBER,
201 "VIEW_NUMBER mismatch"
202 );
203 assert_eq!(
204 table_dump_message.sequence_number, SEQUENCE_NUMBER,
205 "SEQUENCE_NUMBER mismatch"
206 );
207 let encoded = table_dump_message.encode();
209 assert_eq!(encoded, bytes);
210 }
211 #[test]
212 fn test_parse_table_dump_message_ipv6() {
213 let mut bytes_mut = BytesMut::new();
214 bytes_mut.put_u16(VIEW_NUMBER);
216 bytes_mut.put_u16(SEQUENCE_NUMBER);
217 bytes_mut.put_u128(IPV6_PREFIX.into());
218 bytes_mut.put_u8(PREFIX_LEN);
219 bytes_mut.put_u8(STATUS);
220 bytes_mut.put_u32(TIME as u32);
221 bytes_mut.put_u128(PEER_IPV6.into());
222 bytes_mut.put_u16(PEER_ASN_16BIT);
223 bytes_mut.put_u16(ATTRIBUTE_LENGTH as u16);
224 bytes_mut.put_slice(DUMMY_ATTRIBUTES);
225
226 let bytes = bytes_mut.freeze();
228
229 let table_dump_message_res = parse_table_dump_message(2, bytes.clone());
230 assert!(
231 table_dump_message_res.is_ok(),
232 "Failed to parse TABLE_DUMP_V1 message"
233 );
234
235 let table_dump_message = table_dump_message_res.unwrap();
236 assert_eq!(
237 table_dump_message.view_number, VIEW_NUMBER,
238 "VIEW_NUMBER mismatch"
239 );
240 assert_eq!(
241 table_dump_message.sequence_number, SEQUENCE_NUMBER,
242 "SEQUENCE_NUMBER mismatch"
243 );
244 let encoded = table_dump_message.encode();
248 assert_eq!(encoded, bytes);
249 }
250}