From 11fa53642d89c574fe64933665a4fa0d2cd10a2d Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 1 Feb 2022 15:11:52 -0500 Subject: [PATCH] import nmstate-1.1.0-5.el8_5 --- .../BZ_2034139-do-not-rename-connection.patch | 45 +++ ...Z_2034139-ovs-remove-ovs-port-prefix.patch | 110 ++++++ ...riov-New-way-to-wait-VF-been-created.patch | 326 ++++++++++++++++++ SPECS/nmstate.spec | 11 +- 4 files changed, 491 insertions(+), 1 deletion(-) create mode 100644 SOURCES/BZ_2034139-do-not-rename-connection.patch create mode 100644 SOURCES/BZ_2034139-ovs-remove-ovs-port-prefix.patch create mode 100644 SOURCES/BZ_2039285-sriov-New-way-to-wait-VF-been-created.patch diff --git a/SOURCES/BZ_2034139-do-not-rename-connection.patch b/SOURCES/BZ_2034139-do-not-rename-connection.patch new file mode 100644 index 0000000..7036933 --- /dev/null +++ b/SOURCES/BZ_2034139-do-not-rename-connection.patch @@ -0,0 +1,45 @@ +From daad0a535b370d0a3f847526185c185aca2d9935 Mon Sep 17 00:00:00 2001 +From: Fernando Fernandez Mancera +Date: Thu, 2 Sep 2021 11:33:14 +0200 +Subject: [PATCH] nm.connection: do not rename existing connections + +When an user is specifying a custom name for a connection and then use +Nmstate to modify the interface, it will be renamed. That makes +impossible to use other automation tools because it will require to use +the uuid instead. + +Integration test case added. + +Ref: https://bugzilla.redhat.com/1998222 + +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Gris Ge +--- + libnmstate/nm/connection.py | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py +index 5a79c6f..39eb2b5 100644 +--- a/libnmstate/nm/connection.py ++++ b/libnmstate/nm/connection.py +@@ -98,9 +98,6 @@ class _ConnectionSetting: + self._setting.props.master = controller + self._setting.props.slave_type = port_type + +- def set_profile_name(self, con_name): +- self._setting.props.id = con_name +- + @property + def setting(self): + return self._setting +@@ -116,7 +113,6 @@ def create_new_nm_simple_conn(iface, nm_profile): + con_setting = _ConnectionSetting() + if nm_profile and not is_multiconnect_profile(nm_profile): + con_setting.import_by_profile(nm_profile, iface.is_controller) +- con_setting.set_profile_name(iface.name) + else: + con_setting.create( + iface.name, iface.name, nm_iface_type, iface.is_controller +-- +2.27.0 + diff --git a/SOURCES/BZ_2034139-ovs-remove-ovs-port-prefix.patch b/SOURCES/BZ_2034139-ovs-remove-ovs-port-prefix.patch new file mode 100644 index 0000000..4225ba0 --- /dev/null +++ b/SOURCES/BZ_2034139-ovs-remove-ovs-port-prefix.patch @@ -0,0 +1,110 @@ +From cd41c2c0f6bef7b952648b358246fffa8ce3cf62 Mon Sep 17 00:00:00 2001 +From: Fernando Fernandez Mancera +Date: Thu, 2 Sep 2021 17:39:59 +0200 +Subject: [PATCH 1/2] nm.connection: add postfixes to OVS bridges and + interfaces connections + +When configuring an OVS bridge and interface with the same using +Nmstate, it will generate two connection with the same name. If the user +is willing to use nmcli to manage this profiles, it is not user friendly +because they will need to use the connection UUID instead. + +In order to solve this, Nmstate is adding a postfix on the connection +name. "-if" for OVS interface and "-br" for OVS bridge. + +Please, note that this issue does not affect kernel interfaces because +it is not possible to have duplicated interfaces names in kernel. + +Integration test case added. + +Ref: https://bugzilla.redhat.com/1998218 + +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Gris Ge +--- + libnmstate/nm/connection.py | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py +index 39eb2b5..afe3788 100644 +--- a/libnmstate/nm/connection.py ++++ b/libnmstate/nm/connection.py +@@ -114,8 +114,20 @@ def create_new_nm_simple_conn(iface, nm_profile): + if nm_profile and not is_multiconnect_profile(nm_profile): + con_setting.import_by_profile(nm_profile, iface.is_controller) + else: ++ # OVS bridge and interfaces could sharing the same interface name, to ++ # distinguish them at NM connection level, instead of using interface ++ # name as connection name, we append a postfix. ++ con_name = iface.name ++ if iface.type == InterfaceType.OVS_BRIDGE: ++ con_name = con_name + "-br" ++ elif iface.type == InterfaceType.OVS_INTERFACE: ++ con_name = con_name + "-if" ++ + con_setting.create( +- iface.name, iface.name, nm_iface_type, iface.is_controller ++ con_name, ++ iface.name, ++ nm_iface_type, ++ iface.is_controller, + ) + + apply_lldp_setting(con_setting, iface_info) +-- +2.27.0 + + +From cfdd5afb1ef136d613d5adb3f6f5f6d156962586 Mon Sep 17 00:00:00 2001 +From: Radim Hrazdil +Date: Wed, 10 Nov 2021 16:57:08 +0100 +Subject: [PATCH 2/2] ovs: remove ovs-port prefix + +Prepending the prefix causes ovnkube-node pods to crash. +This change adds -port postfix to ovs-interface connection instead. + +Signed-off-by: Radim Hrazdil +Signed-off-by: Gris Ge +--- + libnmstate/nm/connection.py | 2 ++ + libnmstate/nm/ovs.py | 4 +--- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py +index afe3788..fb4ceba 100644 +--- a/libnmstate/nm/connection.py ++++ b/libnmstate/nm/connection.py +@@ -122,6 +122,8 @@ def create_new_nm_simple_conn(iface, nm_profile): + con_name = con_name + "-br" + elif iface.type == InterfaceType.OVS_INTERFACE: + con_name = con_name + "-if" ++ elif iface.type == InterfaceType.OVS_PORT: ++ con_name = con_name + "-port" + + con_setting.create( + con_name, +diff --git a/libnmstate/nm/ovs.py b/libnmstate/nm/ovs.py +index 424df36..9f2cba0 100644 +--- a/libnmstate/nm/ovs.py ++++ b/libnmstate/nm/ovs.py +@@ -32,8 +32,6 @@ from libnmstate.schema import OvsDB + from .common import NM + + +-PORT_PROFILE_PREFIX = "ovs-port-" +- + CONTROLLER_TYPE_METADATA = "_controller_type" + CONTROLLER_METADATA = "_controller" + SETTING_OVS_EXTERNALIDS = "SettingOvsExternalIDs" +@@ -311,7 +309,7 @@ def create_iface_for_nm_ovs_port(iface): + if ovs.is_ovs_lag_port(port_options): + port_name = port_options[OB.Port.NAME] + else: +- port_name = PORT_PROFILE_PREFIX + iface_name ++ port_name = iface_name + return OvsPortIface( + { + Interface.NAME: port_name, +-- +2.27.0 + diff --git a/SOURCES/BZ_2039285-sriov-New-way-to-wait-VF-been-created.patch b/SOURCES/BZ_2039285-sriov-New-way-to-wait-VF-been-created.patch new file mode 100644 index 0000000..5d4b1bd --- /dev/null +++ b/SOURCES/BZ_2039285-sriov-New-way-to-wait-VF-been-created.patch @@ -0,0 +1,326 @@ +From b8e3c6928c2a22a828b85a6780de3cea1107aa85 Mon Sep 17 00:00:00 2001 +From: Gris Ge +Date: Fri, 24 Dec 2021 16:34:30 +0800 +Subject: [PATCH] sriov: New way to wait VF been created + +By checking `/sys/class/net//device/virtfn/net/` +we could tell the interface name of VF. + +The old VF name guessing method is removed. The `verify_sriov_vf()` is +created to collect all VF interfaces name, then comparing it with +`total_vfs` count and check whether they exists in current state. + +The test indicate kernel/udev does not require extra time to remove VF +interface when decreasing SR-IOV VF count. + +Signed-off-by: Gris Ge +--- + libnmstate/ifaces/ethernet.py | 100 +++++++++++++++------------------- + libnmstate/ifaces/ifaces.py | 44 +-------------- + libnmstate/nispor/ethernet.py | 17 ++++++ + libnmstate/nm/profiles.py | 1 - + libnmstate/nm/sriov.py | 5 +- + 5 files changed, 67 insertions(+), 100 deletions(-) + +diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py +index 84fc665..720deab 100644 +--- a/libnmstate/ifaces/ethernet.py ++++ b/libnmstate/ifaces/ethernet.py +@@ -17,10 +17,9 @@ + # along with this program. If not, see . + # + ++from libnmstate.error import NmstateVerificationError + from libnmstate.schema import Ethernet +-from libnmstate.schema import Interface + from libnmstate.schema import InterfaceType +-from libnmstate.schema import InterfaceState + + from .base_iface import BaseIface + +@@ -30,7 +29,7 @@ MULTIPORT_PCI_DEVICE_PREFIX = "n" + + + class EthernetIface(BaseIface): +- IS_GENERATED_VF_METADATA = "_is_generated_vf" ++ VF_IFACE_NAME_METADATA = "_vf_iface_name" + + def __init__(self, info, save_to_disk=True): + super().__init__(info, save_to_disk) +@@ -56,10 +55,6 @@ class EthernetIface(BaseIface): + state = super().state_for_verify() + _capitalize_sriov_vf_mac(state) + EthernetIface._canonicalize(state) +- if self.is_generated_vf: +- # The VF state is unpredictable when PF is changing total_vfs count +- # Just don't verify generated VF state. +- state.pop(Interface.STATE, None) + return state + + @property +@@ -102,54 +97,6 @@ class EthernetIface(BaseIface): + def duplex(self): + return self.raw.get(Ethernet.CONFIG_SUBTREE, {}).get(Ethernet.DUPLEX) + +- def create_sriov_vf_ifaces(self): +- # Currently there is not a way to see the relation between a SR-IOV PF +- # and its VFs. Broadcom BCM57416 follows a different name pattern for +- # PF and VF, therefore it needs to be parsed if present. +- # +- # PF name: ens2f0np0 +- # VF name: ens2f0v0 +- # +- # The different name pattern is due to: +- # 1. The `n` is for `multi-port PCI device` support. +- # 2. The `p*` is `phys_port_name` provided by the BCM driver +- # `bnxt_en`. +- # +- # If the NIC is following the standard pattern "pfname+v+vfid", this +- # split will not touch it and the vf_pattern will be the PF name. +- # Ref: https://bugzilla.redhat.com/1959679 +- vf_pattern = self.name +- multiport_pattern = ( +- MULTIPORT_PCI_DEVICE_PREFIX + BNXT_DRIVER_PHYS_PORT_PREFIX +- ) +- if len(self.name.split(multiport_pattern)) == 2: +- vf_pattern = self.name.split(multiport_pattern)[0] +- +- vf_ifaces = [ +- EthernetIface( +- { +- # According to manpage of systemd.net-naming-scheme(7), +- # SRIOV VF interface will have v{slot} in device name. +- # Currently, nmstate has no intention to support +- # user-defined udev rule on SRIOV interface naming policy. +- Interface.NAME: f"{vf_pattern}v{i}", +- Interface.TYPE: InterfaceType.ETHERNET, +- # VF will be in DOWN state initialy +- Interface.STATE: InterfaceState.DOWN, +- } +- ) +- for i in range(0, self.sriov_total_vfs) +- ] +- # The generated vf metadata cannot be part of the original dict. +- for vf in vf_ifaces: +- vf._info[EthernetIface.IS_GENERATED_VF_METADATA] = True +- +- return vf_ifaces +- +- @property +- def is_generated_vf(self): +- return self._info.get(EthernetIface.IS_GENERATED_VF_METADATA) is True +- + def remove_vfs_entry_when_total_vfs_decreased(self): + vfs_count = len( + self._info[Ethernet.CONFIG_SUBTREE] +@@ -173,6 +120,16 @@ class EthernetIface(BaseIface): + def check_total_vfs_matches_vf_list(self, total_vfs): + return total_vfs == len(self.sriov_vfs) + ++ def to_dict(self): ++ info = super().to_dict() ++ for vf_info in ( ++ info.get(Ethernet.CONFIG_SUBTREE, {}) ++ .get(Ethernet.SRIOV_SUBTREE, {}) ++ .get(Ethernet.SRIOV.VFS_SUBTREE, []) ++ ): ++ vf_info.pop(EthernetIface.VF_IFACE_NAME_METADATA, None) ++ return info ++ + + def _capitalize_sriov_vf_mac(state): + vfs = ( +@@ -184,3 +141,36 @@ def _capitalize_sriov_vf_mac(state): + vf_mac = vf.get(Ethernet.SRIOV.VFS.MAC_ADDRESS) + if vf_mac: + vf[Ethernet.SRIOV.VFS.MAC_ADDRESS] = vf_mac.upper() ++ ++ ++def verify_sriov_vf(iface, cur_ifaces): ++ """ ++ Checking whether VF interface is been created ++ """ ++ if not ( ++ iface.is_up ++ and (iface.is_desired or iface.is_changed) ++ and iface.type == InterfaceType.ETHERNET ++ and iface.sriov_total_vfs > 0 ++ ): ++ return ++ cur_iface = cur_ifaces.get_iface(iface.name, iface.type) ++ if not cur_iface: ++ # Other verification will raise proper exception when current interface ++ # is missing ++ return ++ cur_vf_names = [] ++ for sriov_vf in cur_iface.sriov_vfs: ++ if sriov_vf.get(EthernetIface.VF_IFACE_NAME_METADATA): ++ cur_vf_names.append(sriov_vf[EthernetIface.VF_IFACE_NAME_METADATA]) ++ ++ if len(cur_vf_names) != iface.sriov_total_vfs: ++ raise NmstateVerificationError( ++ f"Found VF ports count does not match desired " ++ f"{iface.sriov_total_vfs}, current is: {','.join(cur_vf_names)}" ++ ) ++ for cur_vf_name in cur_vf_names: ++ if not cur_ifaces.get_iface(cur_vf_name, InterfaceType.ETHERNET): ++ raise NmstateVerificationError( ++ f"VF interface {cur_vf_name} of PF {iface.name} not found" ++ ) +diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py +index be295e3..4bd6792 100644 +--- a/libnmstate/ifaces/ifaces.py ++++ b/libnmstate/ifaces/ifaces.py +@@ -33,6 +33,7 @@ from .base_iface import BaseIface + from .bond import BondIface + from .dummy import DummyIface + from .ethernet import EthernetIface ++from .ethernet import verify_sriov_vf + from .infiniband import InfiniBandIface + from .linux_bridge import LinuxBridgeIface + from .macvlan import MacVlanIface +@@ -151,7 +152,6 @@ class Ifaces: + self._kernel_ifaces[iface.name] = iface + + self._create_virtual_port() +- self._create_sriov_vfs_when_changed() + self._mark_vf_interface_as_absent_when_sriov_vf_decrease() + self._validate_unknown_port() + self._validate_unknown_parent() +@@ -241,35 +241,6 @@ class Ifaces: + for iface in new_ifaces: + self._kernel_ifaces[iface.name] = iface + +- def _create_sriov_vfs_when_changed(self): +- """ +- When plugin set the TOTAL_VFS of PF, it might take 1 seconds or +- more to have the VFs to be ready. +- Nmstate should use verification retry to make sure VFs are full ready. +- To do that, we include VFs into desire state. +- """ +- new_ifaces = [] +- for iface in self.all_ifaces(): +- if ( +- iface.is_up +- and (iface.is_desired or iface.is_changed) +- and iface.type == InterfaceType.ETHERNET +- and iface.sriov_total_vfs > 0 +- ): +- for new_iface in iface.create_sriov_vf_ifaces(): +- cur_iface = self._kernel_ifaces.get(new_iface.name) +- if cur_iface and cur_iface.is_desired: +- raise NmstateNotSupportedError( +- "Does not support changing SR-IOV PF interface " +- "along with VF interface in the single desire " +- f"state: PF {iface.name}, VF {cur_iface.name}" +- ) +- else: +- new_iface.mark_as_desired() +- new_ifaces.append(new_iface) +- for new_iface in new_ifaces: +- self._kernel_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 +@@ -647,6 +618,7 @@ class Ifaces: + cur_ifaces._remove_ignore_interfaces(self._ignored_ifaces) + self._remove_ignore_interfaces(self._ignored_ifaces) + for iface in self.all_ifaces(): ++ verify_sriov_vf(iface, cur_ifaces) + if iface.is_desired: + if ( + iface.is_virtual +@@ -700,18 +672,6 @@ class Ifaces: + cur_iface.state_for_verify(), + ) + ) +- elif ( +- iface.type == InterfaceType.ETHERNET and iface.is_sriov +- ): +- if not cur_iface.check_total_vfs_matches_vf_list( +- iface.sriov_total_vfs +- ): +- raise NmstateVerificationError( +- "The NIC exceeded the waiting time for " +- "verification and it is failing because " +- "the `total_vfs` does not match the VF " +- "list length." +- ) + + def gen_dns_metadata(self, dns_state, route_state): + iface_metadata = dns_state.gen_metadata(self, route_state) +diff --git a/libnmstate/nispor/ethernet.py b/libnmstate/nispor/ethernet.py +index d6969b9..e4b82ff 100644 +--- a/libnmstate/nispor/ethernet.py ++++ b/libnmstate/nispor/ethernet.py +@@ -17,10 +17,13 @@ + # along with this program. If not, see . + # + ++import os ++ + from libnmstate.schema import Ethernet + from libnmstate.schema import InterfaceType + + from .base_iface import NisporPluginBaseIface ++from libnmstate.ifaces.ethernet import EthernetIface + + + class NisporPluginEthernetIface(NisporPluginBaseIface): +@@ -35,6 +38,9 @@ class NisporPluginEthernetIface(NisporPluginBaseIface): + for vf in self.np_iface.sr_iov.vfs: + vf_infos.append( + { ++ EthernetIface.VF_IFACE_NAME_METADATA: _get_vf_name( ++ self.np_iface.name, vf.vf_id ++ ), + Ethernet.SRIOV.VFS.ID: vf.vf_id, + Ethernet.SRIOV.VFS.MAC_ADDRESS: vf.mac.upper(), + Ethernet.SRIOV.VFS.SPOOF_CHECK: vf.spoof_check, +@@ -76,3 +82,14 @@ def np_ethtool_link_mode_to_nmstate(np_link_mode): + info[Ethernet.SPEED] = np_link_mode.speed + + return info ++ ++ ++def _get_vf_name(pf_name, vf_id): ++ try: ++ vf_names = os.listdir( ++ f"/sys/class/net/{pf_name}/device/virtfn{vf_id}/net/" ++ ) ++ if len(vf_names) >= 1: ++ return vf_names[0] ++ except Exception: ++ return "" +diff --git a/libnmstate/nm/profiles.py b/libnmstate/nm/profiles.py +index 3b0b6be..9e3020b 100644 +--- a/libnmstate/nm/profiles.py ++++ b/libnmstate/nm/profiles.py +@@ -71,7 +71,6 @@ class NmProfiles: + for iface in sorted( + list(net_state.ifaces.all_ifaces()), key=attrgetter("name") + ) +- if not getattr(iface, "is_generated_vf", None) + ] + + for profile in all_profiles: +diff --git a/libnmstate/nm/sriov.py b/libnmstate/nm/sriov.py +index a7e387c..e0bf60b 100644 +--- a/libnmstate/nm/sriov.py ++++ b/libnmstate/nm/sriov.py +@@ -102,8 +102,9 @@ def _create_sriov_vfs_from_config(vfs_config, sriov_setting, vf_ids_to_add): + + + def _set_nm_attribute(vf_object, key, value): +- nm_attr, nm_variant = SRIOV_NMSTATE_TO_NM_MAP[key] +- vf_object.set_attribute(nm_attr, nm_variant(value)) ++ if key in SRIOV_NMSTATE_TO_NM_MAP: ++ nm_attr, nm_variant = SRIOV_NMSTATE_TO_NM_MAP[key] ++ vf_object.set_attribute(nm_attr, nm_variant(value)) + + + def _remove_sriov_vfs_in_setting(vfs_config, sriov_setting, vf_ids_to_remove): +-- +2.27.0 + diff --git a/SPECS/nmstate.spec b/SPECS/nmstate.spec index 3d4e265..59cc1a3 100644 --- a/SPECS/nmstate.spec +++ b/SPECS/nmstate.spec @@ -4,7 +4,7 @@ Name: nmstate Version: 1.1.0 -Release: 3%{?dist} +Release: 5%{?dist} Summary: Declarative network manager API License: LGPLv2+ URL: https://github.com/%{srcname}/%{srcname} @@ -15,6 +15,9 @@ Patch1: 0001-nmstatectl-fix-long-arguments-support.patch Patch2: 0002-nm-ethtool-Preserve-existing-ethtool-settings-when-u.patch Patch3: 0003-ovs-fix-state-ignore-for-ovs-port-when-removing-them.patch Patch4: 0004-nispor-fix-show-of-empty-next_hop_address-and-destin.patch +Patch5: BZ_2034139-do-not-rename-connection.patch +Patch6: BZ_2034139-ovs-remove-ovs-port-prefix.patch +Patch7: BZ_2039285-sriov-New-way-to-wait-VF-been-created.patch BuildArch: noarch BuildRequires: python3-devel BuildRequires: python3-setuptools @@ -89,6 +92,12 @@ gpgv2 --keyring ./gpgkey-mantainers.gpg %{SOURCE1} %{SOURCE0} %{python3_sitelib}/%{libname}/plugins/__pycache__/nmstate_plugin_ovsdb* %changelog +* Wed Jan 12 2022 Gris Ge - 1.1.0-5 +- Remove OVS interface postfix. RHBZ#2034139 + +* Wed Jan 12 2022 Gris Ge - 1.1.0-4 +- Fix SR-IOV on ixgbe. RHBZ#2039285 + * Tue Jul 27 2021 Gris Ge - 1.1.0-3 - Fix state=ignore for OVS interface. RHBZ#1944054 - Fix verification for next hop address 0.0.0.0. RHBZ#1985879