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