Skip to main content

network_device/
routing.rs

1//! Vendor-neutral static-route values.
2
3use crate::IpPrefix;
4use std::fmt;
5use std::net::IpAddr;
6
7/// A static route's destination and next-hop address.
8#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
9pub struct StaticRoute {
10    /// Destination network.
11    destination: IpPrefix,
12    /// IP address of the next hop.
13    next_hop: IpAddr,
14}
15
16impl StaticRoute {
17    /// Creates a route, requiring destination and next hop to use the same IP family.
18    pub fn new(destination: IpPrefix, next_hop: IpAddr) -> Result<Self, StaticRouteError> {
19        if destination.address().is_ipv4() != next_hop.is_ipv4() {
20            return Err(StaticRouteError::AddressFamilyMismatch);
21        }
22        Ok(Self {
23            destination,
24            next_hop,
25        })
26    }
27
28    /// Returns the route destination.
29    pub const fn destination(self) -> IpPrefix {
30        self.destination
31    }
32
33    /// Returns the route's next-hop address.
34    pub const fn next_hop(self) -> IpAddr {
35        self.next_hop
36    }
37}
38
39/// Validation error for [`StaticRoute`].
40#[derive(Clone, Copy, Debug, Eq, PartialEq)]
41pub enum StaticRouteError {
42    /// The destination and next hop use different IP address families.
43    AddressFamilyMismatch,
44}
45
46impl fmt::Display for StaticRouteError {
47    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
48        formatter
49            .write_str("static-route destination and next hop must use the same address family")
50    }
51}
52
53impl std::error::Error for StaticRouteError {}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58    use std::net::{Ipv4Addr, Ipv6Addr};
59
60    #[test]
61    fn route_rejects_a_next_hop_from_another_address_family() {
62        let destination = "192.0.2.0/24".parse::<IpPrefix>().unwrap();
63        assert_eq!(
64            StaticRoute::new(destination, IpAddr::V6(Ipv6Addr::LOCALHOST)),
65            Err(StaticRouteError::AddressFamilyMismatch)
66        );
67        assert!(StaticRoute::new(destination, IpAddr::V4(Ipv4Addr::LOCALHOST)).is_ok());
68    }
69}