1use 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#[derive(Default)]
24pub enum InterfaceType {
25 Bond,
28 LinuxBridge,
31 Dummy,
34 Ethernet,
37 Hsr,
40 Loopback,
43 MacVlan,
46 MacVtap,
49 OvsBridge,
52 OvsInterface,
55 Veth,
58 Vlan,
61 Vrf,
64 Vxlan,
67 #[serde(rename = "infiniband")]
70 InfiniBand,
71 Tun,
74 #[serde(rename = "macsec")]
77 MacSec,
78 Ipsec,
80 Xfrm,
82 #[serde(rename = "ipvlan")]
84 IpVlan,
85 #[default]
87 Unknown,
88 #[serde(untagged)]
90 Other(String),
91}
92
93impl 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 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#[derive(Default)]
151pub enum InterfaceState {
152 #[default]
155 Up,
156 Down,
161 Absent,
164 Unknown,
166 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]
195pub 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 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]
239pub enum Interface {
241 Bond(Box<BondInterface>),
243 Dummy(Box<DummyInterface>),
245 Ethernet(Box<EthernetInterface>),
247 Hsr(Box<HsrInterface>),
249 LinuxBridge(Box<LinuxBridgeInterface>),
251 OvsBridge(Box<OvsBridgeInterface>),
253 OvsInterface(Box<OvsInterface>),
255 Unknown(Box<UnknownInterface>),
257 Vlan(Box<VlanInterface>),
259 Vxlan(Box<VxlanInterface>),
261 MacVlan(Box<MacVlanInterface>),
263 MacVtap(Box<MacVtapInterface>),
265 Vrf(Box<VrfInterface>),
267 InfiniBand(Box<InfiniBandInterface>),
269 Loopback(Box<LoopbackInterface>),
271 MacSec(Box<MacSecInterface>),
273 Ipsec(Box<IpsecInterface>),
275 Xfrm(Box<XfrmInterface>),
277 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 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 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 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 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 pub fn is_up(&self) -> bool {
554 self.base_iface().state == InterfaceState::Up
555 }
556
557 pub fn is_absent(&self) -> bool {
559 self.base_iface().state == InterfaceState::Absent
560 }
561
562 pub fn is_down(&self) -> bool {
564 self.base_iface().state == InterfaceState::Down
565 }
566
567 pub fn is_ignore(&self) -> bool {
569 self.base_iface().state == InterfaceState::Ignore
570 }
571
572 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 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 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 pub fn need_controller(&self) -> bool {
616 matches!(self, Self::OvsInterface(_))
617 }
618
619 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 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 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#[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 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 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 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 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 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(¤t_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 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 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 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 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
1135fn 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, ¤t_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#[derive(Default)]
1168pub enum InterfaceIdentifier {
1169 #[default]
1172 Name,
1173 MacAddress,
1176 PciAddress,
1179}
1180
1181impl InterfaceIdentifier {
1182 pub fn is_default(&self) -> bool {
1183 self == &InterfaceIdentifier::default()
1184 }
1185}