bgpkit_parser/models/bgp/
tunnel_encap.rs1use num_enum::{FromPrimitive, IntoPrimitive};
4use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
5
6#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, FromPrimitive, IntoPrimitive)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[repr(u16)]
10pub enum TunnelType {
11 #[num_enum(default)]
12 Reserved = 0,
13 L2tpv3OverIp = 1,
15 Gre = 2,
17 TransmitTunnelEndpoint = 3,
19 IpsecTunnelMode = 4,
21 IpInIpWithIpsecTransport = 5,
23 MplsInIpWithIpsecTransport = 6,
25 IpInIp = 7,
27 Vxlan = 8,
29 Nvgre = 9,
31 Mpls = 10,
33 MplsInGre = 11,
35 VxlanGpe = 12,
37 MplsInUdp = 13,
39 Ipv6Tunnel = 14,
41 SrPolicy = 15,
43 Bare = 16,
45 SrTunnel = 17,
47 CloudSecurity = 18,
49 Geneve = 19,
51 AnyEncapsulation = 20,
53 GtpTunnel = 21,
55 DpsTunnel = 22,
57}
58
59#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, FromPrimitive, IntoPrimitive)]
61#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
62#[repr(u16)]
63pub enum SubTlvType {
64 #[num_enum(default)]
65 Reserved = 0,
66 Encapsulation = 1,
68 ProtocolType = 2,
70 IpsecTunnelAuthenticator = 3,
72 Color = 4,
74 LoadBalancingBlock = 5,
76 TunnelEgressEndpoint = 6,
78 DsField = 7,
80 UdpDestinationPort = 8,
82 EmbeddedLabelHandling = 9,
84 MplsLabelStack = 10,
86 PrefixSid = 11,
88 Preference = 12,
90 BindingSid = 13,
92 Enlp = 14,
94 Priority = 15,
96 SpiSiRepresentation = 16,
98 Ipv6SidStructure = 17,
100 Ipv4Sid = 18,
102 Ipv6Sid = 19,
104 Srv6BindingSid = 20,
106 SegmentList = 128,
108 PolicyCandidatePathName = 129,
110}
111
112#[derive(Debug, PartialEq, Clone, Eq)]
114#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
115pub struct SubTlv {
116 pub sub_tlv_type: SubTlvType,
117 pub value: Vec<u8>,
118}
119
120impl SubTlv {
121 pub fn new(sub_tlv_type: SubTlvType, value: Vec<u8>) -> Self {
122 Self {
123 sub_tlv_type,
124 value,
125 }
126 }
127}
128
129#[derive(Debug, PartialEq, Clone, Eq)]
131#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
132pub struct TunnelEncapTlv {
133 pub tunnel_type: TunnelType,
134 pub sub_tlvs: Vec<SubTlv>,
135}
136
137impl TunnelEncapTlv {
138 pub fn new(tunnel_type: TunnelType) -> Self {
139 Self {
140 tunnel_type,
141 sub_tlvs: Vec::new(),
142 }
143 }
144
145 pub fn add_sub_tlv(&mut self, sub_tlv: SubTlv) {
146 self.sub_tlvs.push(sub_tlv);
147 }
148
149 pub fn get_tunnel_egress_endpoint(&self) -> Option<IpAddr> {
151 self.sub_tlvs
152 .iter()
153 .find(|tlv| tlv.sub_tlv_type == SubTlvType::TunnelEgressEndpoint)
154 .and_then(|tlv| match tlv.value.len() {
155 4 => {
156 let bytes = &tlv.value[0..4];
157 Some(IpAddr::V4(Ipv4Addr::new(
158 bytes[0], bytes[1], bytes[2], bytes[3],
159 )))
160 }
161 16 => {
162 let mut bytes = [0u8; 16];
163 bytes.copy_from_slice(&tlv.value[0..16]);
164 Some(IpAddr::V6(Ipv6Addr::from(bytes)))
165 }
166 _ => None,
167 })
168 }
169
170 pub fn get_color(&self) -> Option<u32> {
172 self.sub_tlvs
173 .iter()
174 .find(|tlv| tlv.sub_tlv_type == SubTlvType::Color)
175 .and_then(|tlv| {
176 if tlv.value.len() >= 4 {
177 Some(u32::from_be_bytes([
178 tlv.value[0],
179 tlv.value[1],
180 tlv.value[2],
181 tlv.value[3],
182 ]))
183 } else {
184 None
185 }
186 })
187 }
188
189 pub fn get_udp_destination_port(&self) -> Option<u16> {
191 self.sub_tlvs
192 .iter()
193 .find(|tlv| tlv.sub_tlv_type == SubTlvType::UdpDestinationPort)
194 .and_then(|tlv| {
195 if tlv.value.len() >= 2 {
196 Some(u16::from_be_bytes([tlv.value[0], tlv.value[1]]))
197 } else {
198 None
199 }
200 })
201 }
202
203 pub fn get_preference(&self) -> Option<u32> {
205 self.sub_tlvs
206 .iter()
207 .find(|tlv| tlv.sub_tlv_type == SubTlvType::Preference)
208 .and_then(|tlv| {
209 if tlv.value.len() >= 4 {
210 Some(u32::from_be_bytes([
211 tlv.value[0],
212 tlv.value[1],
213 tlv.value[2],
214 tlv.value[3],
215 ]))
216 } else {
217 None
218 }
219 })
220 }
221}
222
223#[derive(Debug, PartialEq, Clone, Eq, Default)]
225#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
226pub struct TunnelEncapAttribute {
227 pub tunnel_tlvs: Vec<TunnelEncapTlv>,
228}
229
230impl TunnelEncapAttribute {
231 pub fn new() -> Self {
232 Self::default()
233 }
234
235 pub fn add_tunnel_tlv(&mut self, tlv: TunnelEncapTlv) {
236 self.tunnel_tlvs.push(tlv);
237 }
238
239 pub fn get_tunnels_by_type(&self, tunnel_type: TunnelType) -> Vec<&TunnelEncapTlv> {
241 self.tunnel_tlvs
242 .iter()
243 .filter(|tlv| tlv.tunnel_type == tunnel_type)
244 .collect()
245 }
246
247 pub fn has_tunnel_type(&self, tunnel_type: TunnelType) -> bool {
249 self.tunnel_tlvs
250 .iter()
251 .any(|tlv| tlv.tunnel_type == tunnel_type)
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use super::*;
258
259 #[test]
260 fn test_tunnel_type_conversion() {
261 assert_eq!(TunnelType::Vxlan as u16, 8);
262 assert_eq!(TunnelType::Nvgre as u16, 9);
263 assert_eq!(TunnelType::SrPolicy as u16, 15);
264 assert_eq!(TunnelType::Geneve as u16, 19);
265 }
266
267 #[test]
268 fn test_sub_tlv_type_conversion() {
269 assert_eq!(SubTlvType::Color as u16, 4);
270 assert_eq!(SubTlvType::TunnelEgressEndpoint as u16, 6);
271 assert_eq!(SubTlvType::UdpDestinationPort as u16, 8);
272 assert_eq!(SubTlvType::SegmentList as u16, 128);
273 }
274
275 #[test]
276 fn test_tunnel_encap_tlv_creation() {
277 let mut tlv = TunnelEncapTlv::new(TunnelType::Vxlan);
278
279 let color_sub_tlv = SubTlv::new(SubTlvType::Color, vec![0x00, 0x00, 0x00, 0x64]); tlv.add_sub_tlv(color_sub_tlv);
282
283 let udp_port_sub_tlv = SubTlv::new(SubTlvType::UdpDestinationPort, vec![0x12, 0xB5]); tlv.add_sub_tlv(udp_port_sub_tlv);
286
287 assert_eq!(tlv.tunnel_type, TunnelType::Vxlan);
288 assert_eq!(tlv.sub_tlvs.len(), 2);
289 assert_eq!(tlv.get_color(), Some(100));
290 assert_eq!(tlv.get_udp_destination_port(), Some(4789));
291 }
292
293 #[test]
294 fn test_tunnel_encap_attribute() {
295 let mut attr = TunnelEncapAttribute::new();
296
297 let mut vxlan_tlv = TunnelEncapTlv::new(TunnelType::Vxlan);
298 vxlan_tlv.add_sub_tlv(SubTlv::new(SubTlvType::Color, vec![0x00, 0x00, 0x00, 0x64]));
299
300 let mut gre_tlv = TunnelEncapTlv::new(TunnelType::Gre);
301 gre_tlv.add_sub_tlv(SubTlv::new(SubTlvType::Color, vec![0x00, 0x00, 0x00, 0xC8]));
302
303 attr.add_tunnel_tlv(vxlan_tlv);
304 attr.add_tunnel_tlv(gre_tlv);
305
306 assert_eq!(attr.tunnel_tlvs.len(), 2);
307 assert!(attr.has_tunnel_type(TunnelType::Vxlan));
308 assert!(attr.has_tunnel_type(TunnelType::Gre));
309 assert!(!attr.has_tunnel_type(TunnelType::Nvgre));
310
311 let vxlan_tunnels = attr.get_tunnels_by_type(TunnelType::Vxlan);
312 assert_eq!(vxlan_tunnels.len(), 1);
313 assert_eq!(vxlan_tunnels[0].get_color(), Some(100));
314 }
315
316 #[test]
317 fn test_tunnel_egress_endpoint_parsing() {
318 let mut tlv = TunnelEncapTlv::new(TunnelType::Vxlan);
319
320 let ipv4_endpoint = SubTlv::new(
322 SubTlvType::TunnelEgressEndpoint,
323 vec![192, 168, 1, 1], );
325 tlv.add_sub_tlv(ipv4_endpoint);
326
327 if let Some(IpAddr::V4(addr)) = tlv.get_tunnel_egress_endpoint() {
328 assert_eq!(addr, Ipv4Addr::new(192, 168, 1, 1));
329 } else {
330 panic!("Expected IPv4 address");
331 }
332 }
333
334 #[test]
335 fn test_sub_tlv_creation() {
336 let sub_tlv = SubTlv::new(SubTlvType::Color, vec![0x00, 0x00, 0x00, 0x64]);
337 assert_eq!(sub_tlv.sub_tlv_type, SubTlvType::Color);
338 assert_eq!(sub_tlv.value.len(), 4);
339 }
340
341 #[test]
342 #[cfg(feature = "serde")]
343 fn test_serde_serialization() {
344 let mut attr = TunnelEncapAttribute::new();
345 let mut tlv = TunnelEncapTlv::new(TunnelType::Vxlan);
346 tlv.add_sub_tlv(SubTlv::new(SubTlvType::Color, vec![0x00, 0x00, 0x00, 0x64]));
347 attr.add_tunnel_tlv(tlv);
348
349 let serialized = serde_json::to_string(&attr).unwrap();
350 let deserialized: TunnelEncapAttribute = serde_json::from_str(&serialized).unwrap();
351
352 assert_eq!(attr, deserialized);
353 }
354}