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 pub fn length(&self) -> u16 {
129 self.value.len() as u16
130 }
131}
132
133#[derive(Debug, PartialEq, Clone, Eq)]
135#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
136pub struct TunnelEncapTlv {
137 pub tunnel_type: TunnelType,
138 pub sub_tlvs: Vec<SubTlv>,
139}
140
141impl TunnelEncapTlv {
142 pub fn new(tunnel_type: TunnelType) -> Self {
143 Self {
144 tunnel_type,
145 sub_tlvs: Vec::new(),
146 }
147 }
148
149 pub fn add_sub_tlv(&mut self, sub_tlv: SubTlv) {
150 self.sub_tlvs.push(sub_tlv);
151 }
152
153 pub fn get_tunnel_egress_endpoint(&self) -> Option<IpAddr> {
155 self.sub_tlvs
156 .iter()
157 .find(|tlv| tlv.sub_tlv_type == SubTlvType::TunnelEgressEndpoint)
158 .and_then(|tlv| match tlv.value.len() {
159 4 => {
160 let bytes = &tlv.value[0..4];
161 Some(IpAddr::V4(Ipv4Addr::new(
162 bytes[0], bytes[1], bytes[2], bytes[3],
163 )))
164 }
165 16 => {
166 let mut bytes = [0u8; 16];
167 bytes.copy_from_slice(&tlv.value[0..16]);
168 Some(IpAddr::V6(Ipv6Addr::from(bytes)))
169 }
170 _ => None,
171 })
172 }
173
174 pub fn get_color(&self) -> Option<u32> {
176 self.sub_tlvs
177 .iter()
178 .find(|tlv| tlv.sub_tlv_type == SubTlvType::Color)
179 .and_then(|tlv| {
180 if tlv.value.len() >= 4 {
181 Some(u32::from_be_bytes([
182 tlv.value[0],
183 tlv.value[1],
184 tlv.value[2],
185 tlv.value[3],
186 ]))
187 } else {
188 None
189 }
190 })
191 }
192
193 pub fn get_udp_destination_port(&self) -> Option<u16> {
195 self.sub_tlvs
196 .iter()
197 .find(|tlv| tlv.sub_tlv_type == SubTlvType::UdpDestinationPort)
198 .and_then(|tlv| {
199 if tlv.value.len() >= 2 {
200 Some(u16::from_be_bytes([tlv.value[0], tlv.value[1]]))
201 } else {
202 None
203 }
204 })
205 }
206
207 pub fn get_preference(&self) -> Option<u32> {
209 self.sub_tlvs
210 .iter()
211 .find(|tlv| tlv.sub_tlv_type == SubTlvType::Preference)
212 .and_then(|tlv| {
213 if tlv.value.len() >= 4 {
214 Some(u32::from_be_bytes([
215 tlv.value[0],
216 tlv.value[1],
217 tlv.value[2],
218 tlv.value[3],
219 ]))
220 } else {
221 None
222 }
223 })
224 }
225}
226
227#[derive(Debug, PartialEq, Clone, Eq, Default)]
229#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
230pub struct TunnelEncapAttribute {
231 pub tunnel_tlvs: Vec<TunnelEncapTlv>,
232}
233
234impl TunnelEncapAttribute {
235 pub fn new() -> Self {
236 Self::default()
237 }
238
239 pub fn add_tunnel_tlv(&mut self, tlv: TunnelEncapTlv) {
240 self.tunnel_tlvs.push(tlv);
241 }
242
243 pub fn get_tunnels_by_type(&self, tunnel_type: TunnelType) -> Vec<&TunnelEncapTlv> {
245 self.tunnel_tlvs
246 .iter()
247 .filter(|tlv| tlv.tunnel_type == tunnel_type)
248 .collect()
249 }
250
251 pub fn has_tunnel_type(&self, tunnel_type: TunnelType) -> bool {
253 self.tunnel_tlvs
254 .iter()
255 .any(|tlv| tlv.tunnel_type == tunnel_type)
256 }
257}
258
259#[cfg(test)]
260mod tests {
261 use super::*;
262
263 #[test]
264 fn test_tunnel_type_conversion() {
265 assert_eq!(TunnelType::Vxlan as u16, 8);
266 assert_eq!(TunnelType::Nvgre as u16, 9);
267 assert_eq!(TunnelType::SrPolicy as u16, 15);
268 assert_eq!(TunnelType::Geneve as u16, 19);
269 }
270
271 #[test]
272 fn test_sub_tlv_type_conversion() {
273 assert_eq!(SubTlvType::Color as u16, 4);
274 assert_eq!(SubTlvType::TunnelEgressEndpoint as u16, 6);
275 assert_eq!(SubTlvType::UdpDestinationPort as u16, 8);
276 assert_eq!(SubTlvType::SegmentList as u16, 128);
277 }
278
279 #[test]
280 fn test_tunnel_encap_tlv_creation() {
281 let mut tlv = TunnelEncapTlv::new(TunnelType::Vxlan);
282
283 let color_sub_tlv = SubTlv::new(SubTlvType::Color, vec![0x00, 0x00, 0x00, 0x64]); tlv.add_sub_tlv(color_sub_tlv);
286
287 let udp_port_sub_tlv = SubTlv::new(SubTlvType::UdpDestinationPort, vec![0x12, 0xB5]); tlv.add_sub_tlv(udp_port_sub_tlv);
290
291 assert_eq!(tlv.tunnel_type, TunnelType::Vxlan);
292 assert_eq!(tlv.sub_tlvs.len(), 2);
293 assert_eq!(tlv.get_color(), Some(100));
294 assert_eq!(tlv.get_udp_destination_port(), Some(4789));
295 }
296
297 #[test]
298 fn test_tunnel_encap_attribute() {
299 let mut attr = TunnelEncapAttribute::new();
300
301 let mut vxlan_tlv = TunnelEncapTlv::new(TunnelType::Vxlan);
302 vxlan_tlv.add_sub_tlv(SubTlv::new(SubTlvType::Color, vec![0x00, 0x00, 0x00, 0x64]));
303
304 let mut gre_tlv = TunnelEncapTlv::new(TunnelType::Gre);
305 gre_tlv.add_sub_tlv(SubTlv::new(SubTlvType::Color, vec![0x00, 0x00, 0x00, 0xC8]));
306
307 attr.add_tunnel_tlv(vxlan_tlv);
308 attr.add_tunnel_tlv(gre_tlv);
309
310 assert_eq!(attr.tunnel_tlvs.len(), 2);
311 assert!(attr.has_tunnel_type(TunnelType::Vxlan));
312 assert!(attr.has_tunnel_type(TunnelType::Gre));
313 assert!(!attr.has_tunnel_type(TunnelType::Nvgre));
314
315 let vxlan_tunnels = attr.get_tunnels_by_type(TunnelType::Vxlan);
316 assert_eq!(vxlan_tunnels.len(), 1);
317 assert_eq!(vxlan_tunnels[0].get_color(), Some(100));
318 }
319
320 #[test]
321 fn test_tunnel_egress_endpoint_parsing() {
322 let mut tlv = TunnelEncapTlv::new(TunnelType::Vxlan);
323
324 let ipv4_endpoint = SubTlv::new(
326 SubTlvType::TunnelEgressEndpoint,
327 vec![192, 168, 1, 1], );
329 tlv.add_sub_tlv(ipv4_endpoint);
330
331 if let Some(IpAddr::V4(addr)) = tlv.get_tunnel_egress_endpoint() {
332 assert_eq!(addr, Ipv4Addr::new(192, 168, 1, 1));
333 } else {
334 panic!("Expected IPv4 address");
335 }
336 }
337
338 #[test]
339 fn test_sub_tlv_length() {
340 let sub_tlv = SubTlv::new(SubTlvType::Color, vec![0x00, 0x00, 0x00, 0x64]);
341 assert_eq!(sub_tlv.length(), 4);
342 }
343
344 #[test]
345 #[cfg(feature = "serde")]
346 fn test_serde_serialization() {
347 let mut attr = TunnelEncapAttribute::new();
348 let mut tlv = TunnelEncapTlv::new(TunnelType::Vxlan);
349 tlv.add_sub_tlv(SubTlv::new(SubTlvType::Color, vec![0x00, 0x00, 0x00, 0x64]));
350 attr.add_tunnel_tlv(tlv);
351
352 let serialized = serde_json::to_string(&attr).unwrap();
353 let deserialized: TunnelEncapAttribute = serde_json::from_str(&serialized).unwrap();
354
355 assert_eq!(attr, deserialized);
356 }
357}