Skip to main content

bgpkit_parser/models/network/
afi.rs

1use num_enum::{IntoPrimitive, TryFromPrimitive};
2use std::net::IpAddr;
3
4/// AFI -- Address Family Identifier
5///
6/// <https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xhtml>
7#[derive(Debug, PartialEq, TryFromPrimitive, IntoPrimitive, Clone, Copy, Eq, Hash)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[repr(u16)]
10pub enum Afi {
11    Ipv4 = 1,
12    Ipv6 = 2,
13    /// BGP Link-State - RFC 7752
14    LinkState = 16388,
15}
16
17impl From<IpAddr> for Afi {
18    #[inline]
19    fn from(value: IpAddr) -> Self {
20        match value {
21            IpAddr::V4(_) => Afi::Ipv4,
22            IpAddr::V6(_) => Afi::Ipv6,
23        }
24    }
25}
26
27/// SAFI -- Subsequent Address Family Identifier
28///
29/// SAFI can be: Unicast, Multicast, or both, as well as MPLS VPN variants.
30/// The AFI determines the IP version (IPv4/IPv6), while SAFI determines the application.
31///
32/// References:
33/// - RFC 4760: Multiprotocol Extensions for BGP-4
34/// - RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs) - defines SAFI 128
35/// - RFC 6514: BGP Signaling of Multicast VPNs - defines SAFI 129
36/// - RFC 7752: BGP Link-State - defines SAFI 71, 72
37/// - RFC 8950: Advertising IPv4 Network Layer Reachability Information (NLRI) with an IPv6 Next Hop
38#[derive(Debug, PartialEq, TryFromPrimitive, IntoPrimitive, Clone, Copy, Eq, Hash)]
39#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
40#[repr(u8)]
41pub enum Safi {
42    Unicast = 1,
43    Multicast = 2,
44    UnicastMulticast = 3,
45    /// MPLS-labeled address - RFC 3107/8277
46    /// SAFI 4 for labeled unicast prefixes (not VPN)
47    MplsLabel = 4,
48    /// BGP Link-State - RFC 7752
49    LinkState = 71,
50    /// BGP Link-State VPN - RFC 7752
51    LinkStateVpn = 72,
52    /// MPLS-labeled VPN address - RFC 4364, used in RFC 8950 Section 4
53    /// Works with both AFI 1 (VPN-IPv4) and AFI 2 (VPN-IPv6)
54    MplsVpn = 128,
55    /// Multicast for BGP/MPLS IP VPNs - RFC 6514
56    /// Works with both AFI 1 (Multicast VPN-IPv4) and AFI 2 (Multicast VPN-IPv6)
57    MulticastVpn = 129,
58    /// Flow Specification - RFC 8955/8956
59    /// Works with both AFI 1 (IPv4 Flow-Spec) and AFI 2 (IPv6 Flow-Spec)
60    FlowSpec = 133,
61    /// L3VPN Flow Specification - RFC 8955/8956
62    /// Works with both AFI 1 (VPN-IPv4 Flow-Spec) and AFI 2 (VPN-IPv6 Flow-Spec)
63    FlowSpecL3Vpn = 134,
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn test_afi_from() {
72        assert_eq!(
73            Afi::from(IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1))),
74            Afi::Ipv4
75        );
76        assert_eq!(
77            Afi::from(IpAddr::V6(std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))),
78            Afi::Ipv6
79        );
80    }
81
82    #[test]
83    fn test_afi_safi_repr() {
84        assert_eq!(Afi::Ipv4 as u16, 1);
85        assert_eq!(Afi::Ipv6 as u16, 2);
86        assert_eq!(Afi::LinkState as u16, 16388);
87
88        assert_eq!(Safi::Unicast as u8, 1);
89        assert_eq!(Safi::Multicast as u8, 2);
90        assert_eq!(Safi::UnicastMulticast as u8, 3);
91        // RFC 7752 Link-State SAFI values
92        assert_eq!(Safi::LinkState as u8, 71);
93        assert_eq!(Safi::LinkStateVpn as u8, 72);
94        // RFC 8950 VPN SAFI values
95        assert_eq!(Safi::MplsVpn as u8, 128);
96        assert_eq!(Safi::MulticastVpn as u8, 129);
97        // RFC 8955/8956 Flow-Spec SAFI values
98        assert_eq!(Safi::FlowSpec as u8, 133);
99        assert_eq!(Safi::FlowSpecL3Vpn as u8, 134);
100    }
101
102    #[test]
103    #[cfg(feature = "serde")]
104    fn test_afi_safi_serde() {
105        let afi = Afi::Ipv4;
106        let serialized = serde_json::to_string(&afi).unwrap();
107        assert_eq!(serialized, "\"Ipv4\"");
108        let deserialized: Afi = serde_json::from_str(&serialized).unwrap();
109        assert_eq!(deserialized, afi);
110
111        let afi = Afi::Ipv6;
112        let serialized = serde_json::to_string(&afi).unwrap();
113        assert_eq!(serialized, "\"Ipv6\"");
114        let deserialized: Afi = serde_json::from_str(&serialized).unwrap();
115        assert_eq!(deserialized, afi);
116
117        let safi = Safi::Unicast;
118        let serialized = serde_json::to_string(&safi).unwrap();
119        assert_eq!(serialized, "\"Unicast\"");
120        let deserialized: Safi = serde_json::from_str(&serialized).unwrap();
121        assert_eq!(deserialized, safi);
122
123        let safi = Safi::Multicast;
124        let serialized = serde_json::to_string(&safi).unwrap();
125        assert_eq!(serialized, "\"Multicast\"");
126        let deserialized: Safi = serde_json::from_str(&serialized).unwrap();
127        assert_eq!(deserialized, safi);
128
129        let safi = Safi::UnicastMulticast;
130        let serialized = serde_json::to_string(&safi).unwrap();
131        assert_eq!(serialized, "\"UnicastMulticast\"");
132        let deserialized: Safi = serde_json::from_str(&serialized).unwrap();
133        assert_eq!(deserialized, safi);
134
135        // RFC 8950 VPN SAFI variants
136        let safi = Safi::MplsVpn;
137        let serialized = serde_json::to_string(&safi).unwrap();
138        assert_eq!(serialized, "\"MplsVpn\"");
139        let deserialized: Safi = serde_json::from_str(&serialized).unwrap();
140        assert_eq!(deserialized, safi);
141
142        let safi = Safi::MulticastVpn;
143        let serialized = serde_json::to_string(&safi).unwrap();
144        assert_eq!(serialized, "\"MulticastVpn\"");
145        let deserialized: Safi = serde_json::from_str(&serialized).unwrap();
146        assert_eq!(deserialized, safi);
147
148        // RFC 8955/8956 Flow-Spec SAFI variants
149        let safi = Safi::FlowSpec;
150        let serialized = serde_json::to_string(&safi).unwrap();
151        assert_eq!(serialized, "\"FlowSpec\"");
152        let deserialized: Safi = serde_json::from_str(&serialized).unwrap();
153        assert_eq!(deserialized, safi);
154
155        let safi = Safi::FlowSpecL3Vpn;
156        let serialized = serde_json::to_string(&safi).unwrap();
157        assert_eq!(serialized, "\"FlowSpecL3Vpn\"");
158        let deserialized: Safi = serde_json::from_str(&serialized).unwrap();
159        assert_eq!(deserialized, safi);
160    }
161}