1use 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#[derive(Default)]
23pub enum InterfaceType {
24 Bond,
27 LinuxBridge,
30 Dummy,
33 Ethernet,
36 Hsr,
39 IpTunnel,
42 Loopback,
45 MacVlan,
48 MacVtap,
51 OvsBridge,
54 OvsInterface,
57 Veth,
60 Vlan,
63 Vrf,
66 Vxlan,
69 #[serde(rename = "infiniband")]
72 InfiniBand,
73 Tun,
76 #[serde(rename = "macsec")]
79 MacSec,
80 Ipsec,
82 Xfrm,
84 #[serde(rename = "ipvlan")]
86 IpVlan,
87 #[default]
89 Unknown,
90 #[serde(untagged)]
92 Other(String),
93}
94
95impl 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 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#[derive(Default)]
159pub enum InterfaceState {
160 #[default]
163 Up,
164 Down,
169 Absent,
172 Unknown,
174 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]
203pub 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 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]
247pub enum Interface {
249 Bond(Box<BondInterface>),
251 Dummy(Box<DummyInterface>),
253 Ethernet(Box<EthernetInterface>),
255 Hsr(Box<HsrInterface>),
257 LinuxBridge(Box<LinuxBridgeInterface>),
259 OvsBridge(Box<OvsBridgeInterface>),
261 OvsInterface(Box<OvsInterface>),
263 Unknown(Box<UnknownInterface>),
265 Vlan(Box<VlanInterface>),
267 Vxlan(Box<VxlanInterface>),
269 MacVlan(Box<MacVlanInterface>),
271 MacVtap(Box<MacVtapInterface>),
273 Vrf(Box<VrfInterface>),
275 InfiniBand(Box<InfiniBandInterface>),
277 Loopback(Box<LoopbackInterface>),
279 MacSec(Box<MacSecInterface>),
281 Ipsec(Box<IpsecInterface>),
283 Xfrm(Box<XfrmInterface>),
285 IpVlan(Box<IpVlanInterface>),
287 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 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 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 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 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 pub fn is_up(&self) -> bool {
574 self.base_iface().state == InterfaceState::Up
575 }
576
577 pub fn is_absent(&self) -> bool {
579 self.base_iface().state == InterfaceState::Absent
580 }
581
582 pub fn is_down(&self) -> bool {
584 self.base_iface().state == InterfaceState::Down
585 }
586
587 pub fn is_ignore(&self) -> bool {
589 self.base_iface().state == InterfaceState::Ignore
590 }
591
592 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 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 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 pub fn need_controller(&self) -> bool {
636 matches!(self, Self::OvsInterface(_))
637 }
638
639 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 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 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#[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 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 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 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 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 {
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(¤t_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 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 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 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 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
1224fn merge_desire_with_current(
1228 desired: &Interface,
1229 current: &Interface,
1230) -> Result<Interface, NmstateError> {
1231 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, ¤t_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#[derive(Default)]
1271pub enum InterfaceIdentifier {
1272 #[default]
1275 Name,
1276 MacAddress,
1279 PciAddress,
1282}
1283
1284impl InterfaceIdentifier {
1285 pub fn is_default(&self) -> bool {
1286 self == &InterfaceIdentifier::default()
1287 }
1288}