Skip to main content

nmstate/query_apply/
inter_ifaces.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use crate::{
4    ErrorKind, Interface, InterfaceType, Interfaces, MergedInterfaces,
5    NmstateError,
6    state::{gen_diff_json_value, merge_json_value},
7};
8
9impl Interfaces {
10    pub(crate) fn has_up_ovs_iface(&self) -> bool {
11        self.iter().any(|i| {
12            i.iface_type() == InterfaceType::OvsBridge
13                || i.iface_type() == InterfaceType::OvsInterface
14        })
15    }
16
17    pub fn update(&mut self, other: &Self) {
18        let mut new_ifaces: Vec<Interface> = Vec::new();
19        let other_ifaces = other.to_vec();
20        for other_iface in other_ifaces {
21            let self_iface = if other_iface.is_userspace() {
22                self.get_iface_mut(other_iface.name(), other_iface.iface_type())
23            } else {
24                self.kernel_ifaces.get_mut(other_iface.name())
25            };
26            match self_iface {
27                Some(self_iface) => {
28                    // The OVS with netdev datapath will use `TUN` interface
29                    // as kernel representative
30                    if self_iface.iface_type() == InterfaceType::Tun
31                        && other_iface.iface_type()
32                            == InterfaceType::OvsInterface
33                    {
34                        if let Interface::OvsInterface(other_ovs_iface) =
35                            other_iface
36                        {
37                            let mut new_iface = other_ovs_iface.clone();
38                            new_iface.base = self_iface.base_iface().clone();
39                            new_iface.base.state = other_ovs_iface.base.state;
40                            new_iface.base.iface_type =
41                                InterfaceType::OvsInterface;
42                            new_iface
43                                .base
44                                .controller
45                                .clone_from(&other_ovs_iface.base.controller);
46                            new_iface.base.controller_type.clone_from(
47                                &other_ovs_iface.base.controller_type,
48                            );
49                            let mut new_iface =
50                                Interface::OvsInterface(new_iface);
51                            new_iface.update(other_iface);
52                            new_ifaces.push(new_iface);
53                        }
54                    } else {
55                        self_iface.update(other_iface);
56                    }
57                }
58                None => {
59                    new_ifaces.push(other_iface.clone());
60                }
61            }
62        }
63        for new_iface in new_ifaces {
64            self.push(new_iface);
65        }
66    }
67
68    fn remove_unknown_type_port(&mut self) {
69        let mut pending_actions: Vec<(String, InterfaceType, String)> =
70            Vec::new();
71        for iface in
72            self.kernel_ifaces.values().chain(self.user_ifaces.values())
73        {
74            if !iface.is_controller() {
75                continue;
76            }
77            for port_name in find_unknown_type_port(iface, self) {
78                pending_actions.push((
79                    iface.name().to_string(),
80                    iface.iface_type(),
81                    port_name.to_string(),
82                ));
83            }
84        }
85
86        for (ctrl_name, ctrl_type, port_name) in pending_actions {
87            if ctrl_type.is_userspace() {
88                if let Some(iface) =
89                    self.user_ifaces.get_mut(&(ctrl_name, ctrl_type))
90                {
91                    iface.remove_port(&port_name)
92                }
93            } else if let Some(iface) = self.kernel_ifaces.get_mut(&ctrl_name) {
94                iface.remove_port(&port_name)
95            }
96        }
97    }
98}
99
100fn find_unknown_type_port<'a>(
101    iface: &'a Interface,
102    cur_ifaces: &Interfaces,
103) -> Vec<&'a str> {
104    let mut ret: Vec<&str> = Vec::new();
105    if let Some(port_names) = iface.ports() {
106        for port_name in port_names {
107            if let Some(port_iface) =
108                cur_ifaces.get_iface(port_name, InterfaceType::Unknown)
109            {
110                if port_iface.iface_type() == InterfaceType::Unknown {
111                    ret.push(port_name);
112                }
113            } else {
114                // Remove not found interface also
115                ret.push(port_name);
116            }
117        }
118    }
119    ret
120}
121
122fn verify_desire_absent_but_found_in_current(
123    des_iface: &Interface,
124    cur_iface: &Interface,
125) -> Result<(), NmstateError> {
126    if cur_iface.is_virtual() {
127        // Virtual interface should be deleted by absent action
128        let e = NmstateError::new(
129            ErrorKind::VerificationError,
130            format!(
131                "Absent/Down interface {}/{} still found as {:?}",
132                des_iface.name(),
133                des_iface.iface_type(),
134                cur_iface
135            ),
136        );
137        log::error!("{e}");
138        Err(e)
139    } else {
140        // Hard to predict real hardware state due to backend variety.
141        Ok(())
142    }
143}
144
145impl MergedInterfaces {
146    pub(crate) fn gen_diff(&self) -> Result<Interfaces, NmstateError> {
147        let mut ret = Interfaces::default();
148        for merged_iface in self
149            .kernel_ifaces
150            .values()
151            .chain(self.user_ifaces.values())
152            .filter(|i| i.is_desired() && i.desired != i.current)
153        {
154            let des_iface = if let Some(i) = merged_iface.for_apply.as_ref() {
155                i
156            } else {
157                continue;
158            };
159            let cur_iface = if let Some(i) = merged_iface.current.as_ref() {
160                let mut cur_iface = i.clone();
161                cur_iface.sanitize(false).ok();
162                cur_iface
163            } else {
164                if let Some(origin_des_iface) = &merged_iface.desired {
165                    ret.push(origin_des_iface.clone());
166                } else {
167                    // Should never happen, but just in case.
168                    ret.push(des_iface.clone());
169                }
170                continue;
171            };
172            let desired_value = serde_json::to_value(des_iface)?;
173            let current_value = serde_json::to_value(&cur_iface)?;
174            if let Some(diff_value) =
175                gen_diff_json_value(&desired_value, &current_value)
176            {
177                let mut new_iface = des_iface.clone_name_type_only();
178                new_iface.base_iface_mut().state = des_iface.base_iface().state;
179                new_iface.include_diff_context(des_iface, &cur_iface);
180                let mut new_iface_value = serde_json::to_value(&new_iface)?;
181                merge_json_value(&mut new_iface_value, &diff_value);
182                let new_iface =
183                    serde_json::from_value::<Interface>(new_iface_value)?;
184                ret.push(new_iface);
185            }
186        }
187        Ok(ret)
188    }
189
190    pub(crate) fn verify(
191        &self,
192        current: &Interfaces,
193    ) -> Result<(), NmstateError> {
194        let mut merged = self.clone();
195        let mut current = current.clone();
196        current.remove_ignored_ifaces(self.ignored_ifaces.as_slice());
197        current.remove_unknown_type_port();
198        merged.process_allow_extra_ovs_patch_ports_for_verify(&mut current);
199
200        for iface in current
201            .kernel_ifaces
202            .values_mut()
203            .chain(current.user_ifaces.values_mut())
204        {
205            iface.sanitize(false).ok();
206            iface.sanitize_current_for_verify();
207        }
208
209        for des_iface in merged.iter_mut().filter(|i| i.is_desired()) {
210            let iface = if let Some(i) = des_iface.for_verify.as_mut() {
211                i
212            } else {
213                continue;
214            };
215            iface.sanitize(false).ok();
216            iface.sanitize_desired_for_verify();
217        }
218
219        for des_iface in merged.iter_mut().filter(|i| i.is_desired()) {
220            let iface = if let Some(i) = des_iface.for_verify.as_mut() {
221                i
222            } else {
223                continue;
224            };
225            if iface.is_absent() || (iface.is_virtual() && iface.is_down()) {
226                if let Some(cur_iface) =
227                    current.get_iface(iface.name(), iface.iface_type())
228                {
229                    verify_desire_absent_but_found_in_current(
230                        iface, cur_iface,
231                    )?;
232                }
233            } else if let Some(cur_iface) =
234                current.get_iface(iface.name(), iface.iface_type())
235            {
236                // Do not verify physical interface with state:down
237                if iface.is_up() {
238                    iface.verify(cur_iface)?;
239                    if let Interface::Ethernet(eth_iface) = iface
240                        && eth_iface.sriov_is_enabled()
241                    {
242                        eth_iface.verify_sriov(&current)?;
243                    }
244                }
245            } else if iface.is_up() {
246                return Err(NmstateError::new(
247                    ErrorKind::VerificationError,
248                    format!(
249                        "Failed to find desired interface {} {:?}",
250                        iface.name(),
251                        iface.iface_type()
252                    ),
253                ));
254            }
255        }
256        Ok(())
257    }
258}