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