diff --git a/.gitignore b/.gitignore
index 4e6d7d9..18b3d9b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-SOURCES/nmstate-0.3.4.tar.gz
+SOURCES/nmstate-1.0.2.tar.gz
 SOURCES/nmstate.gpg
diff --git a/.nmstate.metadata b/.nmstate.metadata
index 3f697a6..a6d3e02 100644
--- a/.nmstate.metadata
+++ b/.nmstate.metadata
@@ -1,2 +1,2 @@
-d732a1ccb1dfc54741a9d602179c809c3223af3a SOURCES/nmstate-0.3.4.tar.gz
+eeda8a0238732e5dc37e2217ed6e316f76c93145 SOURCES/nmstate-1.0.2.tar.gz
 b5f872551d434e2c62b30d70471efaeede83ab44 SOURCES/nmstate.gpg
diff --git a/SOURCES/BZ_1858758-fix_ovs_bond.patch b/SOURCES/BZ_1858758-fix_ovs_bond.patch
deleted file mode 100644
index d71cfcd..0000000
--- a/SOURCES/BZ_1858758-fix_ovs_bond.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 862e669fcfe02b49c0e24af210d6466197962b97 Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Mon, 3 Aug 2020 11:34:44 +0800
-Subject: [PATCH] ovs: Fix bug when adding bond to existing bridge
-
-When adding OVS bond/link aggregation interface to existing OVS bridge,
-nmstate will fail with error:
-
-    > self._ifaces[slave_name].mark_as_changed()
-    E KeyError: 'bond1'
-
-This is because ovs bond interface does not require a interface entry in
-desire state.
-
-Fixed by check before adding dict.
-
-Integration test case added.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/ifaces/ifaces.py | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
-index a400712..1c2ffd5 100644
---- a/libnmstate/ifaces/ifaces.py
-+++ b/libnmstate/ifaces/ifaces.py
-@@ -217,7 +217,8 @@ class Ifaces:
-                     self._ifaces[iface_name].mark_as_changed()
-             if cur_iface:
-                 for slave_name in iface.config_changed_slaves(cur_iface):
--                    self._ifaces[slave_name].mark_as_changed()
-+                    if slave_name in self._ifaces:
-+                        self._ifaces[slave_name].mark_as_changed()
- 
-     def _match_child_iface_state_with_parent(self):
-         """
--- 
-2.28.0
-
diff --git a/SOURCES/BZ_1858762-hide_ovs_patch_port_mtu.patch b/SOURCES/BZ_1858762-hide_ovs_patch_port_mtu.patch
deleted file mode 100644
index 3e5bea9..0000000
--- a/SOURCES/BZ_1858762-hide_ovs_patch_port_mtu.patch
+++ /dev/null
@@ -1,105 +0,0 @@
-From bc2f8445d493f8a5a4ff1ceead13d2b3ac5325cc Mon Sep 17 00:00:00 2001
-From: Fernando Fernandez Mancera <ffmancera@riseup.net>
-Date: Sun, 26 Jul 2020 00:46:16 +0200
-Subject: [PATCH 1/2] nm.wired: do not report MTU if it is 0
-
-If an interface contains an MTU with value 0, Nmstate should not report
-it because it is an special interface like OVS patch port interfaces.
-
-Added a test case for this.
-
-Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
----
- libnmstate/nm/wired.py | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/libnmstate/nm/wired.py b/libnmstate/nm/wired.py
-index 27d4318..64662ac 100644
---- a/libnmstate/nm/wired.py
-+++ b/libnmstate/nm/wired.py
-@@ -124,7 +124,9 @@ def get_info(device):
- 
-     iface = device.get_iface()
-     try:
--        info[Interface.MTU] = int(device.get_mtu())
-+        mtu = int(device.get_mtu())
-+        if mtu:
-+            info[Interface.MTU] = mtu
-     except AttributeError:
-         pass
- 
--- 
-2.27.0
-
-
-From 03aea7d7debfca0f01b60e9f406c9acdf3de3775 Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Mon, 27 Jul 2020 20:51:53 +0800
-Subject: [PATCH 2/2] nm ovs: Raise NmstateNotSupportedError for
- save_to_disk=False
-
-Due to limitation of NetworkManager 1.26, nmstate cannot support
-`save_to_disk=False`(ask, memory only) state for OVS interfaces.
-
-Raise NmstateNotSupportedError if NetworkManager version is older than
-1.28 and has OVS interface in desire state with `save_to_disk=False`.
-
-Integration test case included.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
-Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
----
- libnmstate/nm/applier.py | 23 +++++++++++++++++++++++
- 1 file changed, 23 insertions(+)
-
-diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py
-index 4e20af5..a91cee5 100644
---- a/libnmstate/nm/applier.py
-+++ b/libnmstate/nm/applier.py
-@@ -17,9 +17,11 @@
- # along with this program. If not, see <https://www.gnu.org/licenses/>.
- #
- 
-+from distutils.version import StrictVersion
- import logging
- import itertools
- 
-+from libnmstate.error import NmstateNotSupportedError
- from libnmstate.error import NmstateValueError
- from libnmstate.schema import Interface
- from libnmstate.schema import InterfaceState
-@@ -65,6 +67,17 @@ MASTER_IFACE_TYPES = (
- def apply_changes(context, net_state, save_to_disk):
-     con_profiles = []
- 
-+    if (
-+        not save_to_disk
-+        and _has_ovs_interface_desired_or_changed(net_state)
-+        and StrictVersion(context.client.get_version())
-+        < StrictVersion("1.28.0")
-+    ):
-+        raise NmstateNotSupportedError(
-+            f"NetworkManager version {context.client.get_version()} does not "
-+            f"support 'save_to_disk=False' against OpenvSwitch interface"
-+        )
-+
-     _preapply_dns_fix(context, net_state)
- 
-     ifaces_desired_state = net_state.ifaces.state_to_edit
-@@ -602,3 +615,13 @@ def _preapply_dns_fix(context, net_state):
-         for iface in net_state.ifaces.values():
-             if iface.is_changed or iface.is_desired:
-                 iface.remove_dns_metadata()
-+
-+
-+def _has_ovs_interface_desired_or_changed(net_state):
-+    for iface in net_state.ifaces.values():
-+        if iface.type in (
-+            InterfaceType.OVS_BRIDGE,
-+            InterfaceType.OVS_INTERFACE,
-+            InterfaceType.OVS_PORT,
-+        ) and (iface.is_desired or iface.is_changed):
-+            return True
--- 
-2.27.0
-
diff --git a/SOURCES/BZ_1859844-fix_converting_memory_only.patch b/SOURCES/BZ_1859844-fix_converting_memory_only.patch
deleted file mode 100644
index ef80e65..0000000
--- a/SOURCES/BZ_1859844-fix_converting_memory_only.patch
+++ /dev/null
@@ -1,59 +0,0 @@
-From fc7e6b2329409b95ab1726b7b65f14c284bf67ab Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Mon, 3 Aug 2020 12:07:56 +0800
-Subject: [PATCH] nm: Fix converting memory-only profile to persistent
-
-When converting memory-only profile to persistent using simple desire
-state with `state: up` only, the memory only profile will not be
-converted to persistent.
-
-This is caused by `nm/applier.py` skip profile creation if desire state
-is only `state: up`.
-
-The fix is checking whether current profile's persistent state is equal
-to desired.
-
-Integration test case added.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/nm/applier.py    |  1 +
- libnmstate/nm/connection.py | 10 ++++++++++
- 2 files changed, 11 insertions(+)
-
-diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py
-index 4d40862..26a057f 100644
---- a/libnmstate/nm/applier.py
-+++ b/libnmstate/nm/applier.py
-@@ -125,6 +125,7 @@ def apply_changes(context, net_state, save_to_disk):
-                 and cur_con_profile
-                 and cur_con_profile.profile
-                 and not net_state.ifaces[ifname].is_changed
-+                and cur_con_profile.is_memory_only != save_to_disk
-             ):
-                 # Don't create new profile if original desire does not ask
-                 # anything besides state:up and not been marked as changed.
-diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py
-index 5804f13..1f6c734 100644
---- a/libnmstate/nm/connection.py
-+++ b/libnmstate/nm/connection.py
-@@ -162,6 +162,16 @@ class ConnectionProfile:
-         assert self._con_profile is None
-         self._con_profile = con_profile
- 
-+    @property
-+    def is_memory_only(self):
-+        if self._con_profile:
-+            profile_flags = self._con_profile.get_flags()
-+            return (
-+                NM.SettingsConnectionFlags.UNSAVED & profile_flags
-+                or NM.SettingsConnectionFlags.VOLATILE & profile_flags
-+            )
-+        return False
-+
-     @property
-     def devname(self):
-         if self._con_profile:
--- 
-2.28.0
-
diff --git a/SOURCES/BZ_1861263-handle-external-managed-interface.patch b/SOURCES/BZ_1861263-handle-external-managed-interface.patch
deleted file mode 100644
index dc59dc4..0000000
--- a/SOURCES/BZ_1861263-handle-external-managed-interface.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-From ea7f304cc1ad32c3f2c25b49bf6b2663f348496a Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Tue, 28 Jul 2020 15:59:11 +0800
-Subject: [PATCH] nm: Mark external subordinate as changed
-
-When user create bond with subordinate interfaces using non-NM
-tools(iproute), the NetworkManager will mark the subordinates as
-managed externally.
-
-When the desire state only contains the main interface, nmstate
-noticing the slave list is unchanged, so only activate the main
-interface, then NM remove the subordinate from their main interface.
-
-To workaround that, mark subordinate interfaces as changed when they are
-managed by NM as externally.
-
-Integration test case included.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/nm/applier.py | 24 ++++++++++++++++++++++++
- 1 file changed, 24 insertions(+)
-
-diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py
-index a91cee5..68d11dc 100644
---- a/libnmstate/nm/applier.py
-+++ b/libnmstate/nm/applier.py
-@@ -79,6 +79,7 @@ def apply_changes(context, net_state, save_to_disk):
-         )
- 
-     _preapply_dns_fix(context, net_state)
-+    _mark_nm_external_subordinate_changed(context, net_state)
- 
-     ifaces_desired_state = net_state.ifaces.state_to_edit
-     ifaces_desired_state.extend(
-@@ -625,3 +626,26 @@ def _has_ovs_interface_desired_or_changed(net_state):
-             InterfaceType.OVS_PORT,
-         ) and (iface.is_desired or iface.is_changed):
-             return True
-+
-+
-+def _mark_nm_external_subordinate_changed(context, net_state):
-+    """
-+    When certain main interface contains subordinates is marked as
-+    connected(externally), it means its profile is memory only and will lost
-+    on next deactivation.
-+    For this case, we should mark the subordinate as changed.
-+    that subordinate should be marked as changed for NM to take over.
-+    """
-+    for iface in net_state.ifaces.values():
-+        if iface.type in MASTER_IFACE_TYPES:
-+            for subordinate in iface.slaves:
-+                nmdev = context.get_nm_dev(subordinate)
-+                if nmdev:
-+                    nm_ac = nmdev.get_active_connection()
-+                    if (
-+                        nm_ac
-+                        and NM.ActivationStateFlags.EXTERNAL
-+                        & nm_ac.get_state_flags()
-+                    ):
-+                        subordinate_iface = net_state.ifaces[subordinate]
-+                        subordinate_iface.mark_as_changed()
--- 
-2.27.0
-
diff --git a/SOURCES/BZ_1861668_ignore_unknown_iface.patch b/SOURCES/BZ_1861668_ignore_unknown_iface.patch
deleted file mode 100644
index 665dd7d..0000000
--- a/SOURCES/BZ_1861668_ignore_unknown_iface.patch
+++ /dev/null
@@ -1,200 +0,0 @@
-From a8590744fbdd4bce9ab340ac49a7add31727b990 Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Wed, 29 Jul 2020 17:51:27 +0800
-Subject: [PATCH 1/3] nm applier: Fix external managed interface been marked as
- changed
-
-The net_state passing to `_mark_nm_external_subordinate_changed()`
-does not contain unknown type interface, so the
-`net_state.ifaces[subordinate]` could trigger KeyError as subordinate
-not found.
-
-Changed it to use `get()` and only perform this changes to
-desired/changed interface.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/nm/applier.py | 7 ++++---
- 1 file changed, 4 insertions(+), 3 deletions(-)
-
-diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py
-index 68d11dc..d0fb5f3 100644
---- a/libnmstate/nm/applier.py
-+++ b/libnmstate/nm/applier.py
-@@ -637,7 +637,7 @@ def _mark_nm_external_subordinate_changed(context, net_state):
-     that subordinate should be marked as changed for NM to take over.
-     """
-     for iface in net_state.ifaces.values():
--        if iface.type in MASTER_IFACE_TYPES:
-+        if iface.is_desired or iface.is_changed and iface.is_master:
-             for subordinate in iface.slaves:
-                 nmdev = context.get_nm_dev(subordinate)
-                 if nmdev:
-@@ -647,5 +647,6 @@ def _mark_nm_external_subordinate_changed(context, net_state):
-                         and NM.ActivationStateFlags.EXTERNAL
-                         & nm_ac.get_state_flags()
-                     ):
--                        subordinate_iface = net_state.ifaces[subordinate]
--                        subordinate_iface.mark_as_changed()
-+                        subordinate_iface = net_state.ifaces.get(subordinate)
-+                        if subordinate_iface:
-+                            subordinate_iface.mark_as_changed()
--- 
-2.28.0
-
-
-From 77a05cfe726efc4a4207d57958a71e1730b6d62a Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Wed, 29 Jul 2020 18:02:52 +0800
-Subject: [PATCH 2/3] nm: Ignore externally managed interface for down/absent
- main interface
-
-When main interface been marked as down or absent, its subordinate
-should be also marked as so. NetworkManager plugin should ignore
-externally managed subordinate in this case.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/nm/applier.py | 26 +++++++++++---------------
- libnmstate/nm/device.py  |  8 ++++++++
- 2 files changed, 19 insertions(+), 15 deletions(-)
-
-diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py
-index d0fb5f3..9cd8f9a 100644
---- a/libnmstate/nm/applier.py
-+++ b/libnmstate/nm/applier.py
-@@ -50,6 +50,7 @@ from . import vxlan
- from . import wired
- from .common import NM
- from .dns import get_dns_config_iface_names
-+from .device import is_externally_managed
- 
- 
- MAXIMUM_INTERFACE_LENGTH = 15
-@@ -265,13 +266,14 @@ def _set_ifaces_admin_state(context, ifaces_desired_state, con_profiles):
-                     == InterfaceState.ABSENT
-                 )
-                 for affected_nmdev in nmdevs:
--                    devs_to_deactivate[
--                        affected_nmdev.get_iface()
--                    ] = affected_nmdev
--                    if is_absent:
--                        devs_to_delete_profile[
-+                    if not is_externally_managed(affected_nmdev):
-+                        devs_to_deactivate[
-                             affected_nmdev.get_iface()
-                         ] = affected_nmdev
-+                        if is_absent:
-+                            devs_to_delete_profile[
-+                                affected_nmdev.get_iface()
-+                            ] = affected_nmdev
-                 if (
-                     is_absent
-                     and nmdev.is_software()
-@@ -640,13 +642,7 @@ def _mark_nm_external_subordinate_changed(context, net_state):
-         if iface.is_desired or iface.is_changed and iface.is_master:
-             for subordinate in iface.slaves:
-                 nmdev = context.get_nm_dev(subordinate)
--                if nmdev:
--                    nm_ac = nmdev.get_active_connection()
--                    if (
--                        nm_ac
--                        and NM.ActivationStateFlags.EXTERNAL
--                        & nm_ac.get_state_flags()
--                    ):
--                        subordinate_iface = net_state.ifaces.get(subordinate)
--                        if subordinate_iface:
--                            subordinate_iface.mark_as_changed()
-+                if nmdev and is_externally_managed(nmdev):
-+                    subordinate_iface = net_state.ifaces.get(subordinate)
-+                    if subordinate_iface:
-+                        subordinate_iface.mark_as_changed()
-diff --git a/libnmstate/nm/device.py b/libnmstate/nm/device.py
-index 528f57d..a175b71 100644
---- a/libnmstate/nm/device.py
-+++ b/libnmstate/nm/device.py
-@@ -23,6 +23,7 @@ from libnmstate.error import NmstateLibnmError
- 
- from . import active_connection as ac
- from . import connection
-+from .common import NM
- 
- 
- def activate(context, dev=None, connection_id=None):
-@@ -161,3 +162,10 @@ def get_device_common_info(dev):
-         "type_name": dev.get_type_description(),
-         "state": dev.get_state(),
-     }
-+
-+
-+def is_externally_managed(nmdev):
-+    nm_ac = nmdev.get_active_connection()
-+    return (
-+        nm_ac and NM.ActivationStateFlags.EXTERNAL & nm_ac.get_state_flags()
-+    )
--- 
-2.28.0
-
-
-From afb51e8421b8749962dd9ee2e31b61548de09a78 Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Wed, 29 Jul 2020 18:22:32 +0800
-Subject: [PATCH 3/3] state: Remove unmanaged interface before verifying
-
-Since we remove unknown type interface before sending to apply,
-we should also remove unknown type interface before verifying.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/ifaces/ifaces.py | 9 +++++----
- libnmstate/nm/device.py     | 4 +---
- 2 files changed, 6 insertions(+), 7 deletions(-)
-
-diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
-index 1ff4198..a400712 100644
---- a/libnmstate/ifaces/ifaces.py
-+++ b/libnmstate/ifaces/ifaces.py
-@@ -286,16 +286,16 @@ class Ifaces:
-     def cur_ifaces(self):
-         return self._cur_ifaces
- 
--    def _remove_unmanaged_slaves(self):
-+    def _remove_unknown_interface_type_slaves(self):
-         """
--        When master containing unmanaged slaves, they should be removed from
--        master slave list.
-+        When master containing slaves with unknown interface type, they should
-+        be removed from master slave list before verifying.
-         """
-         for iface in self._ifaces.values():
-             if iface.is_up and iface.is_master and iface.slaves:
-                 for slave_name in iface.slaves:
-                     slave_iface = self._ifaces[slave_name]
--                    if not slave_iface.is_up:
-+                    if slave_iface.type == InterfaceType.UNKNOWN:
-                         iface.remove_slave(slave_name)
- 
-     def verify(self, cur_iface_infos):
-@@ -304,6 +304,7 @@ class Ifaces:
-             cur_iface_infos=cur_iface_infos,
-             save_to_disk=self._save_to_disk,
-         )
-+        cur_ifaces._remove_unknown_interface_type_slaves()
-         for iface in self._ifaces.values():
-             if iface.is_desired:
-                 if iface.is_virtual and iface.original_dict.get(
-diff --git a/libnmstate/nm/device.py b/libnmstate/nm/device.py
-index a175b71..fdf05bc 100644
---- a/libnmstate/nm/device.py
-+++ b/libnmstate/nm/device.py
-@@ -166,6 +166,4 @@ def get_device_common_info(dev):
- 
- def is_externally_managed(nmdev):
-     nm_ac = nmdev.get_active_connection()
--    return (
--        nm_ac and NM.ActivationStateFlags.EXTERNAL & nm_ac.get_state_flags()
--    )
-+    return nm_ac and NM.ActivationStateFlags.EXTERNAL & nm_ac.get_state_flags()
--- 
-2.28.0
-
diff --git a/SOURCES/BZ_1862025-remove_existing_profiles.patch b/SOURCES/BZ_1862025-remove_existing_profiles.patch
deleted file mode 100644
index 2a07082..0000000
--- a/SOURCES/BZ_1862025-remove_existing_profiles.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-From 3c5337a22273717df6fb51818216816bbff77035 Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Thu, 30 Jul 2020 16:54:40 +0800
-Subject: [PATCH] nm profile: Remove inactivate profile of desired interface
-
-For changed/desired interface, NM should remove all its inactive
-profiles so that it could update and activate the same one.
-
-Integration test case included.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/nm/applier.py    | 10 +++++++++-
- libnmstate/nm/connection.py |  9 +++++++--
- 2 files changed, 16 insertions(+), 3 deletions(-)
-
-diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py
-index 9cd8f9a..4d40862 100644
---- a/libnmstate/nm/applier.py
-+++ b/libnmstate/nm/applier.py
-@@ -105,6 +105,15 @@ def apply_changes(context, net_state, save_to_disk):
-                 cur_con_profile = connection.ConnectionProfile(
-                     context, profile=con_profile
-                 )
-+
-+        if save_to_disk:
-+            # TODO: Need handle save_to_disk=False
-+            connection.delete_iface_profiles_except(
-+                context,
-+                ifname,
-+                cur_con_profile.profile if cur_con_profile else None,
-+            )
-+
-         original_desired_iface_state = {}
-         if net_state.ifaces.get(ifname):
-             iface = net_state.ifaces[ifname]
-@@ -137,7 +146,6 @@ def apply_changes(context, net_state, save_to_disk):
-             con_profiles.append(new_con_profile)
-         else:
-             # Missing connection, attempting to create a new one.
--            connection.delete_iface_inactive_connections(context, ifname)
-             new_con_profile.add(save_to_disk)
-             con_profiles.append(new_con_profile)
-     context.wait_all_finish()
-diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py
-index 02890bc..5804f13 100644
---- a/libnmstate/nm/connection.py
-+++ b/libnmstate/nm/connection.py
-@@ -496,9 +496,14 @@ def get_device_active_connection(nm_device):
-     return active_conn
- 
- 
--def delete_iface_inactive_connections(context, ifname):
-+def delete_iface_profiles_except(context, ifname, excluded_profile):
-     for con in list_connections_by_ifname(context, ifname):
--        con.delete()
-+        if (
-+            not excluded_profile
-+            or not con.profile
-+            or con.profile.get_uuid() != excluded_profile.get_uuid()
-+        ):
-+            con.delete()
- 
- 
- def list_connections_by_ifname(context, ifname):
--- 
-2.28.0
-
diff --git a/SOURCES/BZ_1866269-preserve_nm_uuid_in_ovsdb.patch b/SOURCES/BZ_1866269-preserve_nm_uuid_in_ovsdb.patch
deleted file mode 100644
index 214aa8c..0000000
--- a/SOURCES/BZ_1866269-preserve_nm_uuid_in_ovsdb.patch
+++ /dev/null
@@ -1,120 +0,0 @@
-From 21e06fd5af76cc1fe65497222a04c1cffa2bc546 Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Thu, 6 Aug 2020 13:07:59 +0800
-Subject: [PATCH] ovsdb: Preserve the NM external_ids
-
-For newly created OVS internal interface with customer external_ids,
-the ovsdb plugin will remove the NM external_ids `NM.connection.uuid`.
-
-The fix is read the current `NM.connection.uuid` before applying
-configure and merge it with original desired state.
-
-Integration test cases added.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/plugins/nmstate_plugin_ovsdb.py | 69 +++++++++++++---------
- 1 file changed, 40 insertions(+), 29 deletions(-)
-
-diff --git a/libnmstate/plugins/nmstate_plugin_ovsdb.py b/libnmstate/plugins/nmstate_plugin_ovsdb.py
-index 83965e1..12ab10d 100644
---- a/libnmstate/plugins/nmstate_plugin_ovsdb.py
-+++ b/libnmstate/plugins/nmstate_plugin_ovsdb.py
-@@ -161,7 +161,14 @@ class NmstateOvsdbPlugin(NmstatePlugin):
-         return ifaces
- 
-     def apply_changes(self, net_state, save_to_disk):
-+        # State might changed after other plugin invoked apply_changes()
-         self.refresh_content()
-+        cur_iface_to_ext_ids = {}
-+        for iface_info in self.get_interfaces():
-+            cur_iface_to_ext_ids[iface_info[Interface.NAME]] = iface_info[
-+                OvsDB.OVS_DB_SUBTREE
-+            ][OvsDB.EXTERNAL_IDS]
-+
-         pending_changes = []
-         for iface in net_state.ifaces.values():
-             if not iface.is_changed and not iface.is_desired:
-@@ -174,7 +181,34 @@ class NmstateOvsdbPlugin(NmstatePlugin):
-                 table_name = "Interface"
-             else:
-                 continue
--            pending_changes.extend(_generate_db_change(table_name, iface))
-+            ids_after_nm_applied = cur_iface_to_ext_ids.get(iface.name, {})
-+            ids_before_nm_applied = (
-+                iface.to_dict()
-+                .get(OvsDB.OVS_DB_SUBTREE, {})
-+                .get(OvsDB.EXTERNAL_IDS, {})
-+            )
-+            original_desire_ids = iface.original_dict.get(
-+                OvsDB.OVS_DB_SUBTREE, {}
-+            ).get(OvsDB.EXTERNAL_IDS)
-+
-+            desire_ids = []
-+
-+            if original_desire_ids is None:
-+                desire_ids = ids_before_nm_applied
-+            else:
-+                desire_ids = original_desire_ids
-+
-+            # should include external_id created by NetworkManager.
-+            if NM_EXTERNAL_ID in ids_after_nm_applied:
-+                desire_ids[NM_EXTERNAL_ID] = ids_after_nm_applied[
-+                    NM_EXTERNAL_ID
-+                ]
-+            if desire_ids != ids_after_nm_applied:
-+                pending_changes.append(
-+                    _generate_db_change_external_ids(
-+                        table_name, iface.name, desire_ids
-+                    )
-+                )
-         if pending_changes:
-             if not save_to_disk:
-                 raise NmstateNotImplementedError(
-@@ -242,38 +276,15 @@ class NmstateOvsdbPlugin(NmstatePlugin):
-             )
- 
- 
--def _generate_db_change(table_name, iface_state):
--    return _generate_db_change_external_ids(table_name, iface_state)
--
--
--def _generate_db_change_external_ids(table_name, iface_state):
--    pending_changes = []
--    desire_ids = iface_state.original_dict.get(OvsDB.OVS_DB_SUBTREE, {}).get(
--        OvsDB.EXTERNAL_IDS
--    )
-+def _generate_db_change_external_ids(table_name, iface_name, desire_ids):
-     if desire_ids and not isinstance(desire_ids, dict):
-         raise NmstateValueError("Invalid external_ids, should be dictionary")
- 
--    if desire_ids or desire_ids == {}:
--        # should include external_id required by NetworkManager.
--        merged_ids = (
--            iface_state.to_dict()
--            .get(OvsDB.OVS_DB_SUBTREE, {})
--            .get(OvsDB.EXTERNAL_IDS, {})
--        )
--        if NM_EXTERNAL_ID in merged_ids:
--            desire_ids[NM_EXTERNAL_ID] = merged_ids[NM_EXTERNAL_ID]
--
--        # Convert all value to string
--        for key, value in desire_ids.items():
--            desire_ids[key] = str(value)
-+    # Convert all value to string
-+    for key, value in desire_ids.items():
-+        desire_ids[key] = str(value)
- 
--        pending_changes.append(
--            _Changes(
--                table_name, OvsDB.EXTERNAL_IDS, iface_state.name, desire_ids
--            )
--        )
--    return pending_changes
-+    return _Changes(table_name, OvsDB.EXTERNAL_IDS, iface_name, desire_ids)
- 
- 
- NMSTATE_PLUGIN = NmstateOvsdbPlugin
--- 
-2.28.0
-
diff --git a/SOURCES/BZ_1869345_ovsdb_remove_all_ports.patch b/SOURCES/BZ_1869345_ovsdb_remove_all_ports.patch
deleted file mode 100644
index e1a1ac3..0000000
--- a/SOURCES/BZ_1869345_ovsdb_remove_all_ports.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From 913b739c8fea8e9b14d3785371c8e4f48723dbd6 Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Tue, 18 Aug 2020 17:55:12 +0800
-Subject: [PATCH] ovsdb: Allowing remove all ports from OVS bridge
-
-When removing all ports from OVS bridge, the OVSDB will have no
-information regarding this bridge, which cause OVSDB failed to find
-the correct row.
-
-Silently ignore row not found failure and let verification stage do the
-work.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/plugins/nmstate_plugin_ovsdb.py | 8 --------
- 1 file changed, 8 deletions(-)
-
-diff --git a/libnmstate/plugins/nmstate_plugin_ovsdb.py b/libnmstate/plugins/nmstate_plugin_ovsdb.py
-index 12ab10d..f667e8f 100644
---- a/libnmstate/plugins/nmstate_plugin_ovsdb.py
-+++ b/libnmstate/plugins/nmstate_plugin_ovsdb.py
-@@ -222,19 +222,11 @@ class NmstateOvsdbPlugin(NmstatePlugin):
-     def _db_write(self, changes):
-         changes_index = {change.row_name: change for change in changes}
-         changed_tables = set(change.table_name for change in changes)
--        updated_names = []
-         for changed_table in changed_tables:
-             for row in self._idl.tables[changed_table].rows.values():
-                 if row.name in changes_index:
-                     change = changes_index[row.name]
-                     setattr(row, change.column_name, change.column_value)
--                    updated_names.append(change.row_name)
--        new_rows = set(changes_index.keys()) - set(updated_names)
--        if new_rows:
--            raise NmstatePluginError(
--                f"BUG: row {new_rows} does not exists in OVS DB "
--                "and currently we don't create new row"
--            )
- 
-     def _start_transaction(self):
-         self._transaction = Transaction(self._idl)
--- 
-2.28.0
-
diff --git a/SOURCES/BZ_1887349-Allow-duplicate-iface-name-in-ovs.patch b/SOURCES/BZ_1887349-Allow-duplicate-iface-name-in-ovs.patch
deleted file mode 100644
index d47e0d8..0000000
--- a/SOURCES/BZ_1887349-Allow-duplicate-iface-name-in-ovs.patch
+++ /dev/null
@@ -1,111 +0,0 @@
-From 36ee761dd0d671439323077e4f77a89071fdcd9c Mon Sep 17 00:00:00 2001
-From: Edward Haas <edwardh@redhat.com>
-Date: Wed, 7 Oct 2020 20:13:12 +0300
-Subject: [PATCH 1/2] nm, bridge, ovs: Collect only existing profiles
-
-During the reporting flow, connections that are in teardown process
-no longer point to a valid profile. Avoid collecting such profiles (in
-practice, these are actually `None` objects).
-
-Signed-off-by: Edward Haas <edwardh@redhat.com>
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/nm/bridge.py | 6 +++---
- libnmstate/nm/ovs.py    | 4 +++-
- 2 files changed, 6 insertions(+), 4 deletions(-)
-
-diff --git a/libnmstate/nm/bridge.py b/libnmstate/nm/bridge.py
-index b885f7a..0ca6c2d 100644
---- a/libnmstate/nm/bridge.py
-+++ b/libnmstate/nm/bridge.py
-@@ -260,9 +260,9 @@ def _get_slave_profiles_by_name(master_device):
-     for dev in master_device.get_slaves():
-         active_con = connection.get_device_active_connection(dev)
-         if active_con:
--            slaves_profiles_by_name[
--                dev.get_iface()
--            ] = active_con.props.connection
-+            profile = active_con.props.connection
-+            if profile:
-+                slaves_profiles_by_name[dev.get_iface()] = profile
-     return slaves_profiles_by_name
- 
- 
-diff --git a/libnmstate/nm/ovs.py b/libnmstate/nm/ovs.py
-index 2518773..eb373c3 100644
---- a/libnmstate/nm/ovs.py
-+++ b/libnmstate/nm/ovs.py
-@@ -279,5 +279,7 @@ def _get_slave_profiles(master_device, devices_info):
-         if active_con:
-             master = active_con.props.master
-             if master and (master.get_iface() == master_device.get_iface()):
--                slave_profiles.append(active_con.props.connection)
-+                profile = active_con.props.connection
-+                if profile:
-+                    slave_profiles.append(profile)
-     return slave_profiles
--- 
-2.28.0
-
-
-From caf638d75e57da8770cd884782475f1c5668fd6d Mon Sep 17 00:00:00 2001
-From: Edward Haas <edwardh@redhat.com>
-Date: Wed, 7 Oct 2020 12:26:42 +0300
-Subject: [PATCH 2/2] nm, ovs: Fix report crash when OVS has dup iface names
-
-In case of an existing OVS deployment which uses an identical name for
-the bridge, port and interface, libnmstate.show() exploded.
-
-It is now possible to report such deployments.
-
-Signed-off-by: Edward Haas <edwardh@redhat.com>
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/nm/ovs.py | 24 +++++++++++++++++++++---
- 1 file changed, 21 insertions(+), 3 deletions(-)
-
-diff --git a/libnmstate/nm/ovs.py b/libnmstate/nm/ovs.py
-index eb373c3..d1f26ba 100644
---- a/libnmstate/nm/ovs.py
-+++ b/libnmstate/nm/ovs.py
-@@ -140,7 +140,12 @@ def get_port_by_slave(nmdev):
- 
- 
- def get_ovs_info(context, bridge_device, devices_info):
--    port_profiles = _get_slave_profiles(bridge_device, devices_info)
-+    ovs_ports_info = (
-+        info
-+        for info in devices_info
-+        if is_ovs_port_type_id(info[1]["type_id"])
-+    )
-+    port_profiles = _get_slave_profiles(bridge_device, ovs_ports_info)
-     ports = _get_bridge_ports_info(context, port_profiles, devices_info)
-     options = _get_bridge_options(context, bridge_device)
- 
-@@ -203,8 +208,21 @@ def _get_bridge_port_info(context, port_profile, devices_info):
-     vlan_mode = port_setting.props.vlan_mode
- 
-     port_name = port_profile.get_interface_name()
--    port_device = context.get_nm_dev(port_name)
--    port_slave_profiles = _get_slave_profiles(port_device, devices_info)
-+    port_device = next(
-+        dev
-+        for dev, devinfo in devices_info
-+        if devinfo["name"] == port_name
-+        and is_ovs_port_type_id(devinfo["type_id"])
-+    )
-+    devices_info_excluding_bridges_and_ports = (
-+        info
-+        for info in devices_info
-+        if not is_ovs_bridge_type_id(info[1]["type_id"])
-+        and not is_ovs_port_type_id(info[1]["type_id"])
-+    )
-+    port_slave_profiles = _get_slave_profiles(
-+        port_device, devices_info_excluding_bridges_and_ports
-+    )
-     port_slave_names = [c.get_interface_name() for c in port_slave_profiles]
- 
-     if port_slave_names:
--- 
-2.28.0
-
diff --git a/SOURCES/BZ_1890497-nm-bond-Ignore-ad_actor_system-00-00-00-00-00-00.patch b/SOURCES/BZ_1890497-nm-bond-Ignore-ad_actor_system-00-00-00-00-00-00.patch
deleted file mode 100644
index 986aab9..0000000
--- a/SOURCES/BZ_1890497-nm-bond-Ignore-ad_actor_system-00-00-00-00-00-00.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From 8a7f1758da4cba81d65ba4b9b06bbf4b750a6f87 Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Thu, 22 Oct 2020 14:09:27 +0800
-Subject: [PATCH 1/2] nm bond: Ignore ad_actor_system=00:00:00:00:00:00
-
-The ad_actor_system=00:00:00:00:00:00 is invalid in kernel as that's the
-default value of ad_actor_system.
-
-NM plugin should not set that value.
-
-Test case included.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
-Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
----
- libnmstate/nm/bond.py             |  9 +++++++++
- tests/integration/nm/bond_test.py | 12 ++++++++++++
- 2 files changed, 21 insertions(+)
-
-diff --git a/libnmstate/nm/bond.py b/libnmstate/nm/bond.py
-index 9ea3648..d196965 100644
---- a/libnmstate/nm/bond.py
-+++ b/libnmstate/nm/bond.py
-@@ -38,6 +38,8 @@ NM_SUPPORTED_BOND_OPTIONS = NM.SettingBond.get_valid_options(
- 
- SYSFS_BOND_OPTION_FOLDER_FMT = "/sys/class/net/{ifname}/bonding"
- 
-+BOND_AD_ACTOR_SYSTEM_USE_BOND_MAC = "00:00:00:00:00:00"
-+
- 
- def create_setting(options, wired_setting):
-     bond_setting = NM.SettingBond.new()
-@@ -48,6 +50,13 @@ def create_setting(options, wired_setting):
-         ):
-             # When in MAC restricted mode, MAC address should be unset.
-             wired_setting.props.cloned_mac_address = None
-+        if (
-+            option_name == "ad_actor_system"
-+            and option_value == BOND_AD_ACTOR_SYSTEM_USE_BOND_MAC
-+        ):
-+            # The all zero ad_actor_system is the kernel default value
-+            # And it is invalid to set as all zero
-+            continue
-         if option_value != SYSFS_EMPTY_VALUE:
-             success = bond_setting.add_option(option_name, str(option_value))
-             if not success:
--- 
-2.25.4
-
diff --git a/SOURCES/BZ_1890497-nm.ipv6-call-clear_routing_rules-when-creating-the-s.patch b/SOURCES/BZ_1890497-nm.ipv6-call-clear_routing_rules-when-creating-the-s.patch
deleted file mode 100644
index 5c6f4b5..0000000
--- a/SOURCES/BZ_1890497-nm.ipv6-call-clear_routing_rules-when-creating-the-s.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 46104725c121def5d85f492afd91e618c1c7c240 Mon Sep 17 00:00:00 2001
-From: Fernando Fernandez Mancera <ffmancera@riseup.net>
-Date: Tue, 27 Oct 2020 12:23:18 +0100
-Subject: [PATCH 2/2] nm.ipv6: call clear_routing_rules() when creating the
- setting
-
-In order to remove IPv6 routing rules Nmstate needs to call
-clear_routing_rules() on the IPv6 setting as it is done on the IPv4
-setting.
-
-Added a testcase for this.
-
-Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
----
- libnmstate/nm/ipv6.py           |  1 +
- tests/integration/route_test.py | 15 +++++++++++++++
- 2 files changed, 16 insertions(+)
-
-diff --git a/libnmstate/nm/ipv6.py b/libnmstate/nm/ipv6.py
-index f252578..9777c89 100644
---- a/libnmstate/nm/ipv6.py
-+++ b/libnmstate/nm/ipv6.py
-@@ -106,6 +106,7 @@ def create_setting(config, base_con_profile):
-             setting_ip.props.never_default = False
-             setting_ip.props.ignore_auto_dns = False
-             setting_ip.clear_routes()
-+            setting_ip.clear_routing_rules()
-             setting_ip.props.gateway = None
-             setting_ip.props.route_table = Route.USE_DEFAULT_ROUTE_TABLE
-             setting_ip.props.route_metric = Route.USE_DEFAULT_METRIC
--- 
-2.25.4
-
diff --git a/SOURCES/BZ_1901571_do_not_check_ovs_daemon_when_showing.patch b/SOURCES/BZ_1901571_do_not_check_ovs_daemon_when_showing.patch
deleted file mode 100644
index 5a91b83..0000000
--- a/SOURCES/BZ_1901571_do_not_check_ovs_daemon_when_showing.patch
+++ /dev/null
@@ -1,103 +0,0 @@
-From 2595c75cb8488e855fc5d98bcc944c6c0ad96b54 Mon Sep 17 00:00:00 2001
-From: Quique Llorente <ellorent@redhat.com>
-Date: Tue, 24 Nov 2020 12:52:35 +0100
-Subject: [PATCH 1/2] ovs: Ignore ovs-port always
-
-At containerize nmstate we cannot run "systemctl openvswitch status" so
-even with a openvswitch running at host it will appear as non running
-but the ovs information will arrive from NM dbus interface. This breaks
-nmstatectl show since ovs-port is not part of nmstate and is not
-included in the schema. This change just ignore ovs-port even if
-openvswitch appear as not running.
-
-Signed-off-by: Quique Llorente <ellorent@redhat.com>
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/nm/plugin.py | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/libnmstate/nm/plugin.py b/libnmstate/nm/plugin.py
-index 4032359..6b6217d 100644
---- a/libnmstate/nm/plugin.py
-+++ b/libnmstate/nm/plugin.py
-@@ -123,6 +123,8 @@ class NetworkManagerPlugin(NmstatePlugin):
-             if nm_bond.is_bond_type_id(type_id):
-                 bondinfo = nm_bond.get_bond_info(dev)
-                 iface_info.update(_ifaceinfo_bond(bondinfo))
-+            elif nm_ovs.is_ovs_port_type_id(type_id):
-+                continue
-             elif NmstatePlugin.OVS_CAPABILITY in capabilities:
-                 if nm_ovs.is_ovs_bridge_type_id(type_id):
-                     iface_info["bridge"] = nm_ovs.get_ovs_info(
-@@ -133,8 +135,6 @@ class NetworkManagerPlugin(NmstatePlugin):
-                     )
-                 elif nm_ovs.is_ovs_interface_type_id(type_id):
-                     iface_info.update(nm_ovs.get_interface_info(act_con))
--                elif nm_ovs.is_ovs_port_type_id(type_id):
--                    continue
- 
-             info.append(iface_info)
- 
--- 
-2.29.2
-
-
-From 3202bdd08737087160ff96bcf921793ce6b8335c Mon Sep 17 00:00:00 2001
-From: Quique Llorente <ellorent@redhat.com>
-Date: Wed, 25 Nov 2020 10:28:43 +0100
-Subject: [PATCH 2/2] ovs: Ignore OVS capabilities at get interfaces
-
-At containerize nmstate we cannot run "systemctl openvswitch status" so
-even with a openvswitch running at host it will appear as non running
-but the ovs information will arrive from NM dbus interface. This breaks
-nmstatectl show since ovs-port is not part of nmstate and is not
-included in the schema. This change removed the whole OVS compatibility check
-when processing the interfaces reporting.
-
-Signed-off-by: Quique Llorente <ellorent@redhat.com>
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/nm/plugin.py | 18 +++++++-----------
- 1 file changed, 7 insertions(+), 11 deletions(-)
-
-diff --git a/libnmstate/nm/plugin.py b/libnmstate/nm/plugin.py
-index 6b6217d..06a5acd 100644
---- a/libnmstate/nm/plugin.py
-+++ b/libnmstate/nm/plugin.py
-@@ -97,7 +97,6 @@ class NetworkManagerPlugin(NmstatePlugin):
- 
-     def get_interfaces(self):
-         info = []
--        capabilities = self.capabilities
- 
-         devices_info = [
-             (dev, nm_device.get_device_common_info(dev))
-@@ -123,18 +122,15 @@ class NetworkManagerPlugin(NmstatePlugin):
-             if nm_bond.is_bond_type_id(type_id):
-                 bondinfo = nm_bond.get_bond_info(dev)
-                 iface_info.update(_ifaceinfo_bond(bondinfo))
-+            elif nm_ovs.is_ovs_bridge_type_id(type_id):
-+                iface_info["bridge"] = nm_ovs.get_ovs_info(
-+                    self.context, dev, devices_info
-+                )
-+                iface_info = _remove_ovs_bridge_unsupported_entries(iface_info)
-+            elif nm_ovs.is_ovs_interface_type_id(type_id):
-+                iface_info.update(nm_ovs.get_interface_info(act_con))
-             elif nm_ovs.is_ovs_port_type_id(type_id):
-                 continue
--            elif NmstatePlugin.OVS_CAPABILITY in capabilities:
--                if nm_ovs.is_ovs_bridge_type_id(type_id):
--                    iface_info["bridge"] = nm_ovs.get_ovs_info(
--                        self.context, dev, devices_info
--                    )
--                    iface_info = _remove_ovs_bridge_unsupported_entries(
--                        iface_info
--                    )
--                elif nm_ovs.is_ovs_interface_type_id(type_id):
--                    iface_info.update(nm_ovs.get_interface_info(act_con))
- 
-             info.append(iface_info)
- 
--- 
-2.29.2
-
diff --git a/SOURCES/BZ_1904889-do-not-remove-unmanaged-ovs-bridge.patch b/SOURCES/BZ_1904889-do-not-remove-unmanaged-ovs-bridge.patch
deleted file mode 100644
index e54c13f..0000000
--- a/SOURCES/BZ_1904889-do-not-remove-unmanaged-ovs-bridge.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From d7393d40aaedeea5dd8291519cddeecdfdabc849 Mon Sep 17 00:00:00 2001
-From: Fernando Fernandez Mancera <ffmancera@riseup.net>
-Date: Mon, 7 Dec 2020 00:51:19 +0100
-Subject: [PATCH] ifaces: do not remove unmanaged orphan interfaces
-
-If there are unmanaged OVS interface present in the network state, NM
-may report uncomplete information. Therefore, nmstate could consider
-them as orphan and remove it when modifying the network state.
-
-In order to fix this, nmstate should not consider it orphan and remove
-it when it is not on desired state or marked as changed.
-
-Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/ifaces/ifaces.py | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
-index 1c2ffd5..703e672 100644
---- a/libnmstate/ifaces/ifaces.py
-+++ b/libnmstate/ifaces/ifaces.py
-@@ -242,8 +242,10 @@ class Ifaces:
- 
-     def _mark_orphen_as_absent(self):
-         for iface in self._ifaces.values():
--            if iface.need_parent and (
--                not iface.parent or not self._ifaces.get(iface.parent)
-+            if (
-+                iface.need_parent
-+                and (not iface.parent or not self._ifaces.get(iface.parent))
-+                and (iface.is_desired or iface.is_changed)
-             ):
-                 iface.mark_as_changed()
-                 iface.state = InterfaceState.ABSENT
--- 
-2.18.4
-
diff --git a/SOURCES/BZ_1908724-sriov-use-verification-retry-to-wait-VF-been-created.patch b/SOURCES/BZ_1908724-sriov-use-verification-retry-to-wait-VF-been-created.patch
deleted file mode 100644
index 8427fbd..0000000
--- a/SOURCES/BZ_1908724-sriov-use-verification-retry-to-wait-VF-been-created.patch
+++ /dev/null
@@ -1,185 +0,0 @@
-From 1d0656c4197f0119d156b0df7b13bffeb5c46861 Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Mon, 4 Jan 2021 11:37:18 +0800
-Subject: [PATCH] sriov: Use verification retry to wait VF been created
-
-When reactivating i40e interface with SR-IOV enabled, the kernel
-takes some time(1 seconds or more in my test) to get the VF interface
-ready in kernel. So at the time of libnmstate returns with success, the
-VF interface might not be ready for use yet.
-
-To fix that, we include VF interfaces in desire state when PV is
-changed/desired. The verification retry will wait the VF to be ready for
-use.
-
-Unit test case and integration test case included.
-
-Also fixed SRIOV integration test cases which are now all passing on i40e
-NIC.
-
-To test on real SRIOV NIC:
-
-    cd tests/integration/
-    sudo env TEST_REAL_NIC=ens1f1 pytest-3 sriov_test.py -vvv
-
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/ifaces/ethernet.py   |  28 ++++
- libnmstate/ifaces/ifaces.py     |  23 +++
- libnmstate/nm/sriov.py          |   2 +-
- libnmstate/nm/wired.py          |  19 ++-
- tests/integration/sriov_test.py | 242 ++++++++++++++++++++++----------
- tests/lib/nm/wired_test.py      |   5 +
- 6 files changed, 231 insertions(+), 88 deletions(-)
-
-diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py
-index b346c36..644fe6d 100644
---- a/libnmstate/ifaces/ethernet.py
-+++ b/libnmstate/ifaces/ethernet.py
-@@ -18,6 +18,9 @@
- #
- 
- 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
- 
-@@ -46,6 +49,31 @@ class EthernetIface(BaseIface):
-         _capitalize_sriov_vf_mac(state)
-         return state
- 
-+    @property
-+    def sriov_total_vfs(self):
-+        return (
-+            self.raw.get(Ethernet.CONFIG_SUBTREE, {})
-+            .get(Ethernet.SRIOV_SUBTREE, {})
-+            .get(Ethernet.SRIOV.TOTAL_VFS, 0)
-+        )
-+
-+    def create_sriov_vf_ifaces(self):
-+        return [
-+            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"{self.name}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)
-+        ]
-+
- 
- def _capitalize_sriov_vf_mac(state):
-     vfs = (
-diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
-index 703e672..7723f43 100644
---- a/libnmstate/ifaces/ifaces.py
-+++ b/libnmstate/ifaces/ifaces.py
-@@ -97,6 +97,7 @@ class Ifaces:
-                 self._ifaces[iface.name] = iface
- 
-             self._create_virtual_slaves()
-+            self._create_sriov_vfs_when_changed()
-             self._validate_unknown_slaves()
-             self._validate_unknown_parent()
-             self._gen_metadata()
-@@ -124,6 +125,28 @@ class Ifaces:
-         for iface in new_ifaces:
-             self._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._ifaces.values():
-+            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():
-+                    if new_iface.name not in self._ifaces:
-+                        new_iface.mark_as_desired()
-+                        new_ifaces.append(new_iface)
-+        for new_iface in new_ifaces:
-+            self._ifaces[new_iface.name] = new_iface
-+
-     def _pre_edit_validation_and_cleanup(self):
-         self._validate_over_booked_slaves()
-         self._validate_vlan_mtu()
-diff --git a/libnmstate/nm/sriov.py b/libnmstate/nm/sriov.py
-index f544732..25b150c 100644
---- a/libnmstate/nm/sriov.py
-+++ b/libnmstate/nm/sriov.py
-@@ -68,7 +68,7 @@ def create_setting(context, iface_state, base_con_profile):
-     sriov_config = iface_state.get(Ethernet.CONFIG_SUBTREE, {}).get(
-         Ethernet.SRIOV_SUBTREE
-     )
--    if sriov_config:
-+    if sriov_config and sriov_config.get(Ethernet.SRIOV.TOTAL_VFS):
-         if not _has_sriov_capability(context, ifname):
-             raise NmstateNotSupportedError(
-                 f"Interface '{ifname}' does not support SR-IOV"
-diff --git a/libnmstate/nm/wired.py b/libnmstate/nm/wired.py
-index 64662ac..5fea2a5 100644
---- a/libnmstate/nm/wired.py
-+++ b/libnmstate/nm/wired.py
-@@ -162,15 +162,18 @@ def _get_mac_address_from_sysfs(ifname):
- 
- 
- def _get_ethernet_info(device, iface):
-+
-     ethernet = {}
-+    sriov_info = sriov.get_info(device)
-+    if sriov_info:
-+        ethernet.update(sriov_info)
-+
-     try:
-         speed = int(device.get_speed())
-         if speed > 0:
-             ethernet[Ethernet.SPEED] = speed
--        else:
--            return None
-     except AttributeError:
--        return None
-+        pass
- 
-     ethtool_results = minimal_ethtool(iface)
-     auto_setting = ethtool_results[Ethernet.AUTO_NEGOTIATION]
-@@ -178,17 +181,11 @@ def _get_ethernet_info(device, iface):
-         ethernet[Ethernet.AUTO_NEGOTIATION] = True
-     elif auto_setting is False:
-         ethernet[Ethernet.AUTO_NEGOTIATION] = False
--    else:
--        return None
- 
-     duplex_setting = ethtool_results[Ethernet.DUPLEX]
-     if duplex_setting in [Ethernet.HALF_DUPLEX, Ethernet.FULL_DUPLEX]:
-         ethernet[Ethernet.DUPLEX] = duplex_setting
--    else:
--        return None
--
--    sriov_info = sriov.get_info(device)
--    if sriov_info:
--        ethernet.update(sriov_info)
- 
-+    if not ethernet:
-+        return None
-     return ethernet
- 
- 
--- 
-2.25.4
-
diff --git a/SOURCES/BZ_1910193-support-multiple-gateways.patch b/SOURCES/BZ_1910193-support-multiple-gateways.patch
deleted file mode 100644
index b9aa129..0000000
--- a/SOURCES/BZ_1910193-support-multiple-gateways.patch
+++ /dev/null
@@ -1,92 +0,0 @@
-From 47bd6db50e33aaa3d3d5e3b70d5f3039122b3a5c Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Sat, 5 Sep 2020 00:36:41 +0800
-Subject: [PATCH] nm route: Add support of multiple gateways
-
-Since NetworkManager 1.22.0, the `NM.SettingIPConfig.props.routes`
-support assigning multiple gateway.
-
-Integration test case updated for this.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/nm/route.py | 30 +++---------------------------
- 1 file changed, 3 insertions(+), 27 deletions(-)
-
-diff --git a/libnmstate/nm/route.py b/libnmstate/nm/route.py
-index 53bcf7c..548b218 100644
---- a/libnmstate/nm/route.py
-+++ b/libnmstate/nm/route.py
-@@ -21,7 +21,6 @@ from operator import itemgetter
- import socket
- 
- from libnmstate import iplib
--from libnmstate.error import NmstateNotImplementedError
- from libnmstate.error import NmstateValueError
- from libnmstate.nm import active_connection as nm_ac
- from libnmstate.schema import Interface
-@@ -31,7 +30,6 @@ from libnmstate.schema import RouteRule
- from .common import GLib
- from .common import NM
- 
--NM_ROUTE_TABLE_ATTRIBUTE = "table"
- IPV4_DEFAULT_GATEWAY_DESTINATION = "0.0.0.0/0"
- IPV6_DEFAULT_GATEWAY_DESTINATION = "::/0"
- 
-@@ -116,7 +114,7 @@ def get_config(acs_and_ip_profiles):
- 
- 
- def _get_per_route_table_id(nm_route, default_table_id):
--    table = nm_route.get_attribute(NM_ROUTE_TABLE_ATTRIBUTE)
-+    table = nm_route.get_attribute(NM.IP_ROUTE_ATTRIBUTE_TABLE)
-     return int(table.get_uint32()) if table else default_table_id
- 
- 
-@@ -152,19 +150,7 @@ def _get_default_route_config(gateway, metric, default_table_id, iface_name):
- 
- def add_routes(setting_ip, routes):
-     for route in routes:
--        if route[Route.DESTINATION] in (
--            IPV4_DEFAULT_GATEWAY_DESTINATION,
--            IPV6_DEFAULT_GATEWAY_DESTINATION,
--        ):
--            if setting_ip.get_gateway():
--                raise NmstateNotImplementedError(
--                    "Only a single default gateway is supported due to a "
--                    "limitation of NetworkManager: "
--                    "https://bugzilla.redhat.com/1707396"
--                )
--            _add_route_gateway(setting_ip, route)
--        else:
--            _add_specfic_route(setting_ip, route)
-+        _add_specfic_route(setting_ip, route)
- 
- 
- def _add_specfic_route(setting_ip, route):
-@@ -181,22 +167,12 @@ def _add_specfic_route(setting_ip, route):
-     )
-     table_id = route.get(Route.TABLE_ID, Route.USE_DEFAULT_ROUTE_TABLE)
-     ip_route.set_attribute(
--        NM_ROUTE_TABLE_ATTRIBUTE, GLib.Variant.new_uint32(table_id)
-+        NM.IP_ROUTE_ATTRIBUTE_TABLE, GLib.Variant.new_uint32(table_id)
-     )
-     # Duplicate route entry will be ignored by libnm.
-     setting_ip.add_route(ip_route)
- 
- 
--def _add_route_gateway(setting_ip, route):
--    setting_ip.props.gateway = route[Route.NEXT_HOP_ADDRESS]
--    setting_ip.props.route_table = route.get(
--        Route.TABLE_ID, Route.USE_DEFAULT_ROUTE_TABLE
--    )
--    setting_ip.props.route_metric = route.get(
--        Route.METRIC, Route.USE_DEFAULT_METRIC
--    )
--
--
- def get_static_gateway_iface(family, iface_routes):
-     """
-     Return one interface with gateway for given IP family.
--- 
-2.27.0
-
diff --git a/SOURCES/BZ_1916073_better-handling-for-timeout.patch b/SOURCES/BZ_1916073_better-handling-for-timeout.patch
deleted file mode 100644
index b47a1d8..0000000
--- a/SOURCES/BZ_1916073_better-handling-for-timeout.patch
+++ /dev/null
@@ -1,419 +0,0 @@
-From 803ad90f11eb57221e7805e5cba8c309bafe1de8 Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Wed, 13 Jan 2021 23:51:31 +0800
-Subject: [PATCH 1/2] nm: Better handling for timeout
-
-When creating 1000 VLAN along with 1000 bridge using each VLAN,
-NetworkManager might trigger two timeout:
-
- * The callback raises `Gio.IOErrorEnum.TIMED_OUT` error.
- * NetworkManager never call callback, nmstate idle check trigger the
-   timeout.
-
-To solve above issue:
-
- * Increase the nmstate idle check timeout to 5 minutes.
-
- * For actions like add profile and activate profile, we add a
-   fallback checker which check whether requested action is already
-   finished using `GLib.timeout_source_new()`
-
- * When `Gio.IOErrorEnum.TIMED_OUT` happens, ignore the failure and wait
-   fallback checker.
-
- * The fallback checker is only started 15 seconds after action started,
-   so this does not impact small desire state.
-
-Test results on RHEL 8.3 i7-8665U 2G RAM:
-
-    10m29.212s to create 1000 VLAN and 1000 bridge over each VLAN.
-
-Changed the integration test case to test 500 VLANs + 500 bridges.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/nm/connection.py | 67 ++++++++++++++++++++++++++++++++++++-
- libnmstate/nm/context.py    |  3 +-
- 2 files changed, 67 insertions(+), 3 deletions(-)
-
-diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py
-index 1f6c734..374a379 100644
---- a/libnmstate/nm/connection.py
-+++ b/libnmstate/nm/connection.py
-@@ -1,5 +1,5 @@
- #
--# Copyright (c) 2018-2020 Red Hat, Inc.
-+# Copyright (c) 2018-2021 Red Hat, Inc.
- #
- # This file is part of nmstate
- #
-@@ -24,11 +24,14 @@ from libnmstate.error import NmstateLibnmError
- from libnmstate.error import NmstateInternalError
- from libnmstate.error import NmstateValueError
- 
-+from .common import GLib
-+from .common import Gio
- from .common import NM
- from . import ipv4
- from . import ipv6
- 
- ACTIVATION_TIMEOUT_FOR_BRIDGE = 35  # Bridge STP requires 30 seconds.
-+FALLBACK_CHECKER_INTERNAL = 15
- 
- 
- class ConnectionProfile:
-@@ -40,6 +43,7 @@ class ConnectionProfile:
-         self._nm_ac = None
-         self._ac_handlers = set()
-         self._dev_handlers = set()
-+        self._fallback_checker = None
- 
-     def create(self, settings):
-         self.profile = NM.SimpleConnection.new()
-@@ -102,6 +106,26 @@ class ConnectionProfile:
-             self._add_connection2_callback,
-             user_data,
-         )
-+        self._fallback_checker = GLib.timeout_source_new(
-+            FALLBACK_CHECKER_INTERNAL * 1000
-+        )
-+        self._fallback_checker.set_callback(
-+            self._profile_add_fallback_checker_callback, action
-+        )
-+        self._fallback_checker.attach(self._ctx.context)
-+
-+    def _profile_add_fallback_checker_callback(self, action):
-+        for nm_profile in self._ctx.client.get_connections():
-+            if nm_profile.get_uuid() == self.profile.get_uuid():
-+                self._fallback_checker_cleanup()
-+                self._ctx.finish_async(action)
-+                return GLib.SOURCE_REMOVE
-+        return GLib.SOURCE_CONTINUE
-+
-+    def _fallback_checker_cleanup(self):
-+        if self._fallback_checker:
-+            self._fallback_checker.destroy()
-+            self._fallback_checker = None
- 
-     def delete(self):
-         if not self.profile:
-@@ -152,6 +176,26 @@ class ConnectionProfile:
-             self._active_connection_callback,
-             user_data,
-         )
-+        self._fallback_checker = GLib.timeout_source_new(
-+            FALLBACK_CHECKER_INTERNAL * 1000
-+        )
-+        self._fallback_checker.set_callback(
-+            self._activation_fallback_checker_callback, action
-+        )
-+        self._fallback_checker.attach(self._ctx.context)
-+
-+    def _activation_fallback_checker_callback(self, action):
-+        if self.devname:
-+            self._nm_dev = self._ctx.get_nm_dev(self.devname)
-+            if self._nm_dev:
-+                self._activation_progress_check(action)
-+            return GLib.SOURCE_CONTINUE
-+        else:
-+            logging.warn(
-+                "Failed to get interface name from profile, "
-+                "can not perform flalback check on activation"
-+            )
-+            return GLib.SOURCE_REMOVE
- 
-     @property
-     def profile(self):
-@@ -213,6 +257,18 @@ class ConnectionProfile:
- 
-         try:
-             nm_act_con = src_object.activate_connection_finish(result)
-+        except GLib.Error as e:
-+            if e.matches(Gio.io_error_quark(), Gio.IOErrorEnum.TIMED_OUT):
-+                logging.debug(
-+                    f"{action} timeout on activation, "
-+                    "using fallback method to wait activation"
-+                )
-+                return
-+            else:
-+                self._ctx.fail(
-+                    NmstateLibnmError(f"{action} failed: error={e}")
-+                )
-+                return
-         except Exception as e:
-             self._ctx.fail(NmstateLibnmError(f"{action} failed: error={e}"))
-             return
-@@ -366,6 +422,7 @@ class ConnectionProfile:
-     def _activation_clean_up(self):
-         self._remove_ac_handlers()
-         self._remove_dev_handlers()
-+        self._fallback_checker_cleanup()
- 
-     def _is_activating(self):
-         if not self._nm_ac or not self._nm_dev:
-@@ -396,6 +453,13 @@ class ConnectionProfile:
-         action = user_data
-         try:
-             profile = src_object.add_connection2_finish(result)[0]
-+        except GLib.Error as e:
-+            if e.matches(Gio.io_error_quark(), Gio.IOErrorEnum.TIMED_OUT):
-+                logging.debug(
-+                    f"{action} timeout, using fallback method to "
-+                    "wait profile creation"
-+                )
-+                return
-         except Exception as e:
-             self._ctx.fail(
-                 NmstateLibnmError(f"{action} failed with error: {e}")
-@@ -410,6 +474,7 @@ class ConnectionProfile:
-                 )
-             )
-         else:
-+            self._fallback_checker_cleanup()
-             self._ctx.finish_async(action)
- 
-     def _update2_callback(self, src_object, result, user_data):
-diff --git a/libnmstate/nm/context.py b/libnmstate/nm/context.py
-index 373ffe8..bc5c41c 100644
---- a/libnmstate/nm/context.py
-+++ b/libnmstate/nm/context.py
-@@ -31,8 +31,7 @@ from .common import Gio
- # last finish async action.
- IDLE_CHECK_INTERNAL = 5
- 
--# libnm dbus connection has reply timeout 25 seconds.
--IDLE_TIMEOUT = 25
-+IDLE_TIMEOUT = 60 * 5  # 5 minutes
- 
- # NetworkManage is using dbus in libnm while the dbus has limitation on
- # maximum number of pending replies per connection.(RHEL/CentOS 8 is 1024)
--- 
-2.27.0
-
-
-From ac82d18f96aa2313583efa1477be441291e2957c Mon Sep 17 00:00:00 2001
-From: Fernando Fernandez Mancera <ffmancera@riseup.net>
-Date: Sun, 17 Jan 2021 11:18:10 +0800
-Subject: [PATCH 2/2] nm: Use fallback checker on profile deactivation and
- delete
-
-When NM is under heave loads, NM might raise timeout error when
-try to deactivate or delete a profile, to solve that this patch
-introduce the same method in 2407f98
-to have a fallback checker on whether profile is deactivated/deleted
-every 15 seconds.
-
-No test case required as current `test_lot_of_vlans_with_bridges` test
-case has `state: absent` which is good enough for testing this patch.
-
-Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/nm/active_connection.py | 61 ++++++++++++++++++++++++------
- libnmstate/nm/connection.py        | 30 +++++++++++++++
- 2 files changed, 80 insertions(+), 11 deletions(-)
-
-diff --git a/libnmstate/nm/active_connection.py b/libnmstate/nm/active_connection.py
-index 062c78a..b235e8b 100644
---- a/libnmstate/nm/active_connection.py
-+++ b/libnmstate/nm/active_connection.py
-@@ -21,12 +21,14 @@ import logging
- 
- from libnmstate.error import NmstateLibnmError
- 
-+from .common import Gio
- from .common import GLib
- from .common import GObject
- from .common import NM
- 
- 
- NM_AC_STATE_CHANGED_SIGNAL = "state-changed"
-+FALLBACK_CHECKER_INTERNAL = 15
- 
- 
- class ActivationError(Exception):
-@@ -37,6 +39,8 @@ class ActiveConnection:
-     def __init__(self, context=None, nm_ac_con=None):
-         self._ctx = context
-         self._act_con = nm_ac_con
-+        self._signal_handler = None
-+        self._fallback_checker = None
- 
-         nmdevs = None
-         if nm_ac_con:
-@@ -75,19 +79,35 @@ class ActiveConnection:
- 
-         action = f"Deactivate profile: {self.devname}"
-         self._ctx.register_async(action)
--        handler_id = act_connection.connect(
-+        self._signal_handler = act_connection.connect(
-             NM_AC_STATE_CHANGED_SIGNAL,
-             self._wait_state_changed_callback,
-             action,
-         )
-         if act_connection.props.state != NM.ActiveConnectionState.DEACTIVATING:
--            user_data = (handler_id, action)
-+            user_data = action
-             self._ctx.client.deactivate_connection_async(
-                 act_connection,
-                 self._ctx.cancellable,
-                 self._deactivate_connection_callback,
-                 user_data,
-             )
-+        self._fallback_checker = GLib.timeout_source_new(
-+            FALLBACK_CHECKER_INTERNAL * 1000
-+        )
-+        self._fallback_checker.set_callback(
-+            self._deactivation_fallback_checker_callback, action
-+        )
-+        self._fallback_checker.attach(self._ctx.context)
-+
-+    def _clean_up(self):
-+        if self._signal_handler:
-+            if self._act_con:
-+                self._act_con.handler_disconnect(self._signal_handler)
-+            self._signal_handler = None
-+        if self._fallback_checker:
-+            self._fallback_checker.destroy()
-+            self._fallback_checker = None
- 
-     def _wait_state_changed_callback(self, act_con, state, reason, action):
-         if self._ctx.is_cancelled():
-@@ -96,13 +116,13 @@ class ActiveConnection:
-             logging.debug(
-                 "Connection deactivation succeeded on %s", self.devname,
-             )
-+            self._clean_up()
-             self._ctx.finish_async(action)
- 
-     def _deactivate_connection_callback(self, src_object, result, user_data):
--        handler_id, action = user_data
-+        action = user_data
-         if self._ctx.is_cancelled():
--            if self._act_con:
--                self._act_con.handler_disconnect(handler_id)
-+            self._clean_up()
-             return
- 
-         try:
-@@ -116,16 +136,20 @@ class ActiveConnection:
-                     "Connection is not active on {}, no need to "
-                     "deactivate".format(self.devname)
-                 )
-+            elif e.matches(Gio.io_error_quark(), Gio.IOErrorEnum.TIMED_OUT):
-+                logging.debug(
-+                    f"{action} timeout, using fallback method to wait profile "
-+                    "deactivation"
-+                )
-+                return
-             else:
--                if self._act_con:
--                    self._act_con.handler_disconnect(handler_id)
-+                self._clean_up()
-                 self._ctx.fail(
-                     NmstateLibnmError(f"{action} failed: error={e}")
-                 )
-                 return
-         except Exception as e:
--            if self._act_con:
--                self._act_con.handler_disconnect(handler_id)
-+            self._clean_up()
-             self._ctx.fail(
-                 NmstateLibnmError(
-                     f"BUG: Unexpected error when activating {self.devname} "
-@@ -135,8 +159,7 @@ class ActiveConnection:
-             return
- 
-         if not success:
--            if self._act_con:
--                self._act_con.handler_disconnect(handler_id)
-+            self._clean_up()
-             self._ctx.fail(
-                 NmstateLibnmError(
-                     f"{action} failed: error='None returned from "
-@@ -144,6 +167,22 @@ class ActiveConnection:
-                 )
-             )
- 
-+    def _deactivation_fallback_checker_callback(self, action):
-+        if self.devname:
-+            self._nmdev = self._ctx.get_nm_dev(self.devname)
-+            if self._nmdev:
-+                self._act_con = self._nmdev.get_active_connection()
-+                if (
-+                    self._act_con
-+                    and self._act_con.props.state
-+                    != NM.ActiveConnectionState.DEACTIVATED
-+                ):
-+                    return GLib.SOURCE_CONTINUE
-+
-+        self._clean_up()
-+        self._ctx.finish_async(action)
-+        return GLib.SOURCE_REMOVE
-+
-     @property
-     def nm_active_connection(self):
-         return self._act_con
-diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py
-index 374a379..af7296f 100644
---- a/libnmstate/nm/connection.py
-+++ b/libnmstate/nm/connection.py
-@@ -144,6 +144,13 @@ class ConnectionProfile:
-                 self._delete_connection_callback,
-                 user_data,
-             )
-+            self._fallback_checker = GLib.timeout_source_new(
-+                FALLBACK_CHECKER_INTERNAL * 1000
-+            )
-+            self._fallback_checker.set_callback(
-+                self._delete_fallback_checker_callback, action
-+            )
-+            self._fallback_checker.attach(self._ctx.context)
- 
-     def activate(self):
-         if self.con_id:
-@@ -504,11 +511,24 @@ class ConnectionProfile:
-         action = user_data
-         try:
-             success = src_object.delete_finish(result)
-+        except GLib.Error as e:
-+            if e.matches(Gio.io_error_quark(), Gio.IOErrorEnum.TIMED_OUT):
-+                logging.debug(
-+                    f"{action} timeout, using fallback method to wait profile "
-+                    "deletion"
-+                )
-+                return
-+            else:
-+                self._ctx.fail(
-+                    NmstateLibnmError(f"{action} failed with error: {e}")
-+                )
-+                return
-         except Exception as e:
-             self._ctx.fail(NmstateLibnmError(f"{action} failed: error={e}"))
-             return
- 
-         if success:
-+            self._fallback_checker_cleanup()
-             self._ctx.finish_async(action)
-         else:
-             self._ctx.fail(
-@@ -518,6 +538,16 @@ class ConnectionProfile:
-                 )
-             )
- 
-+    def _delete_fallback_checker_callback(self, action):
-+        if self.profile:
-+            for nm_profile in self._ctx.client.get_connections():
-+                if nm_profile.get_uuid() == self.profile.get_uuid():
-+                    return GLib.SOURCE_CONTINUE
-+
-+        self._fallback_checker_cleanup()
-+        self._ctx.finish_async(action)
-+        return GLib.SOURCE_REMOVE
-+
-     def _reset_profile(self):
-         self._con_profile = None
- 
--- 
-2.27.0
-
diff --git a/SOURCES/BZ_1916073_retry_on_failure_when_activate.patch b/SOURCES/BZ_1916073_retry_on_failure_when_activate.patch
deleted file mode 100644
index da7f372..0000000
--- a/SOURCES/BZ_1916073_retry_on_failure_when_activate.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-From 013860d2576a34a277178e6afba0935498dc4f72 Mon Sep 17 00:00:00 2001
-From: Fernando Fernandez Mancera <ffmancera@riseup.net>
-Date: Wed, 3 Feb 2021 11:59:05 +0100
-Subject: [PATCH] connection: retry on profile activation if libnm error
- happened
-
-When activating a profile if NetworkManager fails during the activation,
-Nmstate should retry it once.
-
-Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
----
- libnmstate/nm/connection.py | 19 +++++++++++++++++--
- 1 file changed, 17 insertions(+), 2 deletions(-)
-
-diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py
-index 5b9a3aee2..45cb69019 100644
---- a/libnmstate/nm/connection.py
-+++ b/libnmstate/nm/connection.py
-@@ -180,7 +180,8 @@ def activate(self):
-                 "BUG: Cannot activate a profile with empty profile id and "
-                 "empty NM.Device"
-             )
--        user_data = action
-+        retry = True
-+        user_data = action, retry
-         self._ctx.register_async(action)
-         self._ctx.client.activate_connection_async(
-             self.profile,
-@@ -267,7 +268,7 @@ def _active_connection_callback(self, src_object, result, user_data):
-         if self._ctx.is_cancelled():
-             self._activation_clean_up()
-             return
--        action = user_data
-+        action, retry = user_data
- 
-         try:
-             nm_act_con = src_object.activate_connection_finish(result)
-@@ -279,6 +280,20 @@ def _active_connection_callback(self, src_object, result, user_data):
-                 )
-                 return
-             else:
-+                if retry:
-+                    retry = False
-+                    user_data = action, retry
-+                    specific_object = None
-+                    logging.debug(f"Action {action} failed, trying again.")
-+                    self._ctx.client.activate_connection_async(
-+                        self.profile,
-+                        self.nmdevice,
-+                        specific_object,
-+                        self._ctx.cancellable,
-+                        self._active_connection_callback,
-+                        user_data,
-+                    )
-+                    return
-                 self._ctx.fail(
-                     NmstateLibnmError(f"{action} failed: error={e}")
-                 )
diff --git a/SOURCES/BZ_1918712_use_uuid_for_vlan_vxlan_parent.patch b/SOURCES/BZ_1918712_use_uuid_for_vlan_vxlan_parent.patch
deleted file mode 100644
index 3c42770..0000000
--- a/SOURCES/BZ_1918712_use_uuid_for_vlan_vxlan_parent.patch
+++ /dev/null
@@ -1,214 +0,0 @@
-From a85b3dddf82f9e71774229740fbae6ea843d86d6 Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Mon, 18 Jan 2021 15:55:43 +0800
-Subject: [PATCH 1/2] ifaces: Don't validate undesired interface for overbook
-
-There is no need to validate overbooked interface for undesired
-controller interface.
-
-Unit test case included.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/ifaces/ifaces.py | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
-index 7723f43..ee75125 100644
---- a/libnmstate/ifaces/ifaces.py
-+++ b/libnmstate/ifaces/ifaces.py
-@@ -437,6 +437,8 @@ class Ifaces:
-         """
-         slave_master_map = {}
-         for iface in self._ifaces.values():
-+            if not (iface.is_changed or iface.is_desired) or not iface.is_up:
-+                continue
-             for slave_name in iface.slaves:
-                 cur_master = slave_master_map.get(slave_name)
-                 if cur_master:
--- 
-2.27.0
-
-
-From 644d8e5f5072caaba7151e66f211eceb02ae79c3 Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Thu, 21 Jan 2021 20:43:34 +0800
-Subject: [PATCH 2/2] nm vlan/vxlan: Use uuid for VLAN/VxLAN parent
-
-When parent of VLAN/VxLAN is holding the same name of OVS bridge or OVS
-port, NetworkManager will fail with error failed to find interface index
-of that parent.
-
-The root cause is NetworkManager try to use user space interface as
-VLAN/VxLAN parent.
-
-To workaround that, use profile UUID for `NM.SettingVlan.props.parent`
-and `NM.SettingVxlan.props.parent`.
-
-Integration test case included.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
----
- libnmstate/nm/applier.py    | 98 +++++++++++++++++++++++++++++++++++--
- libnmstate/nm/connection.py |  7 +++
- 2 files changed, 100 insertions(+), 5 deletions(-)
-
-diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py
-index 26a057f..8e38df5 100644
---- a/libnmstate/nm/applier.py
-+++ b/libnmstate/nm/applier.py
-@@ -66,8 +66,6 @@ MASTER_IFACE_TYPES = (
- 
- 
- def apply_changes(context, net_state, save_to_disk):
--    con_profiles = []
--
-     if (
-         not save_to_disk
-         and _has_ovs_interface_desired_or_changed(net_state)
-@@ -87,6 +85,10 @@ def apply_changes(context, net_state, save_to_disk):
-         _create_proxy_ifaces_desired_state(ifaces_desired_state)
-     )
- 
-+    # A list of tuple holding both current ConnectionProfile and new/updated
-+    # ConnectionProfile.
-+    pending_con_profiles = []
-+
-     for iface_desired_state in filter(
-         lambda s: s.get(Interface.STATE) != InterfaceState.ABSENT,
-         ifaces_desired_state,
-@@ -131,7 +133,7 @@ def apply_changes(context, net_state, save_to_disk):
-                 # anything besides state:up and not been marked as changed.
-                 # We don't need to do this once we support querying on-disk
-                 # configure
--                con_profiles.append(cur_con_profile)
-+                pending_con_profiles.append((cur_con_profile, None))
-                 continue
-         new_con_profile = _build_connection_profile(
-             context,
-@@ -143,12 +145,25 @@ def apply_changes(context, net_state, save_to_disk):
-             set_conn = new_con_profile.profile.get_setting_connection()
-             set_conn.props.interface_name = iface_desired_state[Interface.NAME]
-         if cur_con_profile and cur_con_profile.profile:
--            cur_con_profile.update(new_con_profile, save_to_disk)
--            con_profiles.append(new_con_profile)
-+            pending_con_profiles.append((cur_con_profile, new_con_profile))
-         else:
-             # Missing connection, attempting to create a new one.
-+            pending_con_profiles.append((None, new_con_profile))
-+
-+    pending_con_profiles = _use_uuid_for_parent(
-+        context, pending_con_profiles, save_to_disk
-+    )
-+
-+    con_profiles = []
-+    for cur_con_profile, new_con_profile in pending_con_profiles:
-+        if cur_con_profile and new_con_profile:
-+            cur_con_profile.update(new_con_profile, save_to_disk)
-+            con_profiles.append(new_con_profile)
-+        elif cur_con_profile is None and new_con_profile:
-             new_con_profile.add(save_to_disk)
-             con_profiles.append(new_con_profile)
-+        elif cur_con_profile:
-+            con_profiles.append(cur_con_profile)
-     context.wait_all_finish()
- 
-     _set_ifaces_admin_state(context, ifaces_desired_state, con_profiles)
-@@ -655,3 +670,76 @@ def _mark_nm_external_subordinate_changed(context, net_state):
-                     subordinate_iface = net_state.ifaces.get(subordinate)
-                     if subordinate_iface:
-                         subordinate_iface.mark_as_changed()
-+
-+
-+def _use_uuid_for_parent(context, pending_con_profiles, save_to_disk):
-+    """
-+    When parent of VLAN/VxLAN is holding the same name with
-+    OVS bridge or OVS port, we should use UUID instead of interface name
-+    """
-+    new_pending_con_profiles = []
-+    kernel_iface_name_to_uuid = {}
-+    for cur_nm_profile in context.client.get_connections():
-+        connection_type = cur_nm_profile.get_connection_type()
-+        if connection_type not in (
-+            NM.SETTING_OVS_BRIDGE_SETTING_NAME,
-+            NM.SETTING_OVS_PORT_SETTING_NAME,
-+        ):
-+            kernel_iface_name_to_uuid[
-+                cur_nm_profile.get_interface_name()
-+            ] = cur_nm_profile.get_uuid()
-+    # Override existing kernel_iface_name_to_uuid with pending changes.
-+    for cur_con_profile, new_con_profile in pending_con_profiles:
-+        if new_con_profile and new_con_profile.profile:
-+            uuid = new_con_profile.profile.get_uuid()
-+            connection_type = new_con_profile.profile.get_connection_type()
-+            iface_name = new_con_profile.profile.get_interface_name()
-+        elif cur_con_profile and cur_con_profile.profile:
-+            uuid = cur_con_profile.profile.get_uuid()
-+            connection_type = cur_con_profile.profile.get_connection_type()
-+            iface_name = cur_con_profile.profile.get_interface_name()
-+        else:
-+            continue
-+
-+        if connection_type not in (
-+            NM.SETTING_OVS_BRIDGE_SETTING_NAME,
-+            NM.SETTING_OVS_PORT_SETTING_NAME,
-+        ):
-+            kernel_iface_name_to_uuid[iface_name] = uuid
-+
-+    for cur_con_profile, new_con_profile in pending_con_profiles:
-+        new_pending_con_profiles.append((cur_con_profile, new_con_profile))
-+        if not new_con_profile:
-+            continue
-+        nm_profile = new_con_profile.profile
-+        if not nm_profile:
-+            continue
-+        connection_type = nm_profile.get_connection_type()
-+        nm_setting = None
-+        if connection_type == NM.SETTING_VLAN_SETTING_NAME:
-+            nm_setting = nm_profile.get_setting_vlan()
-+        elif connection_type == NM.SETTING_VXLAN_SETTING_NAME:
-+            nm_setting = nm_profile.get_setting_vxlan()
-+        else:
-+            continue
-+        if not nm_setting:
-+            continue
-+        parent_iface_name = nm_setting.props.parent
-+        parent_uuid = kernel_iface_name_to_uuid.get(parent_iface_name)
-+        if parent_uuid:
-+            updated_con_profile = connection.ConnectionProfile(context)
-+            new_nm_settings = []
-+            for cur_nm_setting in nm_profile.get_settings():
-+                new_nm_setting = cur_nm_setting.duplicate()
-+                if new_nm_setting.get_name() in (
-+                    NM.SETTING_VLAN_SETTING_NAME,
-+                    NM.SETTING_VXLAN_SETTING_NAME,
-+                ):
-+                    new_nm_setting.props.parent = parent_uuid
-+                new_nm_settings.append(new_nm_setting)
-+            updated_con_profile.create(new_nm_settings)
-+            new_pending_con_profiles.pop()
-+            new_pending_con_profiles.append(
-+                (cur_con_profile, updated_con_profile)
-+            )
-+    return new_pending_con_profiles
-diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py
-index af7296f..5b9a3ae 100644
---- a/libnmstate/nm/connection.py
-+++ b/libnmstate/nm/connection.py
-@@ -63,6 +63,13 @@ class ConnectionProfile:
-         if self.con_id:
-             self.profile = self._ctx.client.get_connection_by_id(self.con_id)
- 
-+    def import_by_uuid(self, uuid):
-+        for nm_profile in self._ctx.client.get_connections():
-+            if nm_profile.get_uuid() == uuid:
-+                self.profile = nm_profile
-+                return
-+        logging.debug(f"Failed to find {uuid} profile")
-+
-     def update(self, con_profile, save_to_disk=True):
-         flags = NM.SettingsUpdate2Flags.BLOCK_AUTOCONNECT
-         if save_to_disk:
--- 
-2.27.0
-
diff --git a/SOURCES/BZ_1931290-SRIOV-Do-not-create-VF-profiles-automatically.patch b/SOURCES/BZ_1931290-SRIOV-Do-not-create-VF-profiles-automatically.patch
deleted file mode 100644
index 43d0dba..0000000
--- a/SOURCES/BZ_1931290-SRIOV-Do-not-create-VF-profiles-automatically.patch
+++ /dev/null
@@ -1,82 +0,0 @@
-From cc7e6da98cc992d2e6d8aa85cd78f02fb8ef8ac3 Mon Sep 17 00:00:00 2001
-From: Fernando Fernandez Mancera <ffmancera@riseup.net>
-Date: Sun, 21 Feb 2021 22:43:57 +0100
-Subject: [PATCH 2/5] SR-IOV: Do not create VF profiles automatically
-
-As VFs are Ethernet type and Nmstate is automatically adding them to the
-desired state and marking them as desired, the profile is being created.
-This is wrong as Nmstate should only wait for verification of the VFs.
-
-In order to fix this, the new VF interfaces are being marked as so. This
-way Nmstate is not creating the profiles anymore.
-
-Integration test case added.
-
-Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
----
- libnmstate/ifaces/ethernet.py      | 10 ++++
- libnmstate/ifaces/ifaces.py        |  1 +
- libnmstate/nm/applier.py           |  5 ++
- tests/integration/nm/sriov_test.py | 92 ++++++++++++++++++++++++++++++
- 4 files changed, 108 insertions(+)
- create mode 100644 tests/integration/nm/sriov_test.py
-
-diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py
-index 3e1bdc5d..f1ece5f5 100644
---- a/libnmstate/ifaces/ethernet.py
-+++ b/libnmstate/ifaces/ethernet.py
-@@ -25,6 +25,9 @@ from libnmstate.schema import InterfaceState
- from .base_iface import BaseIface
- 
- 
-+IS_NEW_SR_IOV_VF = "_is_new_sr_iov_vf"
-+
-+
- class EthernetIface(BaseIface):
-     def merge(self, other):
-         """
-@@ -57,6 +60,13 @@ class EthernetIface(BaseIface):
-             .get(Ethernet.SRIOV.TOTAL_VFS, 0)
-         )
- 
-+    @property
-+    def is_new_sr_iov_vf(self):
-+        return self.raw.get(IS_NEW_SR_IOV_VF)
-+
-+    def mark_as_new_sr_iov_vf(self):
-+        self.raw[IS_NEW_SR_IOV_VF] = True
-+
-     def create_sriov_vf_ifaces(self):
-         return [
-             EthernetIface(
-diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
-index 67ab91c4..a7af9712 100644
---- a/libnmstate/ifaces/ifaces.py
-+++ b/libnmstate/ifaces/ifaces.py
-@@ -144,6 +144,7 @@ class Ifaces:
-                 for new_iface in iface.create_sriov_vf_ifaces():
-                     if new_iface.name not in self._ifaces:
-                         new_iface.mark_as_desired()
-+                        new_iface.mark_as_new_sr_iov_vf()
-                         new_ifaces.append(new_iface)
-         for new_iface in new_ifaces:
-             self._ifaces[new_iface.name] = new_iface
-diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py
-index 8e38df54..cd319ffb 100644
---- a/libnmstate/nm/applier.py
-+++ b/libnmstate/nm/applier.py
-@@ -119,6 +119,11 @@ def apply_changes(context, net_state, save_to_disk):
-         original_desired_iface_state = {}
-         if net_state.ifaces.get(ifname):
-             iface = net_state.ifaces[ifname]
-+            if iface.type == InterfaceType.ETHERNET and iface.is_new_sr_iov_vf:
-+                # For new vfs automatically added to the desired state is just
-+                # for verification, Nmstate should not create a profile for
-+                # them.
-+                continue
-             if iface.is_desired:
-                 original_desired_iface_state = iface.original_dict
-             if (
--- 
-2.29.2
-
diff --git a/SOURCES/BZ_1931290-SRIOV-Remove-VF-interface-when-total-vfs-decrease.patch b/SOURCES/BZ_1931290-SRIOV-Remove-VF-interface-when-total-vfs-decrease.patch
deleted file mode 100644
index 99e3e15..0000000
--- a/SOURCES/BZ_1931290-SRIOV-Remove-VF-interface-when-total-vfs-decrease.patch
+++ /dev/null
@@ -1,112 +0,0 @@
-From c55d39e8485a26490afc36d71fd9d20528ab6fd2 Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-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 <fge@redhat.com>
-Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
----
- 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
-
diff --git a/SOURCES/BZ_1931355-SRIOV-wait-VF-mount-decrease.patch b/SOURCES/BZ_1931355-SRIOV-wait-VF-mount-decrease.patch
new file mode 100644
index 0000000..f215f9f
--- /dev/null
+++ b/SOURCES/BZ_1931355-SRIOV-wait-VF-mount-decrease.patch
@@ -0,0 +1,166 @@
+From 80c97b27707b036f0a54988ade4bda3ccb342b34 Mon Sep 17 00:00:00 2001
+From: Fernando Fernandez Mancera <ffmancera@riseup.net>
+Date: Mon, 22 Feb 2021 12:03:11 +0100
+Subject: [PATCH 1/2] SR-IOV: increase the verification timeout if SR-IOV is
+ present
+
+Certain drivers like i40e take a long time to modify the VFs in the
+kernel. Nmstate is timing out on verification because of that. In order
+to fix this, nmstate is incresing the verification time if SR-IOV is
+present on the desired state.
+
+Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
+Signed-off-by: Gris Ge <fge@redhat.com>
+---
+ libnmstate/ifaces/ethernet.py |  6 ++++++
+ libnmstate/netapplier.py      | 18 +++++++++++++++++-
+ 2 files changed, 23 insertions(+), 1 deletion(-)
+
+diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py
+index 292b7bc..ca8501b 100644
+--- a/libnmstate/ifaces/ethernet.py
++++ b/libnmstate/ifaces/ethernet.py
+@@ -65,6 +65,12 @@ class EthernetIface(BaseIface):
+     def is_peer(self):
+         return self._is_peer
+ 
++    @property
++    def is_sriov(self):
++        return self.raw.get(Ethernet.CONFIG_SUBTREE, {}).get(
++            Ethernet.SRIOV_SUBTREE
++        )
++
+     def create_sriov_vf_ifaces(self):
+         return [
+             EthernetIface(
+diff --git a/libnmstate/netapplier.py b/libnmstate/netapplier.py
+index cf208d1..3c5759b 100644
+--- a/libnmstate/netapplier.py
++++ b/libnmstate/netapplier.py
+@@ -24,6 +24,7 @@ import time
+ 
+ from libnmstate import validator
+ from libnmstate.error import NmstateVerificationError
++from libnmstate.schema import InterfaceType
+ 
+ from .nmstate import create_checkpoints
+ from .nmstate import destroy_checkpoints
+@@ -37,6 +38,7 @@ from .version import get_version
+ MAINLOOP_TIMEOUT = 35
+ VERIFY_RETRY_INTERNAL = 1
+ VERIFY_RETRY_TIMEOUT = 5
++VERIFY_RETRY_TIMEOUT_INCREASE = 4
+ 
+ 
+ def apply(
+@@ -109,7 +111,13 @@ def _apply_ifaces_state(plugins, net_state, verify_change, save_to_disk):
+         plugin.apply_changes(net_state, save_to_disk)
+     verified = False
+     if verify_change:
+-        for _ in range(VERIFY_RETRY_TIMEOUT):
++        if _net_state_contains_sriov_interface(net_state):
++            # If SR-IOV is present, the verification timeout is being increased
++            # to avoid timeouts due to slow drivers like i40e.
++            verify_retry = VERIFY_RETRY_TIMEOUT * VERIFY_RETRY_TIMEOUT_INCREASE
++        else:
++            verify_retry = VERIFY_RETRY_TIMEOUT
++        for _ in range(verify_retry):
+             try:
+                 _verify_change(plugins, net_state)
+                 verified = True
+@@ -120,6 +128,14 @@ def _apply_ifaces_state(plugins, net_state, verify_change, save_to_disk):
+             _verify_change(plugins, net_state)
+ 
+ 
++def _net_state_contains_sriov_interface(net_state):
++    for iface in net_state.ifaces.all_kernel_ifaces.values():
++        if iface.type == InterfaceType.ETHERNET and iface.is_sriov:
++            return True
++
++    return False
++
++
+ def _verify_change(plugins, net_state):
+     current_state = show_with_plugins(plugins)
+     net_state.verify(current_state)
+-- 
+2.27.0
+
+
+From 439fe3a51a82060c5b62974c6c9fbdf403c4196b Mon Sep 17 00:00:00 2001
+From: Fernando Fernandez Mancera <ffmancera@riseup.net>
+Date: Mon, 22 Feb 2021 13:33:06 +0100
+Subject: [PATCH 2/2] SR-IOV: fail on verification if `total_vfs` does not
+ match vfs len
+
+Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
+Signed-off-by: Gris Ge <fge@redhat.com>
+---
+ libnmstate/ifaces/ethernet.py | 11 +++++++++++
+ libnmstate/ifaces/ifaces.py   | 14 ++++++++++++++
+ 2 files changed, 25 insertions(+)
+
+diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py
+index ca8501b..55772ce 100644
+--- a/libnmstate/ifaces/ethernet.py
++++ b/libnmstate/ifaces/ethernet.py
+@@ -61,6 +61,14 @@ class EthernetIface(BaseIface):
+             .get(Ethernet.SRIOV.TOTAL_VFS, 0)
+         )
+ 
++    @property
++    def sriov_vfs(self):
++        return (
++            self.raw.get(Ethernet.CONFIG_SUBTREE, {})
++            .get(Ethernet.SRIOV_SUBTREE, {})
++            .get(Ethernet.SRIOV.VFS_SUBTREE, [])
++        )
++
+     @property
+     def is_peer(self):
+         return self._is_peer
+@@ -108,6 +116,9 @@ class EthernetIface(BaseIface):
+             for i in range(self.sriov_total_vfs, old_sriov_total_vfs)
+         ]
+ 
++    def check_total_vfs_matches_vf_list(self, total_vfs):
++        return total_vfs == len(self.sriov_vfs)
++
+ 
+ def _capitalize_sriov_vf_mac(state):
+     vfs = (
+diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
+index 44c9e61..6c94a98 100644
+--- a/libnmstate/ifaces/ifaces.py
++++ b/libnmstate/ifaces/ifaces.py
+@@ -238,6 +238,8 @@ class Ifaces:
+                     if new_iface.name not in self._kernel_ifaces:
+                         new_iface.mark_as_desired()
+                         new_ifaces.append(new_iface)
++                    else:
++                        self._kernel_ifaces[new_iface.name].mark_as_desired()
+         for new_iface in new_ifaces:
+             self._kernel_ifaces[new_iface.name] = new_iface
+ 
+@@ -656,6 +658,18 @@ 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)
+-- 
+2.27.0
+
diff --git a/SOURCES/BZ_1931751-nmstate-fix-return-code.patch b/SOURCES/BZ_1931751-nmstate-fix-return-code.patch
new file mode 100644
index 0000000..78b6774
--- /dev/null
+++ b/SOURCES/BZ_1931751-nmstate-fix-return-code.patch
@@ -0,0 +1,29 @@
+From b26ab850172a41557cad42cc011bd00d7c108c88 Mon Sep 17 00:00:00 2001
+From: Gris Ge <fge@redhat.com>
+Date: Tue, 23 Feb 2021 13:52:19 +0800
+Subject: [PATCH] nmstatectl: Fix return code of set command
+
+The deprecated command `set` should still return the error like
+old behaviour.
+
+Signed-off-by: Gris Ge <fge@redhat.com>
+---
+ nmstatectl/nmstatectl.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/nmstatectl/nmstatectl.py b/nmstatectl/nmstatectl.py
+index df59942..c94d603 100644
+--- a/nmstatectl/nmstatectl.py
++++ b/nmstatectl/nmstatectl.py
+@@ -323,7 +323,7 @@ def show(args):
+ 
+ def set(args):
+     warnings.warn("Using 'set' is deprecated, use 'apply' instead.")
+-    apply(args)
++    return apply(args)
+ 
+ 
+ def apply(args):
+-- 
+2.27.0
+
diff --git a/SOURCES/BZ_1931784-SR-IOV-fail-on-verification-if-total_vfs-does-not-ma.patch b/SOURCES/BZ_1931784-SR-IOV-fail-on-verification-if-total_vfs-does-not-ma.patch
deleted file mode 100644
index 6806d80..0000000
--- a/SOURCES/BZ_1931784-SR-IOV-fail-on-verification-if-total_vfs-does-not-ma.patch
+++ /dev/null
@@ -1,79 +0,0 @@
-From a43609607abe30b973f1cb78cb1754f1a9a91514 Mon Sep 17 00:00:00 2001
-From: Fernando Fernandez Mancera <ffmancera@riseup.net>
-Date: Mon, 22 Feb 2021 13:33:06 +0100
-Subject: [PATCH 4/5] SR-IOV: fail on verification if `total_vfs` does not
- match vfs len
-
-Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
----
- libnmstate/ifaces/ethernet.py | 11 +++++++++++
- libnmstate/ifaces/ifaces.py   | 17 +++++++++++++++++
- 2 files changed, 28 insertions(+)
-
-diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py
-index 1c3ca266..4903bde7 100644
---- a/libnmstate/ifaces/ethernet.py
-+++ b/libnmstate/ifaces/ethernet.py
-@@ -52,6 +52,14 @@ class EthernetIface(BaseIface):
-         _capitalize_sriov_vf_mac(state)
-         return state
- 
-+    @property
-+    def sriov_vfs(self):
-+        return (
-+            self.raw.get(Ethernet.CONFIG_SUBTREE, {})
-+            .get(Ethernet.SRIOV_SUBTREE, {})
-+            .get(Ethernet.SRIOV.VFS_SUBTREE, {})
-+        )
-+
-     @property
-     def sriov_total_vfs(self):
-         return (
-@@ -109,6 +117,9 @@ class EthernetIface(BaseIface):
-             for i in range(self.sriov_total_vfs, old_sriov_total_vfs)
-         ]
- 
-+    def check_total_vfs_matches_vf_list(self, total_vfs):
-+        return total_vfs == len(self.sriov_vfs)
-+
- 
- def _capitalize_sriov_vf_mac(state):
-     vfs = (
-diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
-index b212ebb5..1d30d0c6 100644
---- a/libnmstate/ifaces/ifaces.py
-+++ b/libnmstate/ifaces/ifaces.py
-@@ -146,6 +146,11 @@ class Ifaces:
-                         new_iface.mark_as_desired()
-                         new_iface.mark_as_new_sr_iov_vf()
-                         new_ifaces.append(new_iface)
-+                    else:
-+                        # When the VFs are being modified, all VFs link are
-+                        # being removed from kernel and created again. Nmstate
-+                        # must verify they have been created.
-+                        self._ifaces[new_iface.name].mark_as_desired()
-         for new_iface in new_ifaces:
-             self._ifaces[new_iface.name] = new_iface
- 
-@@ -403,6 +408,18 @@ 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)
--- 
-2.29.2
-
diff --git a/SOURCES/BZ_1931784-SR-IOV-increase-the-verification-timeout-if-SR-IOV.patch b/SOURCES/BZ_1931784-SR-IOV-increase-the-verification-timeout-if-SR-IOV.patch
deleted file mode 100644
index d801c0f..0000000
--- a/SOURCES/BZ_1931784-SR-IOV-increase-the-verification-timeout-if-SR-IOV.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-From afb3f2dfeb5364e8a9a0bde4ad9062f1585a8795 Mon Sep 17 00:00:00 2001
-From: Fernando Fernandez Mancera <ffmancera@riseup.net>
-Date: Mon, 22 Feb 2021 12:03:11 +0100
-Subject: [PATCH 3/5] SR-IOV: increase the verification timeout if SR-IOV is
- present
-
-Certain drivers like i40e take a long time to modify the VFs in the
-kernel. Nmstate is timing out on verification because of that. In order
-to fix this, nmstate is incresing the verification time if SR-IOV is
-present on the desired state.
-
-Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
----
- libnmstate/ifaces/ethernet.py |  5 +++++
- libnmstate/ifaces/ifaces.py   |  4 ++++
- libnmstate/netapplier.py      | 18 +++++++++++++++++-
- 3 files changed, 26 insertions(+), 1 deletion(-)
-
-diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py
-index f1ece5f5..1c3ca266 100644
---- a/libnmstate/ifaces/ethernet.py
-+++ b/libnmstate/ifaces/ethernet.py
-@@ -67,6 +67,11 @@ class EthernetIface(BaseIface):
-     def mark_as_new_sr_iov_vf(self):
-         self.raw[IS_NEW_SR_IOV_VF] = True
- 
-+    def is_sriov(self):
-+        return self.raw.get(Ethernet.CONFIG_SUBTREE, {}).get(
-+            Ethernet.SRIOV_SUBTREE, {}
-+        )
-+
-     def create_sriov_vf_ifaces(self):
-         return [
-             EthernetIface(
-diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
-index a7af9712..b212ebb5 100644
---- a/libnmstate/ifaces/ifaces.py
-+++ b/libnmstate/ifaces/ifaces.py
-@@ -325,6 +325,10 @@ class Ifaces:
-     def current_ifaces(self):
-         return self._cur_ifaces
- 
-+    @property
-+    def all_ifaces(self):
-+        return self._ifaces
-+
-     @property
-     def state_to_edit(self):
-         return [
-diff --git a/libnmstate/netapplier.py b/libnmstate/netapplier.py
-index 24df4d56..6aa1ac07 100644
---- a/libnmstate/netapplier.py
-+++ b/libnmstate/netapplier.py
-@@ -23,6 +23,7 @@ import time
- 
- from libnmstate import validator
- from libnmstate.error import NmstateVerificationError
-+from libnmstate.schema import InterfaceType
- 
- from .nmstate import create_checkpoints
- from .nmstate import destroy_checkpoints
-@@ -35,6 +36,7 @@ from .net_state import NetState
- MAINLOOP_TIMEOUT = 35
- VERIFY_RETRY_INTERNAL = 1
- VERIFY_RETRY_TIMEOUT = 5
-+VERIFY_RETRY_TIMEOUT_INCREASE = 4
- 
- 
- def apply(
-@@ -104,7 +106,13 @@ def _apply_ifaces_state(plugins, net_state, verify_change, save_to_disk):
-         plugin.apply_changes(net_state, save_to_disk)
-     verified = False
-     if verify_change:
--        for _ in range(VERIFY_RETRY_TIMEOUT):
-+        if _net_state_contains_sriov_interface(net_state):
-+            # If SR-IOV is present, the verification timeout is being increased
-+            # to avoid timeouts due to slow drivers like i40e.
-+            verify_retry = VERIFY_RETRY_TIMEOUT * VERIFY_RETRY_TIMEOUT_INCREASE
-+        else:
-+            verify_retry = VERIFY_RETRY_TIMEOUT
-+        for _ in range(verify_retry):
-             try:
-                 _verify_change(plugins, net_state)
-                 verified = True
-@@ -115,6 +123,14 @@ def _apply_ifaces_state(plugins, net_state, verify_change, save_to_disk):
-             _verify_change(plugins, net_state)
- 
- 
-+def _net_state_contains_sriov_interface(net_state):
-+    for iface in net_state.ifaces.all_ifaces.values():
-+        if iface.type == InterfaceType.ETHERNET and iface.is_sriov:
-+            return True
-+
-+    return False
-+
-+
- def _verify_change(plugins, net_state):
-     current_state = show_with_plugins(plugins)
-     net_state.verify(current_state)
--- 
-2.29.2
-
diff --git a/SOURCES/BZ_1932247-bridge-do-not-bring-up-existing-ports.patch b/SOURCES/BZ_1932247-bridge-do-not-bring-up-existing-ports.patch
deleted file mode 100644
index 2b4baec..0000000
--- a/SOURCES/BZ_1932247-bridge-do-not-bring-up-existing-ports.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From cb4cbff0da01bb1e6546c2b28ef2760ec1f89f74 Mon Sep 17 00:00:00 2001
-From: Fernando Fernandez Mancera <ffmancera@riseup.net>
-Date: Wed, 24 Feb 2021 17:12:13 +0100
-Subject: [PATCH 5/5] bridge: do not bring up existing ports
-
-Nmstate should not try to bring up existing ports on a bridge when
-modifying it. The ports will be bring up when being added to the it, if
-the bridge is being modified later, the ports are not going to be
-automatically up.
-
-Ref: https://bugzilla.redhat.com/1932247
-
-Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
----
- libnmstate/ifaces/ifaces.py               |   5 +
- tests/integration/nm/linux_bridge_test.py | 112 +++++++++++++++++++++-
- 2 files changed, 116 insertions(+), 1 deletion(-)
-
-diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
-index 1d30d0c6..5f1f548d 100644
---- a/libnmstate/ifaces/ifaces.py
-+++ b/libnmstate/ifaces/ifaces.py
-@@ -194,7 +194,12 @@ class Ifaces:
-         """
-         for iface in self._ifaces.values():
-             if iface.is_up and iface.is_master:
-+                cur_iface = self.current_ifaces.get(iface.name)
-                 for slave_name in iface.slaves:
-+                    if cur_iface and slave_name in cur_iface.slaves:
-+                        # Nmstate should not touch the port interface which has
-+                        # already been included in current interface.
-+                        continue
-                     slave_iface = self._ifaces[slave_name]
-                     if not slave_iface.is_desired and not slave_iface.is_up:
-                         slave_iface.mark_as_up()
--- 
-2.29.2
-
diff --git a/SOURCES/BZ_1932247-nm-Don-t-touch-unmanaged-interface-unless-desired.patch b/SOURCES/BZ_1932247-nm-Don-t-touch-unmanaged-interface-unless-desired.patch
new file mode 100644
index 0000000..ea46af7
--- /dev/null
+++ b/SOURCES/BZ_1932247-nm-Don-t-touch-unmanaged-interface-unless-desired.patch
@@ -0,0 +1,223 @@
+From ccdcd8f86544a6364109a0c0142d05a5afacf64e Mon Sep 17 00:00:00 2001
+From: Gris Ge <fge@redhat.com>
+Date: Tue, 2 Mar 2021 15:31:20 +0800
+Subject: [PATCH] nm: Don't touch unmanaged interface unless desired
+
+We should ignore NetworkManager unmanaged interface when applying and
+verifying unless certain interface listed in desired state explicitly.
+
+Introduced new plugin interface
+`NmstatePlugin.get_ignored_kernel_interface_names()` where plugin may
+include a list of interface names which should be ignored during
+verification stage.
+
+Integration test case added to simulate CNV usage on partial editing
+a linux bridge holding NM unmanaged interface.
+
+Signed-off-by: Gris Ge <fge@redhat.com>
+---
+ libnmstate/ifaces/base_iface.py           |  3 ++
+ libnmstate/ifaces/ifaces.py               | 26 ++++++++--------
+ libnmstate/netapplier.py                  |  6 ++++
+ libnmstate/nispor/plugin.py               |  6 +++-
+ libnmstate/nm/plugin.py                   | 25 ++++++++++++++++
+ libnmstate/plugin.py                      |  7 +++++
+ tests/integration/linux_bridge_test.py    |  8 +----
+ tests/integration/nm/linux_bridge_test.py | 36 ++++++++++++++++++++++-
+ 8 files changed, 95 insertions(+), 22 deletions(-)
+
+diff --git a/libnmstate/ifaces/base_iface.py b/libnmstate/ifaces/base_iface.py
+index 227c1d20..e3f2a1ca 100644
+--- a/libnmstate/ifaces/base_iface.py
++++ b/libnmstate/ifaces/base_iface.py
+@@ -322,6 +322,9 @@ class BaseIface:
+     def mark_as_up(self):
+         self.raw[Interface.STATE] = InterfaceState.UP
+ 
++    def mark_as_ignored(self):
++        self.raw[Interface.STATE] = InterfaceState.IGNORE
++
+     @property
+     def is_controller(self):
+         return False
+diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
+index 6c94a986..efa24aa3 100644
+--- a/libnmstate/ifaces/ifaces.py
++++ b/libnmstate/ifaces/ifaces.py
+@@ -95,7 +95,6 @@ class Ifaces:
+         self._kernel_ifaces = {}
+         self._user_space_ifaces = _UserSpaceIfaces()
+         self._cur_user_space_ifaces = _UserSpaceIfaces()
+-        self._ignored_ifaces = set()
+         if cur_iface_infos:
+             for iface_info in cur_iface_infos:
+                 cur_iface = _to_specific_iface_obj(iface_info, save_to_disk)
+@@ -143,10 +142,6 @@ class Ifaces:
+                 ):
+                     # Ignore interface with unknown type
+                     continue
+-                if iface.is_ignore:
+-                    self._ignored_ifaces.add(
+-                        (iface.name, iface.type, iface.is_user_space_only)
+-                    )
+                 if cur_iface:
+                     iface.merge(cur_iface)
+                 iface.mark_as_desired()
+@@ -169,6 +164,10 @@ class Ifaces:
+ 
+             self._pre_edit_validation_and_cleanup()
+ 
++    @property
++    def _ignored_ifaces(self):
++        return [iface for iface in self.all_ifaces() if iface.is_ignore]
++
+     def _apply_copy_mac_from(self):
+         for iface in self.all_kernel_ifaces.values():
+             if iface.type not in (
+@@ -284,7 +283,7 @@ class Ifaces:
+         if not defiend in desire state
+         """
+         for iface in self.all_ifaces():
+-            if iface.is_up and iface.is_controller:
++            if iface.is_desired and iface.is_up and iface.is_controller:
+                 for port_name in iface.port:
+                     port_iface = self._kernel_ifaces[port_name]
+                     if not port_iface.is_desired and not port_iface.is_up:
+@@ -550,13 +549,14 @@ class Ifaces:
+         return None
+ 
+     def _remove_iface(self, iface_name, iface_type):
+-        cur_iface = self._cur_kernel_ifaces.get(iface_name, iface_type)
++        cur_iface = self._user_space_ifaces.get(iface_name, iface_type)
+         if cur_iface:
+             self._user_space_ifaces.remove(cur_iface)
+         else:
+             cur_iface = self._kernel_ifaces.get(iface_name)
+             if (
+-                iface_type
++                cur_iface
++                and iface_type
+                 and iface_type != InterfaceType.UNKNOWN
+                 and iface_type == cur_iface.type
+             ):
+@@ -813,14 +813,14 @@ class Ifaces:
+                     port_controller_map[port_name] = iface.name
+ 
+     def _remove_ignore_interfaces(self, ignored_ifaces):
+-        for iface_name, iface_type, _ in ignored_ifaces:
+-            self._remove_iface(iface_name, iface_type)
++        for iface in ignored_ifaces:
++            self._remove_iface(iface.name, iface.type)
+ 
+         # Only kernel interface can be used as port
+         ignored_kernel_iface_names = set(
+-            iface_name
+-            for iface_name, _, is_user_space_only in ignored_ifaces
+-            if not is_user_space_only
++            iface.name
++            for iface in ignored_ifaces
++            if not iface.is_user_space_only
+         )
+ 
+         # Remove ignored port
+diff --git a/libnmstate/netapplier.py b/libnmstate/netapplier.py
+index 3c5759b4..a020f003 100644
+--- a/libnmstate/netapplier.py
++++ b/libnmstate/netapplier.py
+@@ -107,8 +107,14 @@ def rollback(*, checkpoint=None):
+ 
+ 
+ def _apply_ifaces_state(plugins, net_state, verify_change, save_to_disk):
++    for plugin in plugins:
++        for iface_name in plugin.get_ignored_kernel_interface_names():
++            iface = net_state.ifaces.all_kernel_ifaces.get(iface_name)
++            if iface and not iface.is_desired:
++                iface.mark_as_ignored()
+     for plugin in plugins:
+         plugin.apply_changes(net_state, save_to_disk)
++
+     verified = False
+     if verify_change:
+         if _net_state_contains_sriov_interface(net_state):
+diff --git a/libnmstate/nispor/plugin.py b/libnmstate/nispor/plugin.py
+index dc0ea760..19b21d56 100644
+--- a/libnmstate/nispor/plugin.py
++++ b/libnmstate/nispor/plugin.py
+@@ -159,7 +159,11 @@ class NisporPlugin(NmstatePlugin):
+         np_state = NisporNetState.retrieve()
+         logging.debug(f"Nispor: current network state {np_state}")
+         for iface in net_state.ifaces.all_ifaces():
+-            if iface.is_desired:
++            if iface.is_ignore:
++                logging.debug(
++                    f"Nispor: Interface {iface.name} {iface.type} ignored"
++                )
++            elif iface.is_desired:
+                 logging.debug(
+                     f"Nispor: desired network state {iface.to_dict()}"
+                 )
+diff --git a/libnmstate/nm/plugin.py b/libnmstate/nm/plugin.py
+index 302b4cca..335d93c7 100644
+--- a/libnmstate/nm/plugin.py
++++ b/libnmstate/nm/plugin.py
+@@ -36,6 +36,7 @@ from .checkpoint import get_checkpoints
+ from .common import NM
+ from .context import NmContext
+ from .device import get_device_common_info
++from .device import get_iface_type
+ from .device import list_devices
+ from .dns import get_running as get_dns_running
+ from .dns import get_running_config as get_dns_running_config
+@@ -268,6 +269,21 @@ class NetworkManagerPlugin(NmstatePlugin):
+             )
+         return NmProfiles(None).generate_config_strings(net_state)
+ 
++    def get_ignored_kernel_interface_names(self):
++        """
++        Return a list of unmanged kernel interface names.
++        """
++        ignored_ifaces = set()
++        for nm_dev in list_devices(self.client):
++            if (
++                nm_dev
++                and nm_dev.get_iface()
++                and not nm_dev.get_managed()
++                and _is_kernel_iface(nm_dev)
++            ):
++                ignored_ifaces.add(nm_dev.get_iface())
++        return list(ignored_ifaces)
++
+ 
+ def _remove_ovs_bridge_unsupported_entries(iface_info):
+     """
+@@ -283,3 +299,12 @@ def _remove_ovs_bridge_unsupported_entries(iface_info):
+ 
+ def _nm_utils_decode_version():
+     return f"{NM.MAJOR_VERSION}.{NM.MINOR_VERSION}.{NM.MICRO_VERSION}"
++
++
++def _is_kernel_iface(nm_dev):
++    iface_type = get_iface_type(nm_dev)
++    return iface_type != InterfaceType.UNKNOWN and iface_type not in (
++        InterfaceType.OVS_BRIDGE,
++        InterfaceType.OVS_INTERFACE,
++        InterfaceType.OVS_PORT,
++    )
+diff --git a/libnmstate/plugin.py b/libnmstate/plugin.py
+index ef3874ff..e1d9ad58 100644
+--- a/libnmstate/plugin.py
++++ b/libnmstate/plugin.py
+@@ -128,3 +128,10 @@ class NmstatePlugin(metaclass=ABCMeta):
+         persistently.
+         """
+         return []
++
++    def get_ignored_kernel_interface_names(self):
++        """
++        Return a list of kernel interface names which should be ignored
++        during verification stage.
++        """
++        return []
+-- 
+2.29.2
+
diff --git a/SOURCES/BZ_1932247-nm.applier-ignore-not-desired-unmanaged-ifaces.patch b/SOURCES/BZ_1932247-nm.applier-ignore-not-desired-unmanaged-ifaces.patch
deleted file mode 100644
index 283f8fa..0000000
--- a/SOURCES/BZ_1932247-nm.applier-ignore-not-desired-unmanaged-ifaces.patch
+++ /dev/null
@@ -1,77 +0,0 @@
-From fb9352b902f8fec813c149e02e97c7014ef6399c Mon Sep 17 00:00:00 2001
-From: Fernando Fernandez Mancera <ffmancera@riseup.net>
-Date: Mon, 1 Mar 2021 16:25:57 +0100
-Subject: [PATCH] nm.applier: ignore not desired unmanaged ifaces
-
-Nmstate will ignore not desired unmanaged interfaces. If an existing
-unmanaged port of a bridge is not being included in the desired state
-bridge port list, it will not be removed. Basically, Nmstate will not be
-able to remove unmanaged ports from a bridge.
-
-Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
----
- libnmstate/ifaces/ifaces.py               | 11 ++++++---
- libnmstate/nm/applier.py                  | 11 ++++++++-
- tests/integration/linux_bridge_test.py    |  1 +
- tests/integration/nm/linux_bridge_test.py | 30 +++--------------------
- 4 files changed, 21 insertions(+), 32 deletions(-)
-
-diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
-index 5f1f548d..cfc306c6 100644
---- a/libnmstate/ifaces/ifaces.py
-+++ b/libnmstate/ifaces/ifaces.py
-@@ -193,7 +193,7 @@ class Ifaces:
-         if not defiend in desire state
-         """
-         for iface in self._ifaces.values():
--            if iface.is_up and iface.is_master:
-+            if iface.is_desired and iface.is_up and iface.is_master:
-                 cur_iface = self.current_ifaces.get(iface.name)
-                 for slave_name in iface.slaves:
-                     if cur_iface and slave_name in cur_iface.slaves:
-@@ -353,14 +353,17 @@ class Ifaces:
- 
-     def _remove_unknown_interface_type_slaves(self):
-         """
--        When master containing slaves with unknown interface type, they should
--        be removed from master slave list before verifying.
-+        When master containing slaves with unknown interface type or down
-+        state, they should be removed from master slave list before verifying.
-         """
-         for iface in self._ifaces.values():
-             if iface.is_up and iface.is_master and iface.slaves:
-                 for slave_name in iface.slaves:
-                     slave_iface = self._ifaces[slave_name]
--                    if slave_iface.type == InterfaceType.UNKNOWN:
-+                    if (
-+                        slave_iface.type == InterfaceType.UNKNOWN
-+                        or slave_iface.state != InterfaceState.UP
-+                    ):
-                         iface.remove_slave(slave_name)
- 
-     def verify(self, cur_iface_infos):
-diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py
-index cd319ffb..da2dab5b 100644
---- a/libnmstate/nm/applier.py
-+++ b/libnmstate/nm/applier.py
-@@ -80,7 +80,16 @@ def apply_changes(context, net_state, save_to_disk):
-     _preapply_dns_fix(context, net_state)
-     _mark_nm_external_subordinate_changed(context, net_state)
- 
--    ifaces_desired_state = net_state.ifaces.state_to_edit
-+    ifaces_desired_state = []
-+    for iface in net_state.ifaces.all_ifaces.values():
-+        nm_dev = context.get_nm_dev(iface.name)
-+        if nm_dev and not nm_dev.get_managed() and not iface.is_desired:
-+            # We don't change NM.Device from unmanaged to managed unless
-+            # been asked explicitly in desire state
-+            continue
-+        if iface.is_changed or iface.is_desired:
-+            ifaces_desired_state.append(iface.to_dict())
-+
-     ifaces_desired_state.extend(
-         _create_proxy_ifaces_desired_state(ifaces_desired_state)
-     )
--- 
-2.29.2
-
diff --git a/SOURCES/BZ_1933538-bridge-bond-New-property-Interface.COPY_MAC_FROM.patch b/SOURCES/BZ_1933538-bridge-bond-New-property-Interface.COPY_MAC_FROM.patch
deleted file mode 100644
index 3da7bb0..0000000
--- a/SOURCES/BZ_1933538-bridge-bond-New-property-Interface.COPY_MAC_FROM.patch
+++ /dev/null
@@ -1,146 +0,0 @@
-From 34b689a86c7cd4bcf5ab5cf7d903acba7d60f4be Mon Sep 17 00:00:00 2001
-From: Gris Ge <fge@redhat.com>
-Date: Wed, 10 Feb 2021 23:28:37 +0800
-Subject: [PATCH] bridge/bond: New property `Interface.COPY_MAC_FROM`
-
-Introducing `Interface.COPY_MAC_FROM` allowing bridge or bond
-to use MAC address from specified port.
-
-Example:
-
-```yaml
----
-interfaces:
-- name: bond99
-  type: bond
-  state: up
-  copy-mac-from: eth1
-  link-aggregation:
-    mode: balance-rr
-    port:
-    - eth2
-    - eth1
-```
-
-Integration test case included.
-
-Signed-off-by: Gris Ge <fge@redhat.com>
-Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
----
- libnmstate/ifaces/base_iface.py           | 14 +++++++++++
- libnmstate/ifaces/ifaces.py               | 30 +++++++++++++++++++++++
- libnmstate/schema.py                      |  1 +
- libnmstate/schemas/operational-state.yaml |  4 +++
- tests/integration/bond_test.py            | 13 ++++++++++
- tests/integration/linux_bridge_test.py    | 14 +++++++++++
- 6 files changed, 76 insertions(+)
-
-diff --git a/libnmstate/ifaces/base_iface.py b/libnmstate/ifaces/base_iface.py
-index b4ade867..3dbcfe52 100644
---- a/libnmstate/ifaces/base_iface.py
-+++ b/libnmstate/ifaces/base_iface.py
-@@ -391,6 +391,20 @@ class BaseIface:
-         for family, rules in route_rule_metadata.items():
-             self.raw[family][BaseIface.ROUTE_RULES_METADATA] = rules
- 
-+    @property
-+    def copy_mac_from(self):
-+        return self._info.get(Interface.COPY_MAC_FROM)
-+
-+    def apply_copy_mac_from(self, mac):
-+        """
-+        * Add MAC to original desire.
-+        * Remove Interface.COPY_MAC_FROM from original desire.
-+        * Update MAC of merge iface
-+        """
-+        self.raw[Interface.MAC] = mac
-+        self._origin_info[Interface.MAC] = mac
-+        self._origin_info.pop(Interface.COPY_MAC_FROM, None)
-+
- 
- def _remove_empty_description(state):
-     if state.get(Interface.DESCRIPTION) == "":
-diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
-index cfc306c6..1e4d2231 100644
---- a/libnmstate/ifaces/ifaces.py
-+++ b/libnmstate/ifaces/ifaces.py
-@@ -101,12 +101,42 @@ class Ifaces:
-             self._validate_unknown_slaves()
-             self._mark_vf_interface_as_absent_when_sriov_vf_decrease()
-             self._validate_unknown_parent()
-+            self._apply_copy_mac_from()
-             self._gen_metadata()
-             for iface in self._ifaces.values():
-                 iface.pre_edit_validation_and_cleanup()
- 
-             self._pre_edit_validation_and_cleanup()
- 
-+    def _apply_copy_mac_from(self):
-+        for iface in self._ifaces.values():
-+            if iface.type not in (
-+                InterfaceType.LINUX_BRIDGE,
-+                InterfaceType.BOND,
-+            ):
-+                continue
-+            if not iface.copy_mac_from:
-+                continue
-+
-+            if iface.copy_mac_from not in iface.slaves:
-+                raise NmstateValueError(
-+                    f"The interface {iface.name} is holding invalid "
-+                    f"{Interface.COPY_MAC_FROM} property "
-+                    f"as {iface.copy_mac_from} is not in the port "
-+                    f"list: {iface.port}"
-+                )
-+            port_iface = self._ifaces.get(iface.copy_mac_from)
-+            # TODO: bridge/bond might refering the mac from new veth in the
-+            #       same desire state, it too complex to support that.
-+            if not port_iface:
-+                raise NmstateValueError(
-+                    f"The interface {iface.name} is holding invalid "
-+                    f"{Interface.COPY_MAC_FROM} property "
-+                    f"as the port {iface.copy_mac_from} does not exists yet"
-+                )
-+
-+            iface.apply_copy_mac_from(port_iface.mac)
-+
-     def _create_virtual_slaves(self):
-         """
-         Certain master interface could have virtual slaves which does not
-diff --git a/libnmstate/schema.py b/libnmstate/schema.py
-index 8a86c48d..455dbf8f 100644
---- a/libnmstate/schema.py
-+++ b/libnmstate/schema.py
-@@ -44,6 +44,7 @@ class Interface:
- 
-     MAC = "mac-address"
-     MTU = "mtu"
-+    COPY_MAC_FROM = "copy-mac-from"
- 
- 
- class Route:
-diff --git a/libnmstate/schemas/operational-state.yaml b/libnmstate/schemas/operational-state.yaml
-index d856aa5c..8fdeaeec 100644
---- a/libnmstate/schemas/operational-state.yaml
-+++ b/libnmstate/schemas/operational-state.yaml
-@@ -249,6 +249,8 @@ definitions:
-           type: string
-           enum:
-             - bond
-+        copy-mac-from:
-+          type: string
-         link-aggregation:
-           type: object
-           properties:
-@@ -267,6 +269,8 @@ definitions:
-         - $ref: "#/definitions/interface-linux-bridge/ro"
-     ro:
-       properties:
-+        copy-mac-from:
-+          type: string
-         bridge:
-           type: object
-           properties:
--- 
-2.29.2
-
diff --git a/SOURCES/nmstate-0.3.4.tar.gz.asc b/SOURCES/nmstate-0.3.4.tar.gz.asc
deleted file mode 100644
index ac2c220..0000000
--- a/SOURCES/nmstate-0.3.4.tar.gz.asc
+++ /dev/null
@@ -1,16 +0,0 @@
------BEGIN PGP SIGNATURE-----
-
-iQIzBAABCAAdFiEEfUQ+BAINyWGvqJXerIciWuEsPqMFAl8a02UACgkQrIciWuEs
-PqMSmg//T/2C0mP+zb1pnIfcPZvc8dlNgnvtTIN8EK23b6UvxrFYKuPmqRw+Dsir
-N/9enPTUgQKAOtZs7BdtZlCmsaU2bWAF11UgRY+gcSkSVeG0j/kxHLG3sE4RbFiD
-QPKJrqRE6m+ybTOiJ0oVXkR7f2i/AVmZE3+eZHn1TzHQoKZA8MJyExYWmk7wMkfG
-KzE7jvZQ1M4Q6aZKxo4wjAkhAhFLio9HhWnl8z1bLpWWFVHqqMJ04QniDsepczCm
-ISr6grG2TW6bS93lRCdDkS4yGCAYrwZ/5eyN5eOTd/et7FqG/ExFHdVaaro5I1W5
-cbOYyZ1cI/avA9vCWCkC7DUJOh3i5BzzhHaxS65qqpM7fiLIrHZhaLQaLByMO48d
-zo1wDEwIyNvuP4bIVwRycuDhtcLnPs5QwVbfW4HKkn4ULO+inr3lJk8V3ZZ3Ghmz
-qKCrpteJTK/yJl9N2MrXxPvYYe388m4A6GGSVml4mYCd2ZMBrQ8k8fSPdlodmzVJ
-J5gpeJRqm9sdrbv7tmuDfNOjAu0o9MP0/OSA0Lb5ho3pyylGnhsZ7Zkwbn2U/1b2
-zgPmVWJqRhjq01VgderCOerxow7OvetNicrNg/9e7+eFAHV7VUowdKf3vCyk0+nl
-WGeZLxi21w2Q2RH1ThPo6uMxL3pIp7dsbVrqM7oLpUoZzGtFnq8=
-=4Hsb
------END PGP SIGNATURE-----
diff --git a/SOURCES/nmstate-1.0.2.tar.gz.asc b/SOURCES/nmstate-1.0.2.tar.gz.asc
new file mode 100644
index 0000000..ef664a4
--- /dev/null
+++ b/SOURCES/nmstate-1.0.2.tar.gz.asc
@@ -0,0 +1,16 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAABCAAdFiEEfUQ+BAINyWGvqJXerIciWuEsPqMFAmAueEYACgkQrIciWuEs
+PqPJxw//UmWdCJgoClFkEpWqWUkjMmfkGh70PoxtuOeNrAYwHv9zCHDBFjLtaDG1
+18+jakwrVIlTiFHZqfz1g3o0Te86w5rKiU2y0FBtBPZ1cdcJZk2Is5wb/JJo78n+
+9sWRfZmSN0SMiJ5HfzhTdZ2RsZYRSaDPSUxchRY03LzsBusxoK8swWu9oUHqmYKd
+S3k4skP5ZQvpHtKzq9w1lfU4YAw42sRvXHW/++HqGgE0rypf+Wlcu9C+It9kVLCr
+3rdp8iTGTg+LRg7LxFmEsRlmPpxhO25LaxjFvYSFnhE94xOt28KXeHBYs8hPPRwh
++z2w6zJ3hgIrLh10IPzePTWk//KNWDRaAJXQTCma1UE4jdL3+wbxb8H3vl5VCrBU
+3fuj3JwfvFU1NuDf+yuJ0sCKzNXaAzpYYgfIaCaPdtBpg5jl2DTEfEF8QZKYuJDU
+ueCo6reBAlwJzce433aSzBXshFbHG/RdD09duS3p84Dn6ljEN3GfJwUAC9s9TsAQ
+U5+rWog6zMpVke/9yqwEf1KmqtLM3/+Ih30CHb3ZoPTf05KB14k0d1CLDdC9d9dy
+gN0w8xjdTUXbUXW/XIvRVX9KWqyNI6lnZoL0MWzPwUmMxwPJkRpAVpLKpgyUrVpD
+yjtLTFDZJNmfmbi2b0myFFcc2chaXmYlpLCP8vfRYJA3mCee6Xg=
+=b/Mh
+-----END PGP SIGNATURE-----
diff --git a/SPECS/nmstate.spec b/SPECS/nmstate.spec
index 1850ef8..06262d2 100644
--- a/SPECS/nmstate.spec
+++ b/SPECS/nmstate.spec
@@ -3,39 +3,17 @@
 %define libname libnmstate
 
 Name:           nmstate
-Version:        0.3.4
-Release:        27%{?dist}
+Version:        1.0.2
+Release:        5%{?dist}
 Summary:        Declarative network manager API
 License:        LGPLv2+
 URL:            https://github.com/%{srcname}/%{srcname}
 Source0:        %{url}/releases/download/v%{version}/%{srcname}-%{version}.tar.gz
 Source1:        %{url}/releases/download/v%{version}/%{srcname}-%{version}.tar.gz.asc
 Source2:        https://www.nmstate.io/nmstate.gpg
-Patch1:         BZ_1858762-hide_ovs_patch_port_mtu.patch
-Patch2:         BZ_1861263-handle-external-managed-interface.patch
-Patch3:         BZ_1861668_ignore_unknown_iface.patch
-Patch4:         BZ_1862025-remove_existing_profiles.patch
-Patch5:         BZ_1858758-fix_ovs_bond.patch
-Patch6:         BZ_1859844-fix_converting_memory_only.patch
-Patch7:         BZ_1866269-preserve_nm_uuid_in_ovsdb.patch
-Patch8:         BZ_1869345_ovsdb_remove_all_ports.patch
-Patch9:         BZ_1887349-Allow-duplicate-iface-name-in-ovs.patch
-Patch10:        BZ_1890497-nm-bond-Ignore-ad_actor_system-00-00-00-00-00-00.patch
-Patch11:        BZ_1890497-nm.ipv6-call-clear_routing_rules-when-creating-the-s.patch
-Patch12:        BZ_1901571_do_not_check_ovs_daemon_when_showing.patch
-Patch13:        BZ_1904889-do-not-remove-unmanaged-ovs-bridge.patch
-Patch14:        BZ_1910193-support-multiple-gateways.patch
-Patch15:        BZ_1908724-sriov-use-verification-retry-to-wait-VF-been-created.patch
-Patch16:        BZ_1916073_better-handling-for-timeout.patch
-Patch17:        BZ_1918712_use_uuid_for_vlan_vxlan_parent.patch
-Patch18:        BZ_1916073_retry_on_failure_when_activate.patch
-Patch19:        BZ_1931290-SRIOV-Remove-VF-interface-when-total-vfs-decrease.patch
-Patch20:        BZ_1931290-SRIOV-Do-not-create-VF-profiles-automatically.patch
-Patch21:        BZ_1931784-SR-IOV-increase-the-verification-timeout-if-SR-IOV.patch
-Patch22:        BZ_1931784-SR-IOV-fail-on-verification-if-total_vfs-does-not-ma.patch
-Patch23:        BZ_1932247-bridge-do-not-bring-up-existing-ports.patch
-Patch24:        BZ_1932247-nm.applier-ignore-not-desired-unmanaged-ifaces.patch
-Patch25:        BZ_1933538-bridge-bond-New-property-Interface.COPY_MAC_FROM.patch
+Patch1:         BZ_1931751-nmstate-fix-return-code.patch
+Patch2:         BZ_1931355-SRIOV-wait-VF-mount-decrease.patch
+Patch3:         BZ_1932247-nm-Don-t-touch-unmanaged-interface-unless-desired.patch
 BuildArch:      noarch
 BuildRequires:  python3-devel
 BuildRequires:  python3-setuptools
@@ -62,6 +40,8 @@ Recommends:     NetworkManager-config-server
 # required for OVS and team support
 Suggests:       NetworkManager-ovs
 Suggests:       NetworkManager-team
+Requires:       nispor
+Requires:       python3dist(varlink)
 
 %package -n nmstate-plugin-ovsdb
 Summary:        nmstate plugin for OVS database manipulation
@@ -106,53 +86,58 @@ gpgv2 --keyring ./gpgkey-mantainers.gpg %{SOURCE1} %{SOURCE0}
 %{python3_sitelib}/%{libname}/plugins/__pycache__/nmstate_plugin_ovsdb*
 
 %changelog
-* Wed Mar 03 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.3.4-27
-- Introduce `Interface.COPY_MAC_FROM` from bond and bridge. RHBZ#1933538
+* Wed Mar 03 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-5
+- New patch for fixing unmanaged interfaces being managed. RHBZ#1932247
 
-* Wed Mar 03 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.3.4-26
-- New patch do not activating SR-IOV VFs automatically. RHBZ#1931290
-- New patch fixing Nmstate waits when SR-IOV VFs are decreased. RHBZ#1931784
-- New patch fixing Nmstate activating unmanaged bridge ports. RHBZ#1932247
+* Tue Feb 23 2021 Gris Ge <fge@redhat.com> - 1.0.2-4
+- New patch for SRIOV decrease VF amount. RHBZ#1931355
 
-* Fri Feb 05 2021 Gris Ge <fge@redhat.com> - 0.3.4-25
-- Remove patch for fixing the autoconnect on existing profile. RHBZ#1918712
+* Tue Feb 23 2021 Gris Ge <fge@redhat.com> - 1.0.2-3
+- Fix actiation failure when decrease VF mount on i40e. RHBZ#1931355
 
-* Thu Feb 04 2021 Gris Ge <fge@redhat.com> - 0.3.4-24
-- New patch fixing activation failure with 1000 interfaces. RHBZ#1916073
+* Tue Feb 23 2021 Gris Ge <fge@redhat.com> - 1.0.2-2
+- Fix nmstatectl return code of `set` command. RHBZ#1931751
 
-* Wed Feb 03 2021 Gris Ge <fge@redhat.com> - 0.3.4-23
-- Enforcing autoconnect on existing profile. RHBZ#1918712
+* Fri Feb 19 2021 Gris Ge <fge@redhat.com> - 1.0.2-1
+- Upgrade to 1.0.2.
 
-* Fri Jan 22 2021 Gris Ge <fge@redhat.com> - 0.3.4-22
-- Fix creating VLAN/VxLAN over interface also used for OVS. RHBZ#1918712
+* Wed Feb 10 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-0.3
+- Fix sources name
 
-* Sun Jan 17 2021 Gris Ge <fge@redhat.com> - 0.3.4-21
-- Additional patch for profile deactivation and deletion. RHBZ#1916073
+* Wed Feb 10 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-0.2
+- Upgrade to 1.0.2 alpha 2
 
-* Thu Jan 14 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.3.4-20
-- Better handling for timeout on activation. RHBZ#1916073
+* Tue Jan 26 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-0.1
+- Upgrade to 1.0.2 alpha 1
 
-* Mon Jan 04 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.3.4-19
-- Use verification retry to wait SR-IOV VF been created. RHBZ#1908724
+* Tue Jan 19 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.1-1
+- Upgrade to 1.0.1. RHBZ#1881287
 
-* Wed Dec 23 2020 Gris Ge <fge@redhat.com> - 0.3.4-18
-- Support multiple gateways. RHBZ#1910193
+* Tue Jan 05 2021 Gris Ge <fge@redhat.com> - 1.0.1-0.1
+- Upgrade to 1.0.1 alpha 1
 
-* Mon Dec 07 2020 Gris Ge <fge@redhat.com> - 0.3.4-17
-- Rebuild to retrigger the CI gating. RHBZ#1904889
+* Tue Dec 08 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.0-1
+- Upgrade to 1.0.0
 
-* Mon Dec 07 2020 Gris Ge <fge@redhat.com> - 0.3.4-16
-- Don't remove unmanaged OVS interface. RHBZ#1904889
+* Mon Nov 16 2020 Gris Ge <fge@redhat.com> - 1.0.0-0.1
+- Upgrade to 1.0.0 alpha 1
 
-* Thu Nov 26 2020 Gris Ge <fge@redhat.com> - 0.3.4-15
-- Fix `libnmstate.show()` in container with OVS bridge. RHBZ#1901571
+* Wed Oct 28 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.4.1-2
+- Allow VRF port to hold IP information
 
-* Wed Nov 04 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.3.4-14
-- Ignore bond zero ad_actor_system. RHBZ#1890497
-- Fix clear IPv6 routing rules.
+* Thu Oct 22 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.4.1-1
+- Upgrade to 0.4.1
 
-* Wed Oct 14 2020 Gris Ge <fge@redhat.com> - 0.3.4-13
-- Allowing duplicate interface name of ovs. RHBZ#1887349
+* Tue Oct 20 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.4.0-3
+- Add nispor as a dependency for CI gating
+
+* Tue Oct 20 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.4.0-2
+- Rebuild for CI gating
+- Remove old patches from the repository
+
+* Mon Sep 14 2020 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.4.0-1
+- Upgrade to 0.4.0
+- Sync. up with upstream spec file.
 
 * Tue Aug 18 2020 Gris Ge <fge@redhat.com> - 0.3.4-12
 - New patch: OVSDB: Allowing remove all OVS ports. RHBZ#1869345