Skip to main content

nmstate/
iface.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use std::collections::HashSet;
4
5use serde::{Deserialize, Deserializer, Serialize};
6
7use crate::{
8    BaseInterface, BondInterface, DummyInterface, ErrorKind, EthernetInterface,
9    HsrInterface, InfiniBandInterface, IpTunnelInterface, IpVlanInterface,
10    IpsecInterface, LinuxBridgeInterface, LoopbackInterface, MacSecInterface,
11    MacVlanInterface, MacVtapInterface, NmstateError, OvsBridgeInterface,
12    OvsInterface, VlanInterface, VrfInterface, VxlanInterface, XfrmInterface,
13    state::merge_json_value,
14};
15
16#[derive(
17    Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize,
18)]
19#[non_exhaustive]
20#[serde(rename_all = "kebab-case")]
21/// Interface type
22#[derive(Default)]
23pub enum InterfaceType {
24    /// [Bond interface](https://www.kernel.org/doc/Documentation/networking/bonding.txt)
25    /// Deserialize and serialize from/to 'bond'
26    Bond,
27    /// Bridge provided by Linux kernel.
28    /// Deserialize and serialize from/to 'linux-bridge'.
29    LinuxBridge,
30    /// Dummy interface.
31    /// Deserialize and serialize from/to 'dummy'.
32    Dummy,
33    /// Ethernet interface.
34    /// Deserialize and serialize from/to 'ethernet'.
35    Ethernet,
36    /// HSR interface.
37    /// Deserialize and serialize from/to 'hsr'.
38    Hsr,
39    /// IP Tunnel interface.
40    /// Deserialize and serialize from/to 'ip-tunnel'.
41    IpTunnel,
42    /// Loopback interface.
43    /// Deserialize and serialize from/to 'loopback'.
44    Loopback,
45    /// MAC VLAN interface.
46    /// Deserialize and serialize from/to 'mac-vlan'.
47    MacVlan,
48    /// MAC VTAP interface.
49    /// Deserialize and serialize from/to 'mac-vtap'.
50    MacVtap,
51    /// OpenvSwitch bridge.
52    /// Deserialize and serialize from/to 'ovs-bridge'.
53    OvsBridge,
54    /// OpenvSwitch system interface.
55    /// Deserialize and serialize from/to 'ovs-interface'.
56    OvsInterface,
57    /// Virtual ethernet provide by Linux kernel.
58    /// Deserialize and serialize from/to 'veth'.
59    Veth,
60    /// VLAN interface.
61    /// Deserialize and serialize from/to 'vlan'.
62    Vlan,
63    /// [Virtual Routing and Forwarding interface](https://www.kernel.org/doc/html/latest/networking/vrf.html)
64    /// Deserialize and serialize from/to 'vrf'.
65    Vrf,
66    /// VxVLAN interface.
67    /// Deserialize and serialize from/to 'vxlan'.
68    Vxlan,
69    /// [IP over InfiniBand interface](https://docs.kernel.org/infiniband/ipoib.html)
70    /// Deserialize and serialize from/to 'infiniband'.
71    #[serde(rename = "infiniband")]
72    InfiniBand,
73    /// TUN interface. Only used for query, will be ignored when applying.
74    /// Deserialize and serialize from/to 'tun'.
75    Tun,
76    /// MACsec interface.
77    /// Deserialize and serialize from/to 'macsec'
78    #[serde(rename = "macsec")]
79    MacSec,
80    /// Ipsec connection.
81    Ipsec,
82    /// Linux Xfrm kernel interface
83    Xfrm,
84    /// IPVLAN kernel interface
85    #[serde(rename = "ipvlan")]
86    IpVlan,
87    /// Unknown interface.
88    #[default]
89    Unknown,
90    /// Reserved for future use.
91    #[serde(untagged)]
92    Other(String),
93}
94
95//NOTE: Remember to add new interface types also here
96impl std::fmt::Display for InterfaceType {
97    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98        write!(
99            f,
100            "{}",
101            match self {
102                InterfaceType::Bond => "bond",
103                InterfaceType::LinuxBridge => "linux-bridge",
104                InterfaceType::Dummy => "dummy",
105                InterfaceType::Ethernet => "ethernet",
106                InterfaceType::Hsr => "hsr",
107                InterfaceType::IpTunnel => "ip-tunnel",
108                InterfaceType::Loopback => "loopback",
109                InterfaceType::MacVlan => "mac-vlan",
110                InterfaceType::MacVtap => "mac-vtap",
111                InterfaceType::OvsBridge => "ovs-bridge",
112                InterfaceType::OvsInterface => "ovs-interface",
113                InterfaceType::Veth => "veth",
114                InterfaceType::Vlan => "vlan",
115                InterfaceType::Vrf => "vrf",
116                InterfaceType::Vxlan => "vxlan",
117                InterfaceType::InfiniBand => "infiniband",
118                InterfaceType::Unknown => "unknown",
119                InterfaceType::Tun => "tun",
120                InterfaceType::MacSec => "macsec",
121                InterfaceType::Ipsec => "ipsec",
122                InterfaceType::Xfrm => "xfrm",
123                InterfaceType::IpVlan => "ipvlan",
124                InterfaceType::Other(s) => s,
125            }
126        )
127    }
128}
129
130impl InterfaceType {
131    const USERSPACE_IFACE_TYPES: [Self; 2] = [Self::OvsBridge, Self::Ipsec];
132    const CONTROLLER_IFACES_TYPES: [Self; 5] = [
133        Self::Bond,
134        Self::LinuxBridge,
135        Self::OvsBridge,
136        Self::Vrf,
137        Self::Hsr,
138    ];
139
140    // other interfaces are also considered as userspace
141    pub(crate) fn is_userspace(&self) -> bool {
142        self.is_other() || Self::USERSPACE_IFACE_TYPES.contains(self)
143    }
144
145    pub(crate) fn is_other(&self) -> bool {
146        matches!(self, Self::Other(_))
147    }
148
149    pub(crate) fn is_controller(&self) -> bool {
150        Self::CONTROLLER_IFACES_TYPES.contains(self)
151    }
152}
153
154#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
155#[serde(rename_all = "kebab-case")]
156#[non_exhaustive]
157/// The state of interface
158#[derive(Default)]
159pub enum InterfaceState {
160    /// Interface is up and running.
161    /// Deserialize and serialize from/to 'up'.
162    #[default]
163    Up,
164    /// For apply action, down means configuration still exist but
165    /// deactivate. The virtual interface will be removed and other interface
166    /// will be reverted to down state or up with IP disabled state.
167    /// Deserialize and serialize from/to 'down'.
168    Down,
169    /// Only for apply action to remove configuration and deactivate the
170    /// interface.
171    Absent,
172    /// Unknown state.
173    Unknown,
174    /// Interface is not managed by backend. For apply action, interface marked
175    /// as ignore will not be changed and will not cause verification failure
176    /// neither.
177    /// When desired controller listed currently ignored interfaces as its
178    /// port, nmstate will automatically convert these ignored interfaces from
179    /// 'state: ignore' to 'state: up' only when:
180    ///  1. This ignored port is not mentioned in desire state.
181    ///  2. This ignored port is listed as port of a desired controller.
182    ///  3. Controller interface is new or does not contain ignored interfaces
183    ///     currently.
184    ///
185    /// Deserialize and serialize from/to 'ignore'.
186    Ignore,
187}
188
189impl From<&str> for InterfaceState {
190    fn from(s: &str) -> Self {
191        match s {
192            "up" => Self::Up,
193            "down" => Self::Down,
194            "absent" => Self::Absent,
195            "ignore" => Self::Ignore,
196            _ => Self::Unknown,
197        }
198    }
199}
200
201#[derive(Debug, Clone, PartialEq, Eq, Serialize, Default)]
202#[non_exhaustive]
203/// Holder for interface with known interface type defined.
204/// During apply action, nmstate can resolve unknown interface to first
205/// found interface type.
206pub struct UnknownInterface {
207    #[serde(flatten)]
208    pub base: BaseInterface,
209    #[serde(flatten)]
210    pub(crate) other: serde_json::Value,
211}
212
213impl UnknownInterface {
214    pub fn new() -> Self {
215        Self::default()
216    }
217}
218
219impl<'de> Deserialize<'de> for UnknownInterface {
220    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
221    where
222        D: Deserializer<'de>,
223    {
224        let mut ret = UnknownInterface::default();
225        let mut v = serde_json::Map::deserialize(deserializer)?;
226        let mut base_value = serde_json::map::Map::new();
227        if let Some(n) = v.remove("name") {
228            base_value.insert("name".to_string(), n);
229        }
230        if let Some(s) = v.remove("state") {
231            base_value.insert("state".to_string(), s);
232        }
233        // The BaseInterface will only have name and state
234        // These two properties are also stored in `other` for serializing
235        ret.base = BaseInterface::deserialize(
236            serde_json::value::Value::Object(base_value),
237        )
238        .map_err(serde::de::Error::custom)?;
239        ret.other = serde_json::Value::Object(v);
240        Ok(ret)
241    }
242}
243
244#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
245#[serde(rename_all = "kebab-case", untagged)]
246#[non_exhaustive]
247/// Represent a kernel or user space network interface.
248pub enum Interface {
249    /// [Bond interface](https://www.kernel.org/doc/Documentation/networking/bonding.txt)
250    Bond(Box<BondInterface>),
251    /// Dummy interface.
252    Dummy(Box<DummyInterface>),
253    /// Ethernet interface or virtual ethernet(veth) of linux kernel
254    Ethernet(Box<EthernetInterface>),
255    /// HSR interface provided by Linux kernel.
256    Hsr(Box<HsrInterface>),
257    /// Bridge provided by Linux kernel.
258    LinuxBridge(Box<LinuxBridgeInterface>),
259    /// OpenvSwitch bridge.
260    OvsBridge(Box<OvsBridgeInterface>),
261    /// OpenvSwitch system interface.
262    OvsInterface(Box<OvsInterface>),
263    /// Unknown interface.
264    Unknown(Box<UnknownInterface>),
265    /// VLAN interface.
266    Vlan(Box<VlanInterface>),
267    /// VxLAN interface.
268    Vxlan(Box<VxlanInterface>),
269    /// MAC VLAN interface.
270    MacVlan(Box<MacVlanInterface>),
271    /// MAC VTAP interface.
272    MacVtap(Box<MacVtapInterface>),
273    /// [Virtual Routing and Forwarding interface](https://www.kernel.org/doc/html/latest/networking/vrf.html)
274    Vrf(Box<VrfInterface>),
275    /// [IP over InfiniBand interface](https://docs.kernel.org/infiniband/ipoib.html)
276    InfiniBand(Box<InfiniBandInterface>),
277    /// Linux loopback interface
278    Loopback(Box<LoopbackInterface>),
279    /// MACsec interface.
280    MacSec(Box<MacSecInterface>),
281    /// Ipsec connection
282    Ipsec(Box<IpsecInterface>),
283    /// Linux xfrm interface
284    Xfrm(Box<XfrmInterface>),
285    /// Linux IPVLAN interface
286    IpVlan(Box<IpVlanInterface>),
287    /// IP Tunnel interface.
288    IpTunnel(Box<IpTunnelInterface>),
289}
290
291impl<'de> Deserialize<'de> for Interface {
292    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
293    where
294        D: Deserializer<'de>,
295    {
296        let mut v = serde_json::Value::deserialize(deserializer)?;
297
298        // Only included minimum properties for state: absent
299        if matches!(
300            Option::deserialize(&v["state"])
301                .map_err(serde::de::Error::custom)?,
302            Some(InterfaceState::Absent)
303        ) {
304            let mut new_value = serde_json::map::Map::new();
305            if let Some(n) = v.get("name") {
306                new_value.insert("name".to_string(), n.clone());
307            }
308            if let Some(t) = v.get("type") {
309                new_value.insert("type".to_string(), t.clone());
310            }
311            if let Some(s) = v.get("state") {
312                new_value.insert("state".to_string(), s.clone());
313            }
314            if let Some(s) = v.get("identifier") {
315                new_value.insert("identifier".to_string(), s.clone());
316            }
317            if let Some(s) = v.get("mac-address") {
318                new_value.insert("mac-address".to_string(), s.clone());
319            }
320            if let Some(s) = v.get("pci-address") {
321                new_value.insert("pci-address".to_string(), s.clone());
322            }
323            v = serde_json::value::Value::Object(new_value);
324        }
325
326        match Option::deserialize(&v["type"])
327            .map_err(serde::de::Error::custom)?
328        {
329            Some(InterfaceType::Ethernet) => {
330                let inner = EthernetInterface::deserialize(v)
331                    .map_err(serde::de::Error::custom)?;
332                Ok(Interface::Ethernet(Box::new(inner)))
333            }
334            Some(InterfaceType::LinuxBridge) => {
335                let inner = LinuxBridgeInterface::deserialize(v)
336                    .map_err(serde::de::Error::custom)?;
337                Ok(Interface::LinuxBridge(Box::new(inner)))
338            }
339            Some(InterfaceType::Bond) => {
340                let inner = BondInterface::deserialize(v)
341                    .map_err(serde::de::Error::custom)?;
342                Ok(Interface::Bond(Box::new(inner)))
343            }
344            Some(InterfaceType::Veth) => {
345                let inner = EthernetInterface::deserialize(v)
346                    .map_err(serde::de::Error::custom)?;
347                Ok(Interface::Ethernet(Box::new(inner)))
348            }
349            Some(InterfaceType::Vlan) => {
350                let inner = VlanInterface::deserialize(v)
351                    .map_err(serde::de::Error::custom)?;
352                Ok(Interface::Vlan(Box::new(inner)))
353            }
354            Some(InterfaceType::Vxlan) => {
355                let inner = VxlanInterface::deserialize(v)
356                    .map_err(serde::de::Error::custom)?;
357                Ok(Interface::Vxlan(Box::new(inner)))
358            }
359            Some(InterfaceType::Dummy) => {
360                let inner = DummyInterface::deserialize(v)
361                    .map_err(serde::de::Error::custom)?;
362                Ok(Interface::Dummy(Box::new(inner)))
363            }
364            Some(InterfaceType::OvsInterface) => {
365                let inner = OvsInterface::deserialize(v)
366                    .map_err(serde::de::Error::custom)?;
367                Ok(Interface::OvsInterface(Box::new(inner)))
368            }
369            Some(InterfaceType::OvsBridge) => {
370                let inner = OvsBridgeInterface::deserialize(v)
371                    .map_err(serde::de::Error::custom)?;
372                Ok(Interface::OvsBridge(Box::new(inner)))
373            }
374            Some(InterfaceType::MacVlan) => {
375                let inner = MacVlanInterface::deserialize(v)
376                    .map_err(serde::de::Error::custom)?;
377                Ok(Interface::MacVlan(Box::new(inner)))
378            }
379            Some(InterfaceType::MacVtap) => {
380                let inner = MacVtapInterface::deserialize(v)
381                    .map_err(serde::de::Error::custom)?;
382                Ok(Interface::MacVtap(Box::new(inner)))
383            }
384            Some(InterfaceType::Vrf) => {
385                let inner = VrfInterface::deserialize(v)
386                    .map_err(serde::de::Error::custom)?;
387                Ok(Interface::Vrf(Box::new(inner)))
388            }
389            Some(InterfaceType::Hsr) => {
390                let inner = HsrInterface::deserialize(v)
391                    .map_err(serde::de::Error::custom)?;
392                Ok(Interface::Hsr(Box::new(inner)))
393            }
394            Some(InterfaceType::InfiniBand) => {
395                let inner = InfiniBandInterface::deserialize(v)
396                    .map_err(serde::de::Error::custom)?;
397                Ok(Interface::InfiniBand(Box::new(inner)))
398            }
399            Some(InterfaceType::IpTunnel) => {
400                let inner = IpTunnelInterface::deserialize(v)
401                    .map_err(serde::de::Error::custom)?;
402                Ok(Interface::IpTunnel(Box::new(inner)))
403            }
404            Some(InterfaceType::Loopback) => {
405                let inner = LoopbackInterface::deserialize(v)
406                    .map_err(serde::de::Error::custom)?;
407                Ok(Interface::Loopback(Box::new(inner)))
408            }
409            Some(InterfaceType::MacSec) => {
410                let inner = MacSecInterface::deserialize(v)
411                    .map_err(serde::de::Error::custom)?;
412                Ok(Interface::MacSec(Box::new(inner)))
413            }
414            Some(InterfaceType::Ipsec) => {
415                let inner = IpsecInterface::deserialize(v)
416                    .map_err(serde::de::Error::custom)?;
417                Ok(Interface::Ipsec(Box::new(inner)))
418            }
419            Some(InterfaceType::Xfrm) => {
420                let inner = XfrmInterface::deserialize(v)
421                    .map_err(serde::de::Error::custom)?;
422                Ok(Interface::Xfrm(Box::new(inner)))
423            }
424            Some(InterfaceType::IpVlan) => {
425                let inner = IpVlanInterface::deserialize(v)
426                    .map_err(serde::de::Error::custom)?;
427                Ok(Interface::IpVlan(Box::new(inner)))
428            }
429            Some(iface_type) => {
430                log::warn!("Unsupported interface type {iface_type}");
431                let inner = UnknownInterface::deserialize(v)
432                    .map_err(serde::de::Error::custom)?;
433                Ok(Interface::Unknown(Box::new(inner)))
434            }
435            None => {
436                let inner = UnknownInterface::deserialize(v)
437                    .map_err(serde::de::Error::custom)?;
438                Ok(Interface::Unknown(Box::new(inner)))
439            }
440        }
441    }
442}
443
444impl Interface {
445    /// The interface name.
446    pub fn name(&self) -> &str {
447        self.base_iface().name.as_str()
448    }
449
450    pub(crate) fn is_userspace(&self) -> bool {
451        self.base_iface().iface_type.is_userspace()
452    }
453
454    pub(crate) fn is_controller(&self) -> bool {
455        self.base_iface().iface_type.is_controller()
456    }
457
458    /// The interface type
459    pub fn iface_type(&self) -> InterfaceType {
460        self.base_iface().iface_type.clone()
461    }
462
463    pub(crate) fn clone_name_type_only(&self) -> Self {
464        match self {
465            Self::LinuxBridge(iface) => {
466                let mut new_iface = LinuxBridgeInterface::new();
467                new_iface.base = iface.base.clone_name_type_only();
468                Self::LinuxBridge(Box::new(new_iface))
469            }
470            Self::Ethernet(iface) => {
471                let mut new_iface = EthernetInterface::new();
472                new_iface.base = iface.base.clone_name_type_only();
473                // Do not use veth interface type when clone internally
474                new_iface.base.iface_type = InterfaceType::Ethernet;
475                Self::Ethernet(Box::new(new_iface))
476            }
477            Self::Vlan(iface) => {
478                let mut new_iface = VlanInterface::new();
479                new_iface.base = iface.base.clone_name_type_only();
480                Self::Vlan(Box::new(new_iface))
481            }
482            Self::Vxlan(iface) => {
483                let mut new_iface = VxlanInterface::new();
484                new_iface.base = iface.base.clone_name_type_only();
485                Self::Vxlan(Box::new(new_iface))
486            }
487            Self::Dummy(iface) => {
488                let mut new_iface = DummyInterface::new();
489                new_iface.base = iface.base.clone_name_type_only();
490                Self::Dummy(Box::new(new_iface))
491            }
492            Self::OvsInterface(iface) => {
493                let mut new_iface = OvsInterface::new();
494                new_iface.base = iface.base.clone_name_type_only();
495                Self::OvsInterface(Box::new(new_iface))
496            }
497            Self::OvsBridge(iface) => {
498                let mut new_iface = OvsBridgeInterface::new();
499                new_iface.base = iface.base.clone_name_type_only();
500                Self::OvsBridge(Box::new(new_iface))
501            }
502            Self::Bond(iface) => {
503                let mut new_iface = BondInterface::new();
504                new_iface.base = iface.base.clone_name_type_only();
505                Self::Bond(Box::new(new_iface))
506            }
507            Self::MacVlan(iface) => {
508                let mut new_iface = MacVlanInterface::new();
509                new_iface.base = iface.base.clone_name_type_only();
510                Self::MacVlan(Box::new(new_iface))
511            }
512            Self::MacVtap(iface) => {
513                let mut new_iface = MacVtapInterface::new();
514                new_iface.base = iface.base.clone_name_type_only();
515                Self::MacVtap(Box::new(new_iface))
516            }
517            Self::Vrf(iface) => {
518                let mut new_iface = VrfInterface::new();
519                new_iface.base = iface.base.clone_name_type_only();
520                Self::Vrf(Box::new(new_iface))
521            }
522            Self::Hsr(iface) => {
523                let mut new_iface = HsrInterface::new();
524                new_iface.base = iface.base.clone_name_type_only();
525                Self::Hsr(Box::new(new_iface))
526            }
527            Self::InfiniBand(iface) => {
528                let new_iface = InfiniBandInterface {
529                    base: iface.base.clone_name_type_only(),
530                    ..Default::default()
531                };
532                Self::InfiniBand(Box::new(new_iface))
533            }
534            Self::IpTunnel(iface) => {
535                let mut new_iface = IpTunnelInterface::new();
536                new_iface.base = iface.base.clone_name_type_only();
537                Self::IpTunnel(Box::new(new_iface))
538            }
539            Self::Loopback(iface) => {
540                let mut new_iface = LoopbackInterface::new();
541                new_iface.base = iface.base.clone_name_type_only();
542                Self::Loopback(Box::new(new_iface))
543            }
544            Self::MacSec(iface) => {
545                let mut new_iface = MacSecInterface::new();
546                new_iface.base = iface.base.clone_name_type_only();
547                Self::MacSec(Box::new(new_iface))
548            }
549            Self::Ipsec(iface) => {
550                let mut new_iface = IpsecInterface::new();
551                new_iface.base = iface.base.clone_name_type_only();
552                Self::Ipsec(Box::new(new_iface))
553            }
554            Self::Xfrm(iface) => {
555                let mut new_iface = XfrmInterface::new();
556                new_iface.base = iface.base.clone_name_type_only();
557                Self::Xfrm(Box::new(new_iface))
558            }
559            Self::IpVlan(iface) => {
560                let mut new_iface = IpVlanInterface::new();
561                new_iface.base = iface.base.clone_name_type_only();
562                Self::IpVlan(Box::new(new_iface))
563            }
564            Self::Unknown(iface) => {
565                let mut new_iface = UnknownInterface::new();
566                new_iface.base = iface.base.clone_name_type_only();
567                Self::Unknown(Box::new(new_iface))
568            }
569        }
570    }
571
572    /// Whether interface is up, default to true.
573    pub fn is_up(&self) -> bool {
574        self.base_iface().state == InterfaceState::Up
575    }
576
577    /// Whether interface is marked as absent.
578    pub fn is_absent(&self) -> bool {
579        self.base_iface().state == InterfaceState::Absent
580    }
581
582    /// Whether interface is marked as down.
583    pub fn is_down(&self) -> bool {
584        self.base_iface().state == InterfaceState::Down
585    }
586
587    /// Whether interface is marked as ignore.
588    pub fn is_ignore(&self) -> bool {
589        self.base_iface().state == InterfaceState::Ignore
590    }
591
592    // Whether desire state only has `name, type, state`.
593    pub(crate) fn is_up_exist_config(&self) -> bool {
594        self.is_up()
595            && match serde_json::to_value(self) {
596                Ok(v) => {
597                    if let Some(obj) = v.as_object() {
598                        // The name, type and state are always been serialized
599                        obj.len() == 3
600                    } else {
601                        log::error!(
602                            "BUG: is_up_exist_connection() got unexpected(not \
603                             object) serde_json::to_value() return {v}"
604                        );
605                        false
606                    }
607                }
608                Err(e) => {
609                    log::error!(
610                        "BUG: is_up_exist_connection() got unexpected \
611                         serde_json::to_value() failure {e}"
612                    );
613                    false
614                }
615            }
616    }
617
618    /// Whether interface is virtual(can delete from kernel).
619    /// Since loopback interface should not be deleted from system,
620    /// hence we consider loopback interface as __not__ virtual interface.
621    /// Unknown interface is considered as __not__ virtual interface.
622    pub fn is_virtual(&self) -> bool {
623        !matches!(
624            self,
625            Self::Ethernet(_)
626                | Self::Unknown(_)
627                | Self::InfiniBand(_)
628                | Self::Loopback(_)
629        )
630    }
631
632    /// Whether current interface only lives when its control exists.
633    /// For example, OpenvSwitch system interface can only exists when
634    /// its controller OpenvSwitch bridge exists.
635    pub fn need_controller(&self) -> bool {
636        matches!(self, Self::OvsInterface(_))
637    }
638
639    /// Get reference of its [BaseInterface].
640    pub fn base_iface(&self) -> &BaseInterface {
641        match self {
642            Self::LinuxBridge(iface) => &iface.base,
643            Self::Bond(iface) => &iface.base,
644            Self::Ethernet(iface) => &iface.base,
645            Self::Hsr(iface) => &iface.base,
646            Self::Vlan(iface) => &iface.base,
647            Self::Vxlan(iface) => &iface.base,
648            Self::Dummy(iface) => &iface.base,
649            Self::OvsBridge(iface) => &iface.base,
650            Self::OvsInterface(iface) => &iface.base,
651            Self::MacVlan(iface) => &iface.base,
652            Self::MacVtap(iface) => &iface.base,
653            Self::Vrf(iface) => &iface.base,
654            Self::InfiniBand(iface) => &iface.base,
655            Self::Loopback(iface) => &iface.base,
656            Self::MacSec(iface) => &iface.base,
657            Self::Ipsec(iface) => &iface.base,
658            Self::IpTunnel(iface) => &iface.base,
659            Self::Xfrm(iface) => &iface.base,
660            Self::IpVlan(iface) => &iface.base,
661            Self::Unknown(iface) => &iface.base,
662        }
663    }
664
665    pub fn base_iface_mut(&mut self) -> &mut BaseInterface {
666        match self {
667            Self::LinuxBridge(iface) => &mut iface.base,
668            Self::Bond(iface) => &mut iface.base,
669            Self::Ethernet(iface) => &mut iface.base,
670            Self::Hsr(iface) => &mut iface.base,
671            Self::Vlan(iface) => &mut iface.base,
672            Self::Vxlan(iface) => &mut iface.base,
673            Self::Dummy(iface) => &mut iface.base,
674            Self::OvsInterface(iface) => &mut iface.base,
675            Self::OvsBridge(iface) => &mut iface.base,
676            Self::MacVlan(iface) => &mut iface.base,
677            Self::MacVtap(iface) => &mut iface.base,
678            Self::Vrf(iface) => &mut iface.base,
679            Self::InfiniBand(iface) => &mut iface.base,
680            Self::Loopback(iface) => &mut iface.base,
681            Self::MacSec(iface) => &mut iface.base,
682            Self::Ipsec(iface) => &mut iface.base,
683            Self::IpTunnel(iface) => &mut iface.base,
684            Self::Xfrm(iface) => &mut iface.base,
685            Self::IpVlan(iface) => &mut iface.base,
686            Self::Unknown(iface) => &mut iface.base,
687        }
688    }
689
690    /// The name of ports.
691    /// Return None if its is not controller or not mentioned port section
692    pub fn ports(&self) -> Option<Vec<&str>> {
693        if self.is_absent() {
694            match self {
695                Self::LinuxBridge(_) => Some(Vec::new()),
696                Self::OvsBridge(_) => Some(Vec::new()),
697                Self::Bond(_) => Some(Vec::new()),
698                Self::Vrf(_) => Some(Vec::new()),
699                _ => None,
700            }
701        } else {
702            match self {
703                Self::LinuxBridge(iface) => iface.ports(),
704                Self::OvsBridge(iface) => iface.ports(),
705                Self::Bond(iface) => iface.ports(),
706                Self::Vrf(iface) => iface.ports(),
707                Self::Hsr(iface) => iface.ports(),
708                _ => None,
709            }
710        }
711    }
712
713    pub fn allow_extra_ports(&self) -> Option<bool> {
714        match self {
715            Self::LinuxBridge(iface) => {
716                iface.bridge.as_ref().and_then(|b| b.allow_extra_ports)
717            }
718            Self::OvsBridge(iface) => {
719                iface.bridge.as_ref().and_then(|b| b.allow_extra_ports)
720            }
721            _ => None,
722        }
723    }
724
725    pub fn set_allow_extra_ports(&mut self, value: Option<bool>) {
726        match self {
727            Self::LinuxBridge(iface) => {
728                if let Some(b) = iface.bridge.as_mut() {
729                    b.allow_extra_ports = value;
730                }
731            }
732            Self::OvsBridge(iface) => {
733                if let Some(b) = iface.bridge.as_mut() {
734                    b.allow_extra_ports = value;
735                }
736            }
737            _ => (),
738        }
739    }
740
741    pub(crate) fn remove_extra_ports(&self, current: &mut Self) {
742        let (Some(des_ports), Some(cur_ports)) =
743            (self.ports(), current.ports())
744        else {
745            return;
746        };
747
748        let to_delete: Vec<String> = cur_ports
749            .iter()
750            .filter(|p| !des_ports.contains(p))
751            .map(|p| p.to_string())
752            .collect();
753        if to_delete.is_empty() {
754            return;
755        }
756        for port in to_delete {
757            current.remove_port(&port);
758        }
759    }
760
761    // This function is for pre-edit clean up and check on current, `for_apply`,
762    // `for_verify` states.
763    //
764    // It is plugin's duty to clean up the state for querying before showing to
765    // user. Hence please do not use this function for querying.
766    // The `is_desired` is used to suppress error checking and logging on
767    // non-desired state.
768    pub(crate) fn sanitize(
769        &mut self,
770        is_desired: bool,
771    ) -> Result<(), NmstateError> {
772        self.base_iface_mut().sanitize(is_desired)?;
773        match self {
774            Interface::Ethernet(iface) => iface.sanitize()?,
775            Interface::Hsr(iface) => iface.sanitize(is_desired)?,
776            Interface::LinuxBridge(iface) => iface.sanitize(is_desired)?,
777            Interface::OvsInterface(iface) => iface.sanitize(is_desired)?,
778            Interface::OvsBridge(iface) => iface.sanitize(is_desired)?,
779            Interface::Vrf(iface) => iface.sanitize(is_desired)?,
780            Interface::Bond(iface) => iface.sanitize()?,
781            Interface::MacVlan(iface) => iface.sanitize(is_desired)?,
782            Interface::MacVtap(iface) => iface.sanitize(is_desired)?,
783            Interface::Loopback(iface) => iface.sanitize(is_desired)?,
784            Interface::MacSec(iface) => iface.sanitize(is_desired)?,
785            Interface::Ipsec(iface) => iface.sanitize(is_desired),
786            Interface::Vlan(iface) => iface.sanitize(is_desired)?,
787            Interface::IpVlan(iface) => iface.sanitize(is_desired)?,
788            Interface::IpTunnel(iface) => iface.sanitize(is_desired)?,
789            _ => (),
790        }
791        Ok(())
792    }
793
794    pub(crate) fn parent(&self) -> Option<&str> {
795        match self {
796            Interface::Vlan(vlan) => vlan.parent(),
797            Interface::Vxlan(vxlan) => vxlan.parent(),
798            Interface::OvsInterface(ovs) => ovs.parent(),
799            Interface::MacVlan(vlan) => vlan.parent(),
800            Interface::MacVtap(vtap) => vtap.parent(),
801            Interface::InfiniBand(ib) => ib.parent(),
802            Interface::MacSec(macsec) => macsec.parent(),
803            _ => None,
804        }
805    }
806
807    pub(crate) fn remove_port(&mut self, port_name: &str) {
808        if let Interface::LinuxBridge(br_iface) = self {
809            br_iface.remove_port(port_name);
810        } else if let Interface::OvsBridge(br_iface) = self {
811            br_iface.remove_port(port_name);
812        } else if let Interface::Bond(iface) = self {
813            iface.remove_port(port_name);
814        } else if let Interface::Vrf(iface) = self {
815            iface.remove_port(port_name);
816        } else {
817            log::error!(
818                "BUG: Interface::remove_port() been invoked against \
819                 unsupported interface type {} for interface {}",
820                self.iface_type(),
821                self.name(),
822            );
823        }
824    }
825
826    pub(crate) fn change_parent_name(&mut self, parent_name: &str) {
827        match self {
828            Interface::Vlan(vlan) => vlan.change_parent_name(parent_name),
829            Interface::Vxlan(vxlan) => vxlan.change_parent_name(parent_name),
830            Interface::MacVlan(vlan) => vlan.change_parent_name(parent_name),
831            Interface::MacVtap(vtap) => vtap.change_parent_name(parent_name),
832            Interface::MacSec(macsec) => macsec.change_parent_name(parent_name),
833            _ => {
834                log::warn!(
835                    "BUG: change_parent_name() invoked against unsupported \
836                     interface type {self:?}"
837                )
838            }
839        }
840    }
841
842    pub(crate) fn change_port_name(
843        &mut self,
844        org_port_name: &str,
845        new_port_name: String,
846    ) {
847        if let Interface::LinuxBridge(iface) = self {
848            iface.change_port_name(org_port_name, new_port_name);
849        } else if let Interface::OvsBridge(iface) = self {
850            iface.change_port_name(org_port_name, new_port_name);
851        } else if let Interface::Bond(iface) = self {
852            iface.change_port_name(org_port_name, new_port_name);
853        } else if let Interface::Vrf(iface) = self {
854            iface.change_port_name(org_port_name, new_port_name);
855        }
856    }
857}
858
859// The default on enum is experimental, but clippy is suggestion we use
860// that experimental derive. Suppress the warning there
861#[allow(clippy::derivable_impls)]
862impl Default for Interface {
863    fn default() -> Self {
864        Interface::Unknown(Box::default())
865    }
866}
867
868#[derive(Clone, Debug, Default, PartialEq, Eq)]
869pub(crate) struct MergedInterface {
870    pub(crate) for_verify: Option<Interface>,
871    pub(crate) for_apply: Option<Interface>,
872    pub(crate) merged: Interface,
873    pub(crate) desired: Option<Interface>,
874    pub(crate) current: Option<Interface>,
875}
876
877impl MergedInterface {
878    pub(crate) fn new(
879        desired: Option<Interface>,
880        current: Option<Interface>,
881    ) -> Result<Self, NmstateError> {
882        let mut ret = Self {
883            for_verify: desired.clone(),
884            for_apply: desired.clone(),
885            merged: {
886                match (desired.as_ref(), current.as_ref()) {
887                    (Some(d), Some(c)) => merge_desire_with_current(d, c)?,
888                    (Some(d), None) => d.clone(),
889                    (None, Some(c)) => c.clone(),
890                    (None, None) => {
891                        return Err(NmstateError::new(
892                            ErrorKind::Bug,
893                            "BUG: MergedInterface got both desired and \
894                             current set to None"
895                                .to_string(),
896                        ));
897                    }
898                }
899            },
900            desired,
901            current,
902        };
903        ret.pre_inter_ifaces_process();
904        Ok(ret)
905    }
906
907    pub(crate) fn is_desired(&self) -> bool {
908        self.desired.is_some()
909    }
910
911    // desired or invoked `mark_as_changed()`.
912    pub(crate) fn is_changed(&self) -> bool {
913        self.for_apply.is_some()
914    }
915
916    fn pre_inter_ifaces_process(&mut self) {
917        if self.merged.is_up() && self.is_desired() {
918            self.special_merge();
919            self.create_ovs_iface_for_empty_ports();
920        }
921    }
922
923    // This function is designed to hold smart changes or validations
924    // which only depend on desire and current status of single interface.
925    // This function will be invoked __after__ inter-ifaces process done.
926    pub(crate) fn post_inter_ifaces_process(
927        &mut self,
928    ) -> Result<(), NmstateError> {
929        self.preserve_current_controller_info();
930        self.post_inter_ifaces_process_base_iface()?;
931        self.post_inter_ifaces_process_sriov()?;
932        self.post_inter_ifaces_process_vrf()?;
933        self.post_inter_ifaces_process_bond()?;
934        self.post_inter_ifaces_process_vlan();
935        self.post_inter_ifaces_process_hsr();
936
937        if let Some(apply_iface) = self.for_apply.as_mut() {
938            apply_iface.sanitize(true)?;
939        }
940        Ok(())
941    }
942
943    // After HashMap based merging, extra task required for special use case
944    // like.
945    fn special_merge(&mut self) {
946        if let (Some(desired), Some(current)) =
947            (self.desired.as_ref(), self.current.as_ref())
948        {
949            self.merged
950                .base_iface_mut()
951                .special_merge(desired.base_iface(), current.base_iface());
952
953            if let Interface::Bond(bond_iface) = &mut self.merged {
954                if let (
955                    Interface::Bond(des_bond_iface),
956                    Interface::Bond(cur_bond_iface),
957                ) = (desired, current)
958                {
959                    bond_iface.special_merge(des_bond_iface, cur_bond_iface);
960                }
961            } else if let Interface::LinuxBridge(br_iface) = &mut self.merged {
962                if let (
963                    Interface::LinuxBridge(des_br_iface),
964                    Interface::LinuxBridge(cur_br_iface),
965                ) = (desired, current)
966                {
967                    br_iface.special_merge(des_br_iface, cur_br_iface);
968                }
969            } else if let Interface::OvsBridge(br_iface) = &mut self.merged
970                && let (
971                    Interface::OvsBridge(des_br_iface),
972                    Interface::OvsBridge(cur_br_iface),
973                ) = (desired, current)
974            {
975                br_iface.special_merge(des_br_iface, cur_br_iface);
976            }
977        }
978    }
979
980    pub(crate) fn set_copy_from_mac(&mut self, mac: String) {
981        if let Some(apply_iface) =
982            self.for_apply.as_mut().map(|i| i.base_iface_mut())
983        {
984            apply_iface.copy_mac_from = None;
985            apply_iface.mac_address = Some(mac.to_string());
986        }
987        if let Some(verify_iface) =
988            self.for_verify.as_mut().map(|i| i.base_iface_mut())
989        {
990            verify_iface.copy_mac_from = None;
991            verify_iface.mac_address = Some(mac);
992        }
993    }
994
995    pub(crate) fn process_allow_extra_bridge_ports(&mut self) {
996        let (Some(des_iface), Some(for_verify)) =
997            (self.desired.as_mut(), self.for_verify.as_mut())
998        else {
999            return;
1000        };
1001        if des_iface.allow_extra_ports() != Some(true) {
1002            return;
1003        }
1004        for_verify.set_allow_extra_ports(None);
1005        if let Some(cur_iface) = self.current.as_mut() {
1006            des_iface.remove_extra_ports(cur_iface);
1007        }
1008    }
1009
1010    // Return two list, first is changed port attached to specified interface,
1011    // second is changed port detached from specified interface.
1012    pub(crate) fn get_changed_ports(&self) -> Option<(Vec<&str>, Vec<&str>)> {
1013        let desired_iface = self.desired.as_ref()?;
1014
1015        if desired_iface.is_absent() {
1016            {
1017                let ports = self.current.as_ref().and_then(|c| c.ports())?;
1018                return Some((Vec::new(), ports));
1019            }
1020        }
1021
1022        let desired_port_names = match desired_iface.ports() {
1023            Some(p) => HashSet::from_iter(p.iter().cloned()),
1024            None => {
1025                // If current interface is in ignore state, even user did not
1026                // defining ports in desire, we should preserving existing port
1027                // lists
1028                {
1029                    let cur_iface = self.current.as_ref()?;
1030                    if cur_iface.is_ignore() {
1031                        cur_iface.ports().map(|ports| {
1032                            HashSet::<&str>::from_iter(ports.iter().cloned())
1033                        })?
1034                    } else {
1035                        return None;
1036                    }
1037                }
1038            }
1039        };
1040
1041        let current_port_names = self
1042            .current
1043            .as_ref()
1044            .and_then(|cur_iface| {
1045                if cur_iface.is_ignore() {
1046                    None
1047                } else {
1048                    cur_iface.ports()
1049                }
1050            })
1051            .map(|ports| HashSet::<&str>::from_iter(ports.iter().cloned()))
1052            .unwrap_or_default();
1053
1054        let mut chg_attached_ports: Vec<&str> = desired_port_names
1055            .difference(&current_port_names)
1056            .cloned()
1057            .collect();
1058        let chg_detached_ports: Vec<&str> = current_port_names
1059            .difference(&desired_port_names)
1060            .cloned()
1061            .collect();
1062
1063        // Linux Bridge might have changed configure its port configuration with
1064        // port name list unchanged.
1065        // In this case, we should ask LinuxBridgeInterface to generate a list
1066        // of configure changed port.
1067        if let (
1068            Interface::LinuxBridge(des_br_iface),
1069            Some(Interface::LinuxBridge(cur_br_iface)),
1070        ) = (desired_iface, self.current.as_ref())
1071        {
1072            for port_name in des_br_iface.get_config_changed_ports(cur_br_iface)
1073            {
1074                if !chg_attached_ports.contains(&port_name) {
1075                    chg_attached_ports.push(port_name);
1076                }
1077            }
1078        }
1079        // Bond might have changed its ports configuration with
1080        // port name list unchanged.
1081        // In this case, we should ask BondInterface to generate a new ports
1082        // configuration list.
1083        else if let (
1084            Interface::Bond(des_bond_iface),
1085            Some(Interface::Bond(cur_bond_iface)),
1086        ) = (desired_iface, self.current.as_ref())
1087        {
1088            for port_name in
1089                des_bond_iface.get_config_changed_ports(cur_bond_iface)
1090            {
1091                if !chg_attached_ports.contains(&port_name) {
1092                    chg_attached_ports.push(port_name);
1093                }
1094            }
1095        }
1096
1097        Some((chg_attached_ports, chg_detached_ports))
1098    }
1099
1100    // Store `Interface` with name and type into `for_apply`.
1101    // Do nothing if specified interface is already desired.
1102    pub(crate) fn mark_as_changed(&mut self) {
1103        if self.desired.is_none()
1104            && let Some(cur_iface) = self.current.as_ref()
1105        {
1106            let iface = cur_iface.clone_name_type_only();
1107            self.for_apply = Some(iface);
1108            self.preserve_current_controller_info();
1109            self.preserve_current_identifer_info();
1110        }
1111    }
1112
1113    pub(crate) fn mark_as_absent(&mut self) {
1114        self.mark_as_changed();
1115        self.merged.base_iface_mut().state = InterfaceState::Absent;
1116        if let Some(apply_iface) = self.for_apply.as_mut() {
1117            apply_iface.base_iface_mut().state = InterfaceState::Absent;
1118        }
1119    }
1120
1121    pub(crate) fn apply_ctrller_change(
1122        &mut self,
1123        ctrl_name: String,
1124        ctrl_type: Option<InterfaceType>,
1125        ctrl_state: InterfaceState,
1126    ) -> Result<(), NmstateError> {
1127        if self.merged.need_controller()
1128            && ctrl_name.is_empty()
1129            && let Some(org_ctrl) = self
1130                .current
1131                .as_ref()
1132                .and_then(|c| c.base_iface().controller.as_ref())
1133            && Some(true) == self.for_apply.as_ref().map(|i| i.is_up())
1134        {
1135            return Err(NmstateError::new(
1136                ErrorKind::InvalidArgument,
1137                format!(
1138                    "Interface {} cannot live without controller, but it is \
1139                     detached from original controller {org_ctrl}, cannot \
1140                     apply desired `state:up`",
1141                    self.merged.name()
1142                ),
1143            ));
1144        }
1145
1146        if !self.is_changed() {
1147            self.mark_as_changed();
1148            if ctrl_state == InterfaceState::Up {
1149                self.merged.base_iface_mut().state = InterfaceState::Up;
1150                if let Some(apply_iface) = self.for_apply.as_mut() {
1151                    apply_iface.base_iface_mut().state = InterfaceState::Up;
1152                }
1153            }
1154            log::info!(
1155                "Include interface {} to edit as its controller required so",
1156                self.merged.name()
1157            );
1158        }
1159        let apply_iface = if let Some(i) = self.for_apply.as_mut() {
1160            i
1161        } else {
1162            return Err(NmstateError::new(
1163                ErrorKind::Bug,
1164                format!(
1165                    "Reached unreachable code: apply_ctrller_change() \
1166                     self.for_apply still None: {self:?}"
1167                ),
1168            ));
1169        };
1170
1171        // Some interface cannot live without controller
1172        if self.merged.need_controller() && ctrl_name.is_empty() {
1173            if let Some(org_ctrl) = self
1174                .current
1175                .as_ref()
1176                .and_then(|c| c.base_iface().controller.as_ref())
1177            {
1178                log::info!(
1179                    "Interface {} cannot live without controller, marking as \
1180                     absent as it has been detached from its original \
1181                     controller {org_ctrl}",
1182                    self.merged.name(),
1183                );
1184            }
1185            self.merged.base_iface_mut().state = InterfaceState::Absent;
1186            apply_iface.base_iface_mut().state = InterfaceState::Absent;
1187            if let Some(verify_iface) = self.for_verify.as_mut() {
1188                verify_iface.base_iface_mut().state = InterfaceState::Absent;
1189            }
1190        } else {
1191            apply_iface.base_iface_mut().controller = Some(ctrl_name.clone());
1192            apply_iface
1193                .base_iface_mut()
1194                .controller_type
1195                .clone_from(&ctrl_type);
1196            self.merged.base_iface_mut().controller = Some(ctrl_name);
1197            self.merged.base_iface_mut().controller_type = ctrl_type;
1198            if !self.merged.base_iface().can_have_ip() {
1199                self.merged.base_iface_mut().ipv4 = None;
1200                self.merged.base_iface_mut().ipv6 = None;
1201            }
1202        }
1203        Ok(())
1204    }
1205
1206    fn preserve_current_controller_info(&mut self) {
1207        if let Some(apply_iface) = self.for_apply.as_mut()
1208            && apply_iface.base_iface().controller.is_none()
1209            && let Some(cur_iface) = self.current.as_ref()
1210            && cur_iface.base_iface().controller.as_ref().is_some()
1211        {
1212            apply_iface
1213                .base_iface_mut()
1214                .controller
1215                .clone_from(&cur_iface.base_iface().controller);
1216            apply_iface
1217                .base_iface_mut()
1218                .controller_type
1219                .clone_from(&cur_iface.base_iface().controller_type);
1220        }
1221    }
1222}
1223
1224// This function is merging all properties without known their meanings.
1225// When special merging required, please do that in `MergedInterface.process()`,
1226// after merged using stored `desired` and `current`.
1227fn merge_desire_with_current(
1228    desired: &Interface,
1229    current: &Interface,
1230) -> Result<Interface, NmstateError> {
1231    // No need to handle InterfaceType::Unknown, `resolve_unknown_ifaces()`
1232    // already checked.
1233    if desired.iface_type() != current.iface_type() {
1234        return Err(NmstateError::new(
1235            ErrorKind::InvalidArgument,
1236            format!(
1237                "Desired interface {} holds different interface type than \
1238                 current: desired {} vs current {}",
1239                desired.name(),
1240                desired.iface_type(),
1241                current.iface_type()
1242            ),
1243        ));
1244    }
1245    let mut desired_value = serde_json::to_value(desired)?;
1246    let current_value = serde_json::to_value(current)?;
1247    merge_json_value(&mut desired_value, &current_value);
1248
1249    let iface: Interface = serde_json::from_value(desired_value)?;
1250
1251    Ok(iface)
1252}
1253
1254#[derive(
1255    Debug,
1256    Clone,
1257    Copy,
1258    PartialEq,
1259    Eq,
1260    Hash,
1261    PartialOrd,
1262    Ord,
1263    Serialize,
1264    Deserialize,
1265)]
1266#[serde(rename_all = "kebab-case", deny_unknown_fields)]
1267#[non_exhaustive]
1268/// Interface Identifier defines the method for network backend on matching
1269/// network interface
1270#[derive(Default)]
1271pub enum InterfaceIdentifier {
1272    /// Use interface name to match the network interface, default value.
1273    /// Deserialize and serialize from/to 'name'.
1274    #[default]
1275    Name,
1276    /// Use interface MAC address to match the network interface.
1277    /// Deserialize and serialize from/to 'mac-address'.
1278    MacAddress,
1279    /// Use PCI Address to match the network interface.
1280    /// Deserialize and serialize from/to 'pci-address'.
1281    PciAddress,
1282}
1283
1284impl InterfaceIdentifier {
1285    pub fn is_default(&self) -> bool {
1286        self == &InterfaceIdentifier::default()
1287    }
1288}