1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// SPDX-License-Identifier: Apache-2.0

use crate::{
    nispor::ethtool::np_ethtool_to_nmstate,
    nispor::ip::{np_ipv4_to_nmstate, np_ipv6_to_nmstate},
    nispor::mptcp::get_iface_mptcp_conf,
    BaseInterface, InterfaceState, InterfaceType,
};

fn np_iface_type_to_nmstate(
    np_iface_type: &nispor::IfaceType,
) -> InterfaceType {
    match np_iface_type {
        nispor::IfaceType::Bond => InterfaceType::Bond,
        nispor::IfaceType::Bridge => InterfaceType::LinuxBridge,
        nispor::IfaceType::Dummy => InterfaceType::Dummy,
        nispor::IfaceType::Ethernet => InterfaceType::Ethernet,
        nispor::IfaceType::Hsr => InterfaceType::Hsr,
        nispor::IfaceType::Loopback => InterfaceType::Loopback,
        nispor::IfaceType::MacSec => InterfaceType::MacSec,
        nispor::IfaceType::MacVlan => InterfaceType::MacVlan,
        nispor::IfaceType::MacVtap => InterfaceType::MacVtap,
        nispor::IfaceType::OpenvSwitch => InterfaceType::OvsInterface,
        nispor::IfaceType::Veth => InterfaceType::Veth,
        nispor::IfaceType::Vlan => InterfaceType::Vlan,
        nispor::IfaceType::Vrf => InterfaceType::Vrf,
        nispor::IfaceType::Vxlan => InterfaceType::Vxlan,
        nispor::IfaceType::Ipoib => InterfaceType::InfiniBand,
        nispor::IfaceType::Tun => InterfaceType::Tun,
        nispor::IfaceType::Xfrm => InterfaceType::Xfrm,
        nispor::IfaceType::Other(v) => InterfaceType::Other(v.to_lowercase()),
        _ => InterfaceType::Other(format!("{np_iface_type:?}").to_lowercase()),
    }
}

impl From<(&nispor::IfaceState, &[nispor::IfaceFlag])> for InterfaceState {
    fn from(tuple: (&nispor::IfaceState, &[nispor::IfaceFlag])) -> Self {
        let (state, flags) = tuple;
        if *state == nispor::IfaceState::Up
            || flags.contains(&nispor::IfaceFlag::Up)
            || flags.contains(&nispor::IfaceFlag::Running)
        {
            InterfaceState::Up
        } else if *state == nispor::IfaceState::Down {
            InterfaceState::Down
        } else {
            InterfaceState::Unknown
        }
    }
}

pub(crate) fn np_iface_to_base_iface(
    np_iface: &nispor::Iface,
    running_config_only: bool,
) -> BaseInterface {
    let mut base_iface = BaseInterface {
        name: np_iface.name.to_string(),
        driver: np_iface.driver.clone(),
        state: (&np_iface.state, np_iface.flags.as_slice()).into(),
        iface_type: np_iface_type_to_nmstate(&np_iface.iface_type),
        ipv4: np_ipv4_to_nmstate(np_iface, running_config_only),
        ipv6: np_ipv6_to_nmstate(np_iface, running_config_only),
        mac_address: Some(np_iface.mac_address.to_uppercase()),
        permanent_mac_address: get_permanent_mac_address(np_iface),
        controller: np_iface.controller.as_ref().map(|c| c.to_string()),
        mtu: if np_iface.mtu >= 0 {
            Some(np_iface.mtu as u64)
        } else {
            Some(0u64)
        },
        min_mtu: if !running_config_only {
            if let Some(mtu) = np_iface.min_mtu {
                if mtu >= 0 {
                    Some(mtu as u64)
                } else {
                    None
                }
            } else {
                None
            }
        } else {
            None
        },
        max_mtu: if !running_config_only {
            if let Some(mtu) = np_iface.max_mtu {
                if mtu >= 0 {
                    Some(mtu as u64)
                } else {
                    None
                }
            } else {
                None
            }
        } else {
            None
        },
        accept_all_mac_addresses: if np_iface
            .flags
            .contains(&nispor::IfaceFlag::Promisc)
        {
            Some(true)
        } else {
            Some(false)
        },
        ethtool: np_ethtool_to_nmstate(np_iface),
        ..Default::default()
    };
    if !InterfaceType::SUPPORTED_LIST.contains(&base_iface.iface_type) {
        log::info!(
            "Got unsupported interface type {}: {}, ignoring",
            &base_iface.iface_type,
            &base_iface.name
        );
        base_iface.state = InterfaceState::Ignore;
    }

    base_iface.mptcp = get_iface_mptcp_conf(&base_iface);

    base_iface
}

fn get_permanent_mac_address(iface: &nispor::Iface) -> Option<String> {
    if iface.permanent_mac_address.is_empty() {
        // Bond port also hold perm_hwaddr which is the mac address before
        // this interface been assgined to bond as subordinate.
        if let Some(bond_port_info) = &iface.bond_subordinate {
            if bond_port_info.perm_hwaddr.is_empty() {
                None
            } else {
                Some(bond_port_info.perm_hwaddr.as_str().to_uppercase())
            }
        } else {
            None
        }
    } else {
        Some(iface.permanent_mac_address.clone())
    }
}