From c55d39e8485a26490afc36d71fd9d20528ab6fd2 Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Thu, 18 Feb 2021 18:01:17 +0800 Subject: [PATCH 1/5] SRIOV: Remove VF interface when total-vfs decrease When `Ethernet.SRIOV.TOTAL_VFS` decrease, we should mark removed VF interface as absent. Both integration and unit test cases have been include. The integration test has been tested on real SRIOV hardware. Signed-off-by: Gris Ge Signed-off-by: Fernando Fernandez Mancera --- libnmstate/ifaces/base_iface.py | 5 +++++ libnmstate/ifaces/ethernet.py | 20 ++++++++++++++++++ libnmstate/ifaces/ifaces.py | 24 +++++++++++++++++++++ tests/integration/sriov_test.py | 37 +++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) diff --git a/libnmstate/ifaces/base_iface.py b/libnmstate/ifaces/base_iface.py index 564d583a..b4ade867 100644 --- a/libnmstate/ifaces/base_iface.py +++ b/libnmstate/ifaces/base_iface.py @@ -177,6 +177,11 @@ class BaseIface: def mark_as_desired(self): self._is_desired = True + def mark_as_absent_by_desire(self): + self.mark_as_desired() + self._info[Interface.STATE] = InterfaceState.ABSENT + self._origin_info[Interface.STATE] = InterfaceState.ABSENT + def to_dict(self): return deepcopy(self._info) diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py index 644fe6dd..3e1bdc5d 100644 --- a/libnmstate/ifaces/ethernet.py +++ b/libnmstate/ifaces/ethernet.py @@ -74,6 +74,26 @@ class EthernetIface(BaseIface): for i in range(0, self.sriov_total_vfs) ] + def remove_vfs_entry_when_total_vfs_decreased(self): + vfs_count = len( + self._info[Ethernet.CONFIG_SUBTREE] + .get(Ethernet.SRIOV_SUBTREE, {}) + .get(Ethernet.SRIOV.VFS_SUBTREE, []) + ) + if vfs_count > self.sriov_total_vfs: + [ + self._info[Ethernet.CONFIG_SUBTREE][Ethernet.SRIOV_SUBTREE][ + Ethernet.SRIOV.VFS_SUBTREE + ].pop() + for _ in range(self.sriov_total_vfs, vfs_count) + ] + + def get_delete_vf_interface_names(self, old_sriov_total_vfs): + return [ + f"{self.name}v{i}" + for i in range(self.sriov_total_vfs, old_sriov_total_vfs) + ] + def _capitalize_sriov_vf_mac(state): vfs = ( diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py index ee75125d..67ab91c4 100644 --- a/libnmstate/ifaces/ifaces.py +++ b/libnmstate/ifaces/ifaces.py @@ -99,6 +99,7 @@ class Ifaces: self._create_virtual_slaves() self._create_sriov_vfs_when_changed() self._validate_unknown_slaves() + self._mark_vf_interface_as_absent_when_sriov_vf_decrease() self._validate_unknown_parent() self._gen_metadata() for iface in self._ifaces.values(): @@ -147,6 +148,29 @@ class Ifaces: for new_iface in new_ifaces: self._ifaces[new_iface.name] = new_iface + def _mark_vf_interface_as_absent_when_sriov_vf_decrease(self): + """ + When SRIOV TOTAL_VFS decreased, we should mark certain VF interfaces + as absent and also remove the entry in `Ethernet.SRIOV.VFS_SUBTREE`. + """ + for iface_name, iface in self._ifaces.items(): + if iface.type != InterfaceType.ETHERNET or not iface.is_up: + continue + if iface_name not in self.current_ifaces: + continue + cur_iface = self.current_ifaces[iface_name] + if ( + cur_iface.sriov_total_vfs != 0 + and iface.sriov_total_vfs < cur_iface.sriov_total_vfs + ): + iface.remove_vfs_entry_when_total_vfs_decreased() + for vf_name in iface.get_delete_vf_interface_names( + cur_iface.sriov_total_vfs + ): + vf_iface = self._ifaces.get(vf_name) + if vf_iface: + vf_iface.mark_as_absent_by_desire() + def _pre_edit_validation_and_cleanup(self): self._validate_over_booked_slaves() self._validate_vlan_mtu() -- 2.29.2