Blame SOURCES/BZ_2160416-fix-SRIOV.patch

2bf224
From d410b928c8f2a22d42d1974b62ab5b3164861184 Mon Sep 17 00:00:00 2001
2bf224
From: Gris Ge <fge@redhat.com>
2bf224
Date: Thu, 23 Feb 2023 13:06:01 +0800
2bf224
Subject: [PATCH] nm: Fix error on SR-IOV
2bf224
2bf224
When SR-IOV VF naming scheme is like `ens1f0v0`, nmstate will delete
2bf224
the VF NM connection when applying this state:
2bf224
2bf224
```yml
2bf224
---
2bf224
interfaces:
2bf224
- name: ens1f0
2bf224
  type: ethernet
2bf224
  state: up
2bf224
  ethernet:
2bf224
    sr-iov:
2bf224
      total-vfs: 1
2bf224
- name: ens1f0v0
2bf224
  type: ethernet
2bf224
  state: up
2bf224
  ipv4:
2bf224
    enabled: false
2bf224
  ipv6:
2bf224
    enabled: false
2bf224
```
2bf224
2bf224
This is because `delete_other_profiles()` is checking
2bf224
`self._nm_profile()` from active NM profile instead of newly created
2bf224
one. The fix is using newly created profile `self._nm_simple_conn`.
2bf224
2bf224
We also have race problem when activating PF along with VF, PF
2bf224
activation might delete VF NIC which cause VF activation failed. To
2bf224
workaround that, we activate PF first via `NmProfile.ACTION_SRIOV_PF`
2bf224
and wait on it before start VF activation.
2bf224
2bf224
Also problem found during SR-IOV investigations is we do extra
2bf224
un-required modification to `NM.SettingOvsExternalIDs` even it is not
2bf224
mentioned in desired. We skip overriding `NM.SettingOvsExternalIDs` when
2bf224
not desired.
2bf224
2bf224
Existing test case can cover the use cases.
2bf224
2bf224
Signed-off-by: Gris Ge <fge@redhat.com>
2bf224
---
2bf224
 libnmstate/ifaces/ifaces.py | 18 +++++++++++++++++-
2bf224
 libnmstate/netapplier.py    | 20 +++++++++++---------
2bf224
 libnmstate/nm/connection.py |  2 +-
2bf224
 libnmstate/nm/profile.py    | 12 ++++++++++--
2bf224
 4 files changed, 39 insertions(+), 13 deletions(-)
2bf224
2bf224
diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
2bf224
index 828ff578..470dc0e6 100644
2bf224
--- a/libnmstate/ifaces/ifaces.py
2bf224
+++ b/libnmstate/ifaces/ifaces.py
2bf224
@@ -157,6 +157,23 @@ class Ifaces:
2bf224
     def has_vf_count_change_and_missing_eth(self):
2bf224
         return self._has_vf_count_change() and self._has_missing_veth()
2bf224
 
2bf224
+    def has_sriov_iface(self):
2bf224
+        for iface in self.all_kernel_ifaces.values():
2bf224
+            if (iface.is_desired or iface.is_changed) and iface.is_up:
2bf224
+                cur_iface = self._cur_kernel_ifaces.get(iface.name)
2bf224
+                if (
2bf224
+                    cur_iface
2bf224
+                    and cur_iface.raw.get(Ethernet.CONFIG_SUBTREE, {}).get(
2bf224
+                        Ethernet.SRIOV_SUBTREE, {}
2bf224
+                    )
2bf224
+                ) or iface.original_desire_dict.get(
2bf224
+                    Ethernet.CONFIG_SUBTREE, {}
2bf224
+                ).get(
2bf224
+                    Ethernet.SRIOV_SUBTREE, {}
2bf224
+                ):
2bf224
+                    return True
2bf224
+        return False
2bf224
+
2bf224
     def _has_vf_count_change(self):
2bf224
         for iface in self.all_kernel_ifaces.values():
2bf224
             cur_iface = self._cur_kernel_ifaces.get(iface.name)
2bf224
@@ -664,7 +681,6 @@ class Ifaces:
2bf224
         return None
2bf224
 
2bf224
     def get_cur_iface(self, iface_name, iface_type):
2bf224
-
2bf224
         iface = self._cur_kernel_ifaces.get(iface_name)
2bf224
         if iface and iface_type in (None, InterfaceType.UNKNOWN, iface.type):
2bf224
             return iface
2bf224
diff --git a/libnmstate/netapplier.py b/libnmstate/netapplier.py
2bf224
index ae909126..50a70a9c 100644
2bf224
--- a/libnmstate/netapplier.py
2bf224
+++ b/libnmstate/netapplier.py
2bf224
@@ -104,7 +104,7 @@ def apply(
2bf224
                     pf_net_state,
2bf224
                     verify_change,
2bf224
                     save_to_disk,
2bf224
-                    has_sriov_pf=True,
2bf224
+                    VERIFY_RETRY_COUNT_SRIOV,
2bf224
                 )
2bf224
                 # Refresh the current state
2bf224
                 current_state = show_with_plugins(
2bf224
@@ -120,8 +120,16 @@ def apply(
2bf224
                     current_state,
2bf224
                     save_to_disk,
2bf224
                 )
2bf224
+
2bf224
+        if net_state.ifaces.has_sriov_iface():
2bf224
+            # If SR-IOV is present, the verification timeout is being increased
2bf224
+            # to avoid timeouts due to slow drivers like i40e.
2bf224
+            verify_retry = VERIFY_RETRY_COUNT_SRIOV
2bf224
+        else:
2bf224
+            verify_retry = VERIFY_RETRY_COUNT
2bf224
+
2bf224
         _apply_ifaces_state(
2bf224
-            plugins, net_state, verify_change, save_to_disk, has_sriov_pf=False
2bf224
+            plugins, net_state, verify_change, save_to_disk, verify_retry
2bf224
         )
2bf224
         if commit:
2bf224
             destroy_checkpoints(plugins, checkpoints)
2bf224
@@ -154,7 +162,7 @@ def rollback(*, checkpoint=None):
2bf224
 
2bf224
 
2bf224
 def _apply_ifaces_state(
2bf224
-    plugins, net_state, verify_change, save_to_disk, has_sriov_pf=False
2bf224
+    plugins, net_state, verify_change, save_to_disk, verify_retry
2bf224
 ):
2bf224
     for plugin in plugins:
2bf224
         # Do not allow plugin to modify the net_state for future verification
2bf224
@@ -163,12 +171,6 @@ def _apply_ifaces_state(
2bf224
 
2bf224
     verified = False
2bf224
     if verify_change:
2bf224
-        if has_sriov_pf:
2bf224
-            # If SR-IOV is present, the verification timeout is being increased
2bf224
-            # to avoid timeouts due to slow drivers like i40e.
2bf224
-            verify_retry = VERIFY_RETRY_COUNT_SRIOV
2bf224
-        else:
2bf224
-            verify_retry = VERIFY_RETRY_COUNT
2bf224
         for _ in range(verify_retry):
2bf224
             try:
2bf224
                 _verify_change(plugins, net_state)
2bf224
diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py
2bf224
index 1fbb380b..6448e372 100644
2bf224
--- a/libnmstate/nm/connection.py
2bf224
+++ b/libnmstate/nm/connection.py
2bf224
@@ -240,7 +240,7 @@ def create_new_nm_simple_conn(iface, nm_profile):
2bf224
             InterfaceType.OVS_PORT,
2bf224
         )
2bf224
         or iface.type == InterfaceType.OVS_BRIDGE
2bf224
-    ):
2bf224
+    ) and OvsDB.OVS_DB_SUBTREE in iface.original_desire_dict:
2bf224
         nm_setting = create_ovsdb_external_ids_setting(
2bf224
             iface_info.get(OvsDB.OVS_DB_SUBTREE, {})
2bf224
         )
2bf224
diff --git a/libnmstate/nm/profile.py b/libnmstate/nm/profile.py
2bf224
index 53eaebed..ad1ad19f 100644
2bf224
--- a/libnmstate/nm/profile.py
2bf224
+++ b/libnmstate/nm/profile.py
2bf224
@@ -56,6 +56,7 @@ ROUTE_REMOVED = "_route_removed"
2bf224
 class NmProfile:
2bf224
     # For unmanged iface and desired to down
2bf224
     ACTION_ACTIVATE_FIRST = "activate_first"
2bf224
+    ACTION_SRIOV_PF = "activate_sriov_pf"
2bf224
     ACTION_DEACTIVATE = "deactivate"
2bf224
     ACTION_DEACTIVATE_FIRST = "deactivate_first"
2bf224
     ACTION_DELETE_DEVICE = "delete_device"
2bf224
@@ -77,6 +78,7 @@ class NmProfile:
2bf224
         ACTION_ACTIVATE_FIRST,
2bf224
         ACTION_DEACTIVATE_FIRST,
2bf224
         ACTION_TOP_CONTROLLER,
2bf224
+        ACTION_SRIOV_PF,
2bf224
         ACTION_NEW_IFACES,
2bf224
         ACTION_OTHER_CONTROLLER,
2bf224
         ACTION_NEW_OVS_PORT,
2bf224
@@ -181,6 +183,11 @@ class NmProfile:
2bf224
                 else:
2bf224
                     self._add_action(NmProfile.ACTION_NEW_IFACES)
2bf224
             else:
2bf224
+                if (
2bf224
+                    self._nm_dev.props.capabilities
2bf224
+                    & NM.DeviceCapabilities.SRIOV
2bf224
+                ):
2bf224
+                    self._add_action(NmProfile.ACTION_SRIOV_PF)
2bf224
                 if self._iface.type == InterfaceType.OVS_PORT:
2bf224
                     self._add_action(NmProfile.ACTION_MODIFIED_OVS_PORT)
2bf224
                 if self._iface.type == InterfaceType.OVS_INTERFACE:
2bf224
@@ -462,6 +469,7 @@ class NmProfile:
2bf224
 
2bf224
     def do_action(self, action):
2bf224
         if action in (
2bf224
+            NmProfile.ACTION_SRIOV_PF,
2bf224
             NmProfile.ACTION_MODIFIED,
2bf224
             NmProfile.ACTION_MODIFIED_OVS_PORT,
2bf224
             NmProfile.ACTION_MODIFIED_OVS_IFACE,
2bf224
@@ -559,8 +567,8 @@ class NmProfile:
2bf224
                     or nm_profile.get_connection_type() == self._nm_iface_type
2bf224
                 )
2bf224
                 and (
2bf224
-                    self._nm_profile is None
2bf224
-                    or nm_profile.get_uuid() != self._nm_profile.get_uuid()
2bf224
+                    self._nm_simple_conn is None
2bf224
+                    or nm_profile.get_uuid() != self._nm_simple_conn.get_uuid()
2bf224
                 )
2bf224
             ):
2bf224
                 ProfileDelete(
2bf224
-- 
2bf224
2.39.2
2bf224