diff --git a/SOURCES/1002-dns-sort-according-to-priority-rh2134563.patch b/SOURCES/1002-dns-sort-according-to-priority-rh2134563.patch new file mode 100644 index 0000000..12e79f5 --- /dev/null +++ b/SOURCES/1002-dns-sort-according-to-priority-rh2134563.patch @@ -0,0 +1,69 @@ +From c35eb06542b555523df8d7a6e1d00826deb4f625 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Thu, 13 Oct 2022 17:23:15 +0200 +Subject: [PATCH 1/2] dns: add comment explaining the purpose of `any_removed` + +(cherry picked from commit 4d1ecd8d6dbe6666f9005950a95a6ba8321e653c) +(cherry picked from commit 01b4040a7ad6f0b8c4aad1aabe4827841df2fe1e) +--- + src/core/dns/nm-dns-manager.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c +index 1e54452aa4..c08e2cacd7 100644 +--- a/src/core/dns/nm-dns-manager.c ++++ b/src/core/dns/nm-dns-manager.c +@@ -2039,8 +2039,14 @@ nm_dns_manager_set_ip_config(NMDnsManager *self, + + if (!ip_data) { + ip_data = _dns_config_ip_data_new(data, addr_family, source_tag, l3cd, ip_config_type); +- if (!any_removed) ++ if (!any_removed) { ++ /* `any_removed` tracks whether we deleted any ip_data. If that happened, ++ * we already compared the old and new l3cds and set `changed` accordingly. ++ * Here we only need to set `changed` if we are adding a new ip_data without ++ * removing the old one. ++ */ + changed = TRUE; ++ } + } else { + ip_data->ip_config_type = ip_config_type; + changed = TRUE; +-- +2.37.3 + +From b9b64e667afe4f6f55747a55a28e5f50cf352a4a Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Thu, 13 Oct 2022 17:06:19 +0200 +Subject: [PATCH 2/2] dns: sort the ip-data list when a new element is added + +In nm_dns_manager_set_ip_config() we try to avoid calling update_dns() +unless something changes, because updating DNS is expensive and can +trigger other actions such as a new hostname resolution. + +When we add a new ip_data, even if the new element is equivalent to +the old one that was removed, we need to sort the list again. + +Fixes: ce0a36d20fa6 ('dns: better track l3cd changes') +https://bugzilla.redhat.com/show_bug.cgi?id=2098574 +(cherry picked from commit 3cc7801779ed05d13c3e2422f11ddb365bc37242) +(cherry picked from commit db4c55c8d32179bcaf222029469802d96312413b) +--- + src/core/dns/nm-dns-manager.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c +index c08e2cacd7..a2fead3f35 100644 +--- a/src/core/dns/nm-dns-manager.c ++++ b/src/core/dns/nm-dns-manager.c +@@ -2039,6 +2039,7 @@ nm_dns_manager_set_ip_config(NMDnsManager *self, + + if (!ip_data) { + ip_data = _dns_config_ip_data_new(data, addr_family, source_tag, l3cd, ip_config_type); ++ priv->ip_data_lst_need_sort = TRUE; + if (!any_removed) { + /* `any_removed` tracks whether we deleted any ip_data. If that happened, + * we already compared the old and new l3cds and set `changed` accordingly. +-- +2.37.3 + diff --git a/SOURCES/1003-dhcp-decline-IPv6-lease-if-all-adresses-fail-DAD-rh2132281.patch b/SOURCES/1003-dhcp-decline-IPv6-lease-if-all-adresses-fail-DAD-rh2132281.patch new file mode 100644 index 0000000..527c439 --- /dev/null +++ b/SOURCES/1003-dhcp-decline-IPv6-lease-if-all-adresses-fail-DAD-rh2132281.patch @@ -0,0 +1,220 @@ +From 67f7ee1e7a5c4cfc2d0b67c56a8655b3d9f4781d Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Thu, 1 Sep 2022 10:21:20 +0200 +Subject: [PATCH] dhcp: decline IPv6 lease if all adresses fail DAD + +Currently we accept the DHCPv6 just after addresses are configured on +kernel, without waiting DAD result. Instead, wait that DAD completes +and decline the lease if all addresses are detected as duplicate. + +Note that when an address has non-infinite lifetime and fails DAD, +kernel removes it automatically. With iproute2 we see something like: + +602: testX6 inet6 2620::1234:5678/128 scope global tentative dynamic noprefixroute + valid_lft 7500sec preferred_lft 7200sec +Deleted 602: testX6 inet6 2620::1234:5678/128 scope global dadfailed tentative dynamic noprefixroute + valid_lft 7500sec preferred_lft 7200sec + +Since the address gets removed from the platform cache, at the moment +we don't have a way to check the flags of the removal +message. Therefore, we assume that any address that goes away in +tentative state was detected as duplicate. + +https://bugzilla.redhat.com/show_bug.cgi?id=2096386 +(cherry picked from commit a7eb77260ae6cfc56313e99f6178daa0b8283226) +(cherry picked from commit b671c36189bcddef058bcdce6c9bfeaddeb6c340) +--- + src/core/dhcp/nm-dhcp-client.c | 128 +++++++++++++++++++++++---------- + 1 file changed, 92 insertions(+), 36 deletions(-) + +diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c +index 77cfeecf81..a22fe65b6d 100644 +--- a/src/core/dhcp/nm-dhcp-client.c ++++ b/src/core/dhcp/nm-dhcp-client.c +@@ -1043,8 +1043,11 @@ ipv6_lladdr_find(NMDhcpClient *self) + return NULL; + } + +-static const NMPlatformIP6Address * +-ipv6_tentative_addr_find(NMDhcpClient *self) ++static void ++ipv6_tentative_addr_check(NMDhcpClient *self, ++ GPtrArray **tentative, ++ GPtrArray **missing, ++ const NMPlatformIP6Address **valid) + { + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); + NMDedupMultiIter iter; +@@ -1062,16 +1065,26 @@ ipv6_tentative_addr_find(NMDhcpClient *self) + NMP_CACHE_ID_TYPE_OBJECT_TYPE, + &needle)); + if (!pladdr) { +- /* Address was removed from platform */ ++ /* address removed: we assume that's because DAD failed */ ++ if (missing) { ++ if (!*missing) ++ *missing = g_ptr_array_new(); ++ g_ptr_array_add(*missing, (gpointer) addr); ++ } + continue; + } + + if (NM_FLAGS_HAS(pladdr->n_ifa_flags, IFA_F_TENTATIVE) +- && !NM_FLAGS_HAS(pladdr->n_ifa_flags, IFA_F_OPTIMISTIC)) +- return pladdr; +- } ++ && !NM_FLAGS_HAS(pladdr->n_ifa_flags, IFA_F_OPTIMISTIC)) { ++ if (tentative) { ++ if (!*tentative) ++ *tentative = g_ptr_array_new(); ++ g_ptr_array_add(*tentative, (gpointer) addr); ++ } ++ } + +- return NULL; ++ NM_SET_OUT(valid, addr); ++ } + } + + static void +@@ -1108,21 +1121,61 @@ l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDhcp + + if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE + && priv->l3cfg_notify.wait_ipv6_dad) { +- const NMPlatformIP6Address *tentative; ++ gs_unref_ptrarray GPtrArray *tentative = NULL; ++ gs_unref_ptrarray GPtrArray *missing = NULL; ++ const NMPlatformIP6Address *valid = NULL; ++ char str[NM_UTILS_TO_STRING_BUFFER_SIZE]; ++ guint i; ++ gs_free_error GError *error = NULL; ++ ++ ipv6_tentative_addr_check(self, &tentative, &missing, &valid); ++ if (tentative) { ++ for (i = 0; i < tentative->len; i++) { ++ _LOGD("still waiting DAD for address: %s", ++ nm_platform_ip6_address_to_string(tentative->pdata[i], str, sizeof(str))); ++ } ++ } else { ++ /* done */ + +- tentative = ipv6_tentative_addr_find(self); +- if (!tentative) { +- _LOGD("addresses in the lease completed DAD"); + priv->l3cfg_notify.wait_ipv6_dad = FALSE; + nm_clear_g_source_inst(&priv->v6.dad_timeout_source); + l3_cfg_notify_check_connected(self); +- _emit_notify( +- self, +- &((NMDhcpClientNotifyData){.notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE, +- .lease_update = { +- .l3cd = priv->l3cd_curr, +- .accepted = TRUE, +- }})); ++ ++ if (missing) { ++ for (i = 0; i < missing->len; i++) { ++ _LOGE("DAD failed for address: %s", ++ nm_platform_ip6_address_to_string(missing->pdata[i], str, sizeof(str))); ++ } ++ } ++ ++ if (valid) { ++ /* at least one non-duplicate address */ ++ _LOGD("addresses in the lease completed DAD: accept the lease"); ++ ++ if (_dhcp_client_accept(self, priv->l3cd_curr, &error)) { ++ _emit_notify(self, ++ &((NMDhcpClientNotifyData){ ++ .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE, ++ .lease_update = { ++ .l3cd = priv->l3cd_curr, ++ .accepted = TRUE, ++ }})); ++ } else { ++ gs_free char *reason = ++ g_strdup_printf("error accepting lease: %s", error->message); ++ ++ _LOGD("accept failed: %s", error->message); ++ _emit_notify(self, ++ &((NMDhcpClientNotifyData){ ++ .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD, ++ .it_looks_bad.reason = reason, ++ })); ++ } ++ } else { ++ _LOGD("decline the lease"); ++ if (!_dhcp_client_decline(self, priv->l3cd_curr, "DAD failed", &error)) ++ _LOGD("decline failed: %s", error->message); ++ } + } + } + +@@ -1155,20 +1208,23 @@ l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDhcp + address4->peer_address)) + goto wait_dhcp_commit_done; + } else { +- const NMPlatformIP6Address *address6 = (const NMPlatformIP6Address *) lease_address; +- const NMPlatformIP6Address *tentative; +- char str[NM_UTILS_TO_STRING_BUFFER_SIZE]; ++ const NMPlatformIP6Address *address6 = (const NMPlatformIP6Address *) lease_address; ++ gs_unref_ptrarray GPtrArray *tentative = NULL; ++ char str[NM_UTILS_TO_STRING_BUFFER_SIZE]; ++ guint i; + + if (!nm_l3_config_data_lookup_address_6(committed_l3cd, &address6->address)) + goto wait_dhcp_commit_done; + +- tentative = ipv6_tentative_addr_find(self); ++ ipv6_tentative_addr_check(self, &tentative, NULL, NULL); + if (tentative) { + priv->l3cfg_notify.wait_ipv6_dad = TRUE; + priv->v6.dad_timeout_source = + nm_g_timeout_add_seconds_source(30, ipv6_dad_timeout, self); +- _LOGD("wait DAD for address %s", +- nm_platform_ip6_address_to_string(tentative, str, sizeof(str))); ++ for (i = 0; i < tentative->len; i++) { ++ _LOGD("wait DAD for address %s", ++ nm_platform_ip6_address_to_string(tentative->pdata[i], str, sizeof(str))); ++ } + } else { + priv->l3cfg_notify.wait_ipv6_dad = FALSE; + nm_clear_g_source_inst(&priv->v6.dad_timeout_source); +@@ -1179,22 +1235,22 @@ l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDhcp + + l3_cfg_notify_check_connected(self); + +- _LOGD("accept lease"); ++ if (priv->config.addr_family == AF_INET || !priv->l3cfg_notify.wait_ipv6_dad) { ++ _LOGD("accept lease"); + +- if (!_dhcp_client_accept(self, priv->l3cd_curr, &error)) { +- gs_free char *reason = g_strdup_printf("error accepting lease: %s", error->message); ++ if (!_dhcp_client_accept(self, priv->l3cd_curr, &error)) { ++ gs_free char *reason = g_strdup_printf("error accepting lease: %s", error->message); + +- _LOGD("accept failed: %s", error->message); ++ _LOGD("accept failed: %s", error->message); + +- _emit_notify(self, +- &((NMDhcpClientNotifyData){ +- .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD, +- .it_looks_bad.reason = reason, +- })); +- goto wait_dhcp_commit_done; +- } ++ _emit_notify(self, ++ &((NMDhcpClientNotifyData){ ++ .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD, ++ .it_looks_bad.reason = reason, ++ })); ++ goto wait_dhcp_commit_done; ++ } + +- if (priv->config.addr_family == AF_INET || !priv->l3cfg_notify.wait_ipv6_dad) { + _emit_notify( + self, + &((NMDhcpClientNotifyData){.notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE, +-- +2.38.1 + diff --git a/SOURCES/1004-ovs-wait-that-links-disappear-during-initial-cleanup-rh2153429.patch b/SOURCES/1004-ovs-wait-that-links-disappear-during-initial-cleanup-rh2153429.patch new file mode 100644 index 0000000..3a13c4b --- /dev/null +++ b/SOURCES/1004-ovs-wait-that-links-disappear-during-initial-cleanup-rh2153429.patch @@ -0,0 +1,287 @@ +From bfb21252e6e72f214f1f3bd6e76e210207692c88 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 20 Sep 2022 14:05:42 +0200 +Subject: [PATCH] ovs: wait that links disappear during initial cleanup + +At startup, we remove from ovsdb any existing interface created by NM +and later an interface with the same name might be readded. This can +cause race conditions. Consider this series of events: + +1. at startup NM removes the entry from ovsdb; +2. ovsdb reports success; +3. NM inserts an interface with the same name again; +4. ovs-vswitch monitors ovsdb changes, and gets events for removal and + insertion. Depending on how those events are split in different + batches, it might decide: + 4a. to delete the link and add it back, or + 4b. to keep the existing link because the delete and insertion + cancel out each other. + +When NM sees the link staying in platform, it doesn't know if it's +because of 4b or because 4a will happen eventually. + +To avoid this ambiguity, after ovsdb reports the successful deletion +NM should also wait that the link disappears from platform. + +Unfortunately, this means that ovsdb gets a dependency to the platform +code. + +https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1386 +(cherry picked from commit 4f60fe293cd5461c47d218b632753ecdfb50cbab) +(cherry picked from commit f702be2992f0f34c82e96b420947f9056a4cb24e) +--- + src/core/devices/ovs/nm-ovsdb.c | 155 +++++++++++++++++++++++++++----- + 1 file changed, 132 insertions(+), 23 deletions(-) + +diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c +index e7c9685240..d3e858a19c 100644 +--- a/src/core/devices/ovs/nm-ovsdb.c ++++ b/src/core/devices/ovs/nm-ovsdb.c +@@ -18,6 +18,7 @@ + #include "nm-manager.h" + #include "nm-setting-ovs-external-ids.h" + #include "nm-priv-helper-call.h" ++#include "libnm-platform/nm-platform.h" + + /*****************************************************************************/ + +@@ -120,6 +121,7 @@ enum { + static guint signals[LAST_SIGNAL] = {0}; + + typedef struct { ++ NMPlatform *platform; + GSocketConnection *conn; + GCancellable *conn_cancellable; + char buf[4096]; /* Input buffer */ +@@ -135,8 +137,14 @@ typedef struct { + GHashTable *bridges; /* bridge uuid => OpenvswitchBridge */ + char *db_uuid; + guint num_failures; +- guint num_pending_deletions; + bool ready : 1; ++ struct { ++ GPtrArray *interfaces; /* Interface names we are waiting to go away */ ++ GSource *timeout_source; /* After all deletions complete, wait this ++ * timeout for interfaces to disappear */ ++ gulong link_changed_id; /* Platform link-changed signal handle */ ++ guint num_pending_del; /* Number of ovsdb deletions pending */ ++ } cleanup; + } NMOvsdbPrivate; + + struct _NMOvsdb { +@@ -161,6 +169,7 @@ static void ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposin + static void ovsdb_read(NMOvsdb *self); + static void ovsdb_write(NMOvsdb *self); + static void ovsdb_next_command(NMOvsdb *self); ++static void cleanup_check_ready(NMOvsdb *self); + + /*****************************************************************************/ + +@@ -2283,21 +2292,114 @@ ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposing) + } + + static void +-_check_ready(NMOvsdb *self) ++cleanup_emit_ready(NMOvsdb *self, const char *reason) ++{ ++ NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); ++ ++ _LOGT("cleanup: ready (%s)", reason); ++ ++ nm_clear_pointer(&priv->cleanup.interfaces, g_ptr_array_unref); ++ nm_clear_g_source_inst(&priv->cleanup.timeout_source); ++ nm_clear_g_signal_handler(priv->platform, &priv->cleanup.link_changed_id); ++ ++ priv->ready = TRUE; ++ g_signal_emit(self, signals[READY], 0); ++ nm_manager_unblock_failed_ovs_interfaces(nm_manager_get()); ++} ++ ++static gboolean ++cleanup_timeout(NMOvsdb *self) ++{ ++ cleanup_emit_ready(self, "timeout"); ++ return G_SOURCE_CONTINUE; ++} ++ ++static void ++cleanup_link_cb(NMPlatform *platform, ++ int obj_type_i, ++ int ifindex, ++ NMPlatformLink *plink, ++ int change_type_i, ++ gpointer user_data) ++{ ++ const NMPlatformSignalChangeType change_type = change_type_i; ++ ++ if (change_type != NM_PLATFORM_SIGNAL_REMOVED) ++ return; ++ ++ cleanup_check_ready(user_data); ++} ++ ++static void ++cleanup_check_ready(NMOvsdb *self) + { + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); ++ guint i = 0; + + nm_assert(!priv->ready); + +- if (priv->num_pending_deletions == 0) { +- priv->ready = TRUE; +- g_signal_emit(self, signals[READY], 0); +- nm_manager_unblock_failed_ovs_interfaces(nm_manager_get()); ++ if (priv->cleanup.num_pending_del > 0) ++ return; ++ ++ /* After we have deleted an interface from ovsdb, the link will stay ++ * in platform until ovs-vswitch removes it. To avoid race conditions, ++ * we need to wait until the link goes away; otherwise, after adding the ++ * interface again, these race conditions can happen: ++ * 1) we see the link in platform, and proceed with activation. But after ++ * that, ovs-vswitchd reads the updates from ovsdb-server and deletes/recreates ++ * the link. ++ * 2) ovs-vswitch combines the delete/insert of the interface to a no-op. NM sees ++ * the link staying in platform, but doesn't know whether the link is ready ++ * or we are again in case 1) ++ * In other words, it's necessary to wait that the link goes away before inserting ++ * the interface again. ++ */ ++ while (i < nm_g_ptr_array_len(priv->cleanup.interfaces)) { ++ const char *ifname; ++ const NMDedupMultiHeadEntry *pl_links_head_entry; ++ NMDedupMultiIter pliter; ++ const NMPlatformLink *link; ++ gboolean found = FALSE; ++ ++ ifname = priv->cleanup.interfaces->pdata[i]; ++ pl_links_head_entry = nm_platform_lookup_link_by_ifname(priv->platform, ifname); ++ nmp_cache_iter_for_each_link (&pliter, pl_links_head_entry, &link) { ++ if (link->type == NM_LINK_TYPE_OPENVSWITCH ++ && nmp_object_is_visible(NMP_OBJECT_UP_CAST(link))) { ++ found = TRUE; ++ break; ++ } ++ } ++ ++ if (!found) { ++ g_ptr_array_remove_index_fast(priv->cleanup.interfaces, i); ++ continue; ++ } ++ i++; + } ++ ++ if (nm_g_ptr_array_len(priv->cleanup.interfaces) == 0) { ++ cleanup_emit_ready(self, "all interfaces deleted"); ++ return; ++ } ++ ++ _LOGT("cleanup: still waiting for %d interfaces", priv->cleanup.interfaces->len); ++ ++ if (priv->cleanup.timeout_source) { ++ /* We already registered the timeout/change-callback */ ++ return; ++ } ++ ++ priv->cleanup.timeout_source = ++ nm_g_timeout_add_seconds_source(6, G_SOURCE_FUNC(cleanup_timeout), self); ++ priv->cleanup.link_changed_id = g_signal_connect(priv->platform, ++ NM_PLATFORM_SIGNAL_LINK_CHANGED, ++ G_CALLBACK(cleanup_link_cb), ++ self); + } + + static void +-_del_initial_iface_cb(GError *error, gpointer user_data) ++cleanup_del_iface_cb(GError *error, gpointer user_data) + { + NMOvsdb *self; + gs_free char *ifname = NULL; +@@ -2309,18 +2411,18 @@ _del_initial_iface_cb(GError *error, gpointer user_data) + return; + + priv = NM_OVSDB_GET_PRIVATE(self); +- nm_assert(priv->num_pending_deletions > 0); +- priv->num_pending_deletions--; ++ nm_assert(priv->cleanup.num_pending_del > 0); ++ priv->cleanup.num_pending_del--; + +- _LOGD("delete initial interface '%s': %s %s%s%s, pending %u", ++ _LOGD("cleanup: deleted interface '%s': %s %s%s%s, pending %u", + ifname, + error ? "error" : "success", + error ? "(" : "", + error ? error->message : "", + error ? ")" : "", +- priv->num_pending_deletions); ++ priv->cleanup.num_pending_del); + +- _check_ready(self); ++ cleanup_check_ready(self); + } + + static void +@@ -2331,7 +2433,7 @@ ovsdb_cleanup_initial_interfaces(NMOvsdb *self) + NMUtilsUserData *data; + GHashTableIter iter; + +- if (priv->ready || priv->num_pending_deletions != 0) ++ if (priv->ready || priv->cleanup.num_pending_del > 0 || priv->cleanup.interfaces) + return; + + /* Delete OVS interfaces added by NM. Bridges and ports and +@@ -2339,17 +2441,22 @@ ovsdb_cleanup_initial_interfaces(NMOvsdb *self) + * when no interface is present. */ + g_hash_table_iter_init(&iter, self->_priv.interfaces); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &interface)) { +- if (interface->connection_uuid) { +- priv->num_pending_deletions++; +- _LOGD("deleting initial interface '%s' (pending: %u)", +- interface->name, +- priv->num_pending_deletions); +- data = nm_utils_user_data_pack(self, g_strdup(interface->name)); +- nm_ovsdb_del_interface(self, interface->name, _del_initial_iface_cb, data); ++ if (!interface->connection_uuid) { ++ /* not created by NM, ignore */ ++ continue; + } ++ ++ if (!priv->cleanup.interfaces) ++ priv->cleanup.interfaces = g_ptr_array_new_with_free_func(g_free); ++ g_ptr_array_add(priv->cleanup.interfaces, g_strdup(interface->name)); ++ ++ _LOGD("cleanup: deleting interface '%s'", interface->name); ++ priv->cleanup.num_pending_del++; ++ data = nm_utils_user_data_pack(self, g_strdup(interface->name)); ++ nm_ovsdb_del_interface(self, interface->name, cleanup_del_iface_cb, data); + } + +- _check_ready(self); ++ cleanup_check_ready(self); + } + + static void +@@ -2622,8 +2729,9 @@ nm_ovsdb_init(NMOvsdb *self) + + c_list_init(&priv->calls_lst_head); + +- priv->input = g_string_new(NULL); +- priv->output = g_string_new(NULL); ++ priv->platform = g_object_ref(NM_PLATFORM_GET); ++ priv->input = g_string_new(NULL); ++ priv->output = g_string_new(NULL); + priv->bridges = + g_hash_table_new_full(nm_pstr_hash, nm_pstr_equal, (GDestroyNotify) _free_bridge, NULL); + priv->ports = +@@ -2653,6 +2761,7 @@ dispose(GObject *object) + priv->output = NULL; + } + ++ g_clear_object(&priv->platform); + nm_clear_pointer(&priv->bridges, g_hash_table_destroy); + nm_clear_pointer(&priv->ports, g_hash_table_destroy); + nm_clear_pointer(&priv->interfaces, g_hash_table_destroy); +-- +2.38.1 + diff --git a/SOURCES/1005-core-wait-for-carrier-before-resolving-hostname-via-rh2152891.patch b/SOURCES/1005-core-wait-for-carrier-before-resolving-hostname-via-rh2152891.patch new file mode 100644 index 0000000..cdd64d6 --- /dev/null +++ b/SOURCES/1005-core-wait-for-carrier-before-resolving-hostname-via-rh2152891.patch @@ -0,0 +1,94 @@ +From 43c39b1e1ef66f2ecf970086fdd05ce9b0c7fedf Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Wed, 7 Sep 2022 16:50:02 +0200 +Subject: [PATCH] core: wait for carrier before resolving hostname via DNS + +If there is no carrier on a device, don't try to resolve the hostname +on it. Instead, subscribe to carrier change notifications and retry +again once carrier goes up. + +https://bugzilla.redhat.com/show_bug.cgi?id=2118817 +https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1402 +(cherry picked from commit e3cf5083fba8dd1a3a1df69069de2f7e7411dd5e) +(cherry picked from commit 1673e3f0518cff15dd19f871baecdf64bef48bc7) +--- + src/core/devices/nm-device.c | 7 +++++++ + src/core/nm-policy.c | 29 ++++++++++++++++++++++++++--- + 2 files changed, 33 insertions(+), 3 deletions(-) + +diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c +index 7585acf4d3..461f57b5c1 100644 +--- a/src/core/devices/nm-device.c ++++ b/src/core/devices/nm-device.c +@@ -17158,6 +17158,13 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean + /* If the device is not supposed to have addresses, + * return an immediate empty result.*/ + if (!nm_device_get_applied_connection(self)) { ++ nm_clear_pointer(&priv->hostname_resolver_x[IS_IPv4], _hostname_resolver_free); ++ NM_SET_OUT(out_wait, FALSE); ++ return NULL; ++ } ++ ++ if (!priv->carrier) { ++ nm_clear_pointer(&priv->hostname_resolver_x[IS_IPv4], _hostname_resolver_free); + NM_SET_OUT(out_wait, FALSE); + return NULL; + } +diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c +index 16b0211fa2..c24b484f30 100644 +--- a/src/core/nm-policy.c ++++ b/src/core/nm-policy.c +@@ -796,6 +796,20 @@ device_dns_lookup_done(NMDevice *device, gpointer user_data) + update_system_hostname(self, "lookup finished"); + } + ++static void ++device_carrier_changed(NMDevice *device, GParamSpec *pspec, gpointer user_data) ++{ ++ NMPolicyPrivate *priv = user_data; ++ NMPolicy *self = _PRIV_TO_SELF(priv); ++ gs_free char *msg = NULL; ++ ++ if (nm_device_has_carrier(device)) { ++ g_signal_handlers_disconnect_by_func(device, device_carrier_changed, priv); ++ msg = g_strdup_printf("device '%s' got carrier", nm_device_get_iface(device)); ++ update_system_hostname(self, msg); ++ } ++} ++ + static void + update_system_hostname(NMPolicy *self, const char *msg) + { +@@ -880,6 +894,7 @@ update_system_hostname(NMPolicy *self, const char *msg) + info = &g_array_index(infos, DeviceHostnameInfo, i); + addr_family = info->IS_IPv4 ? AF_INET : AF_INET6; + g_signal_handlers_disconnect_by_func(info->device, device_dns_lookup_done, self); ++ g_signal_handlers_disconnect_by_func(info->device, device_carrier_changed, priv); + + if (info->from_dhcp) { + dhcp_config = nm_device_get_dhcp_config(info->device, addr_family); +@@ -905,10 +920,18 @@ update_system_hostname(NMPolicy *self, const char *msg) + + if (priv->hostname_mode != NM_POLICY_HOSTNAME_MODE_DHCP) { + if (info->from_dns) { +- const char *result; +- gboolean wait = FALSE; ++ const char *result = NULL; ++ gboolean wait = FALSE; + +- result = nm_device_get_hostname_from_dns_lookup(info->device, addr_family, &wait); ++ if (nm_device_has_carrier(info->device)) { ++ result = ++ nm_device_get_hostname_from_dns_lookup(info->device, addr_family, &wait); ++ } else { ++ g_signal_connect(info->device, ++ "notify::" NM_DEVICE_CARRIER, ++ G_CALLBACK(device_carrier_changed), ++ priv); ++ } + if (result) { + _set_hostname(self, result, "from address lookup"); + return; +-- +2.38.1 + diff --git a/SPECS/NetworkManager.spec b/SPECS/NetworkManager.spec index c5d38ef..4fde75e 100644 --- a/SPECS/NetworkManager.spec +++ b/SPECS/NetworkManager.spec @@ -6,7 +6,7 @@ %global epoch_version 1 %global real_version 1.40.0 %global rpm_version %{real_version} -%global release_version 2 +%global release_version 5 %global snapshot %{nil} %global git_sha %{nil} %global bcond_default_debug 0 @@ -196,6 +196,10 @@ Patch3: 0003-order-ipv6-addresses.patch # Bugfixes that are only relevant until next rebase of the package. Patch1001: 1001-revert-restart-DHCP-when-MAC-changes-rh2124443.patch +Patch1002: 1002-dns-sort-according-to-priority-rh2134563.patch +Patch1003: 1003-dhcp-decline-IPv6-lease-if-all-adresses-fail-DAD-rh2132281.patch +Patch1004: 1004-ovs-wait-that-links-disappear-during-initial-cleanup-rh2153429.patch +Patch1005: 1005-core-wait-for-carrier-before-resolving-hostname-via-rh2152891.patch Requires(post): systemd %if 0%{?fedora} || 0%{?rhel} >= 8 @@ -1231,6 +1235,16 @@ fi %changelog +* Fri Dec 16 2022 Fernando Fernandez Mancera 1:1.40.0-5 +- ovs: wait that links disappear during initial cleanup (rh #2153429) +- core: wait for carrier before resolving hostname via DNS (rh #2152891) + +* Mon Nov 28 2022 Fernando Fernandez Mancera 1:1.40.0-4 +- dhcp: decline IPv6 lease if all addresses fail DAD (rh #2132281) + +* Tue Nov 8 2022 Beniamino Galvani - 1:1.40.0-3 +- dns: ensure that nameservers are sorted according to priority (rh #2134563) + * Thu Oct 20 2022 Beniamino Galvani - 1:1.40.0-2 - Don't restart DHCP when MAC changes, to avoid that the IP changes (rh #2124443)