Skip to main content

nmstate/ifaces/
ip_tunnel.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use std::net::IpAddr;
4
5use serde::{Deserialize, Serialize};
6
7use crate::{BaseInterface, ErrorKind, InterfaceType, NmstateError};
8
9#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
10#[serde(rename_all = "kebab-case")]
11#[non_exhaustive]
12/// IP Tunnel interface. The example YAML output of a
13/// [crate::NetworkState] with an ipip interface would be:
14/// ```yaml
15/// ---
16/// interfaces:
17///   - name: ipip0
18///     type: ip-tunnel
19///     state: up
20///     ip-tunnel:
21///       type: ipip
22///       local: 192.0.2.1
23///       remote: 192.0.2.2
24///       ttl: 255
25/// ```
26pub struct IpTunnelInterface {
27    #[serde(flatten)]
28    pub base: BaseInterface,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    /// Deserialize and serialize to `ip-tunnel`.
31    pub ip_tunnel: Option<IpTunnelConfig>,
32}
33
34impl Default for IpTunnelInterface {
35    fn default() -> Self {
36        Self {
37            base: BaseInterface {
38                iface_type: InterfaceType::IpTunnel,
39                ..Default::default()
40            },
41            ip_tunnel: None,
42        }
43    }
44}
45
46impl IpTunnelInterface {
47    pub fn new() -> Self {
48        Self::default()
49    }
50
51    pub(crate) fn sanitize(
52        &mut self,
53        is_desired: bool,
54    ) -> Result<(), NmstateError> {
55        if is_desired
56            && let Some(conf) = &mut self.ip_tunnel
57            && let Some(flow_label) = conf.flow_label
58            && flow_label > 0xFFFFF
59        {
60            return Err(NmstateError::new(
61                ErrorKind::InvalidArgument,
62                "Flow label must be less than 0xFFFFF".to_string(),
63            ));
64        }
65
66        Ok(())
67    }
68}
69
70#[derive(
71    Serialize, Deserialize, Debug, Default, PartialEq, Eq, Clone, Copy,
72)]
73#[serde(rename_all = "kebab-case")]
74#[non_exhaustive]
75pub enum IpTunnelMode {
76    #[default]
77    Unknown,
78    Ipip,
79    Sit,
80    Ip6ip6,
81    Ipip6,
82}
83
84#[derive(
85    Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy,
86)]
87#[serde(rename_all = "kebab-case")]
88#[non_exhaustive]
89pub enum Ip6TunnelFlag {
90    IgnEncapLimit,
91    UseOrigTclass,
92    UseOrigFlowlabel,
93    Mip6Dev,
94    RcvDscpCopy,
95    UseOrigFwMark,
96    AllowLocalRemote,
97    CapXmit,
98    CapRcv,
99    CapPerPacket,
100}
101
102#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
103#[serde(rename_all = "kebab-case")]
104#[non_exhaustive]
105#[derive(Default)]
106pub struct IpTunnelConfig {
107    /// The mode of the IP tunnel.
108    pub mode: Option<IpTunnelMode>,
109
110    /// The parent interface name of the IP tunnel.
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub base_iface: Option<String>,
113
114    #[serde(skip_serializing_if = "Option::is_none")]
115    pub local: Option<IpAddr>,
116
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub remote: Option<IpAddr>,
119
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub ttl: Option<u8>,
122
123    #[serde(skip_serializing_if = "Option::is_none")]
124    pub tos: Option<u8>,
125
126    #[serde(skip_serializing_if = "Option::is_none")]
127    pub flow_label: Option<u32>,
128
129    /// The flags of a ipip6 or ip6ip6 tunnel.
130    #[serde(skip_serializing_if = "Option::is_none")]
131    pub ip6tun_flags: Option<Vec<Ip6TunnelFlag>>,
132
133    /// The PMTU discovery flag of the IP tunnel.
134    #[serde(skip_serializing_if = "Option::is_none")]
135    pub pmtu_disc: Option<bool>,
136
137    #[serde(skip_serializing_if = "Option::is_none")]
138    pub encap_limit: Option<u8>,
139
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub fwmark: Option<u32>,
142}