Skip to main content

nmstate/nispor/
base_iface.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use crate::{
4    AltNameEntry, BaseInterface, InterfaceState, InterfaceType, PciAddress,
5    nispor::{
6        ethtool::np_ethtool_to_nmstate,
7        ip::{np_ipv4_to_nmstate, np_ipv6_to_nmstate},
8        mptcp::get_iface_mptcp_conf,
9    },
10};
11
12fn np_iface_type_to_nmstate(
13    np_iface_type: &nispor::IfaceType,
14) -> InterfaceType {
15    match np_iface_type {
16        nispor::IfaceType::Bond => InterfaceType::Bond,
17        nispor::IfaceType::Bridge => InterfaceType::LinuxBridge,
18        nispor::IfaceType::Dummy => InterfaceType::Dummy,
19        nispor::IfaceType::Ethernet => InterfaceType::Ethernet,
20        nispor::IfaceType::Hsr => InterfaceType::Hsr,
21        nispor::IfaceType::Loopback => InterfaceType::Loopback,
22        nispor::IfaceType::MacSec => InterfaceType::MacSec,
23        nispor::IfaceType::MacVlan => InterfaceType::MacVlan,
24        nispor::IfaceType::MacVtap => InterfaceType::MacVtap,
25        nispor::IfaceType::OpenvSwitch => InterfaceType::OvsInterface,
26        nispor::IfaceType::Veth => InterfaceType::Veth,
27        nispor::IfaceType::Vlan => InterfaceType::Vlan,
28        nispor::IfaceType::Vrf => InterfaceType::Vrf,
29        nispor::IfaceType::Vxlan => InterfaceType::Vxlan,
30        nispor::IfaceType::Ipoib => InterfaceType::InfiniBand,
31        nispor::IfaceType::Tun => InterfaceType::Tun,
32        nispor::IfaceType::Xfrm => InterfaceType::Xfrm,
33        nispor::IfaceType::IpTunnel => InterfaceType::IpTunnel,
34        nispor::IfaceType::IpVlan => InterfaceType::IpVlan,
35        nispor::IfaceType::Other(v) => InterfaceType::Other(v.to_lowercase()),
36        _ => InterfaceType::Other(format!("{np_iface_type:?}").to_lowercase()),
37    }
38}
39
40impl From<(&nispor::IfaceState, &[nispor::IfaceFlag])> for InterfaceState {
41    fn from(tuple: (&nispor::IfaceState, &[nispor::IfaceFlag])) -> Self {
42        let (state, flags) = tuple;
43        // nispor::IfaceState::Up means operational up.
44        // Check also the Running flag with, according to [1], means operational
45        // state Up or Unknown.
46        // [1] https://www.kernel.org/doc/Documentation/networking/operstates.txt
47        if *state == nispor::IfaceState::Up
48            || flags.contains(&nispor::IfaceFlag::Running)
49        {
50            InterfaceState::Up
51        } else if *state == nispor::IfaceState::Down {
52            InterfaceState::Down
53        } else {
54            InterfaceState::Unknown
55        }
56    }
57}
58
59pub(crate) fn np_iface_to_base_iface(
60    np_iface: &nispor::Iface,
61    running_config_only: bool,
62) -> BaseInterface {
63    let mut base_iface = BaseInterface {
64        name: np_iface.name.to_string(),
65        driver: np_iface.driver.clone(),
66        state: (&np_iface.state, np_iface.flags.as_slice()).into(),
67        iface_type: np_iface_type_to_nmstate(&np_iface.iface_type),
68        ipv4: np_ipv4_to_nmstate(np_iface, running_config_only),
69        ipv6: np_ipv6_to_nmstate(np_iface, running_config_only),
70        mac_address: Some(np_iface.mac_address.to_uppercase()),
71        permanent_mac_address: get_permanent_mac_address(np_iface),
72        pci_address: np_iface.pci_address.map(PciAddress::from),
73        controller: np_iface.controller.as_ref().map(|c| c.to_string()),
74        alt_names: get_alt_names(np_iface),
75        mtu: if np_iface.mtu >= 0 {
76            Some(np_iface.mtu as u64)
77        } else {
78            Some(0u64)
79        },
80        min_mtu: if !running_config_only {
81            if let Some(mtu) = np_iface.min_mtu {
82                if mtu >= 0 { Some(mtu as u64) } else { None }
83            } else {
84                None
85            }
86        } else {
87            None
88        },
89        max_mtu: if !running_config_only {
90            if let Some(mtu) = np_iface.max_mtu {
91                if mtu >= 0 { Some(mtu as u64) } else { None }
92            } else {
93                None
94            }
95        } else {
96            None
97        },
98        accept_all_mac_addresses: if np_iface
99            .flags
100            .contains(&nispor::IfaceFlag::Promisc)
101        {
102            Some(true)
103        } else {
104            Some(false)
105        },
106        ethtool: np_ethtool_to_nmstate(np_iface),
107        ..Default::default()
108    };
109    if !InterfaceType::SUPPORTED_LIST.contains(&base_iface.iface_type) {
110        log::debug!(
111            "Got unsupported interface type {}: {}, ignoring",
112            &base_iface.iface_type,
113            &base_iface.name
114        );
115        base_iface.state = InterfaceState::Ignore;
116    }
117
118    base_iface.mptcp = get_iface_mptcp_conf(&base_iface);
119
120    base_iface
121}
122
123fn get_permanent_mac_address(iface: &nispor::Iface) -> Option<String> {
124    if iface.permanent_mac_address.is_empty() {
125        // Bond port also hold perm_hwaddr which is the mac address before
126        // this interface been assgined to bond as subordinate.
127        if let Some(bond_port_info) = &iface.bond_port {
128            if bond_port_info.perm_hwaddr.is_empty() {
129                None
130            } else {
131                Some(bond_port_info.perm_hwaddr.as_str().to_uppercase())
132            }
133        } else {
134            None
135        }
136    } else {
137        Some(iface.permanent_mac_address.as_str().to_uppercase())
138    }
139}
140
141impl From<nispor::PciAddress> for PciAddress {
142    fn from(np_pci: nispor::PciAddress) -> Self {
143        Self {
144            domain: np_pci.domain,
145            bus: np_pci.bus,
146            slot: np_pci.slot,
147            function: np_pci.function,
148        }
149    }
150}
151
152fn get_alt_names(np_iface: &nispor::Iface) -> Option<Vec<AltNameEntry>> {
153    let ret: Vec<AltNameEntry> = np_iface
154        .alt_names
155        .iter()
156        .map(|n| AltNameEntry {
157            name: n.to_string(),
158            ..Default::default()
159        })
160        .collect();
161
162    if ret.is_empty() { None } else { Some(ret) }
163}