bgpkit_parser/models/bgp/
role.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use num_enum::{IntoPrimitive, TryFromPrimitive};

/// BGP Role
///
/// Defined in [RFC9234](https://www.iana.org/go/rfc9234).
#[derive(Debug, TryFromPrimitive, IntoPrimitive, PartialEq, Eq, Hash, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(u8)]
pub enum BgpRole {
    Provider = 0,
    RouteServer = 1,
    RouteServerClient = 2,
    Customer = 3,
    Peer = 4,
}

/// Validate the local-remote BGP Role pairs.
///
/// This function checks the role correctness by following the description in [Section 4.2 of RFC9234](https://www.rfc-editor.org/rfc/rfc9234.html#section-4.2).
///
/// The acceptable local-remote BGP pairs are:
///
/// Local AS Role | Remote AS Role
/// --- | ---
/// Provider | Customer
/// Customer | Provider
/// RouteServer | RouterServer-Client
/// RouterServer-Client | RouteServer
/// Peer | Peer
///
pub fn validate_role_pairs(local_role: &BgpRole, remote_role: &BgpRole) -> bool {
    match local_role {
        BgpRole::Provider => {
            if let BgpRole::Customer = remote_role {
                return true;
            }
            false
        }
        BgpRole::RouteServer => {
            if let BgpRole::RouteServerClient = remote_role {
                return true;
            }
            false
        }
        BgpRole::RouteServerClient => {
            if let BgpRole::RouteServer = remote_role {
                return true;
            }
            false
        }
        BgpRole::Customer => {
            if let BgpRole::Provider = remote_role {
                return true;
            }
            false
        }
        BgpRole::Peer => {
            if let BgpRole::Peer = remote_role {
                return true;
            }
            false
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::models::BgpRole::*;

    #[test]
    fn test_bgp_role_validation() {
        let mut local: BgpRole;
        let mut remote: BgpRole;

        local = Provider;
        remote = Customer;
        assert!(validate_role_pairs(&local, &remote));
        for remote in [Provider, Peer, RouteServer, RouteServerClient] {
            assert!(!validate_role_pairs(&local, &remote));
        }

        local = Customer;
        remote = Provider;
        assert!(validate_role_pairs(&local, &remote));
        for remote in [Customer, Peer, RouteServer, RouteServerClient] {
            assert!(!validate_role_pairs(&local, &remote));
        }

        local = RouteServer;
        remote = RouteServerClient;
        assert!(validate_role_pairs(&local, &remote));
        for remote in [Provider, Customer, Peer, RouteServer] {
            assert!(!validate_role_pairs(&local, &remote));
        }

        local = RouteServerClient;
        remote = RouteServer;
        assert!(validate_role_pairs(&local, &remote));
        for remote in [Provider, Customer, Peer, RouteServerClient] {
            assert!(!validate_role_pairs(&local, &remote));
        }

        local = Peer;
        remote = Peer;
        assert!(validate_role_pairs(&local, &remote));
        for remote in [Provider, Customer, RouteServer, RouteServerClient] {
            assert!(!validate_role_pairs(&local, &remote));
        }
    }
}