about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2020-03-13 00:44:14 +0100
committerMichael Biebl <biebl@debian.org>2020-03-13 00:44:14 +0100
commitb012fa6e1d808e0736c009799c62d835cbfcc1dd (patch)
treeff9a3777f6740e91b55f0a566914bfe4ab37935f /src
parente536d40eaea5dcdc0743b0a5e8e17faa46608a50 (diff)
New upstream version 1.22.10 upstream/1.22.10
Diffstat (limited to 'src')
-rw-r--r--src/devices/nm-device-bond.c11
-rw-r--r--src/devices/nm-device-ethernet.c4
-rw-r--r--src/devices/nm-device.c6
-rw-r--r--src/devices/ovs/nm-device-ovs-port.c13
-rw-r--r--src/devices/wwan/nm-modem-broadband.c10
-rw-r--r--src/dhcp/nm-dhcp-nettools.c1
-rw-r--r--src/dns/nm-dns-manager.c4
-rw-r--r--src/nm-config.c38
-rw-r--r--src/nm-config.h3
-rw-r--r--src/nm-logging.c39
-rw-r--r--src/nm-manager.c115
-rw-r--r--src/nm-manager.h2
-rw-r--r--src/platform/nmp-object.h10
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c2
-rw-r--r--src/tests/test-core.c4
-rw-r--r--src/vpn/nm-vpn-connection.c4
16 files changed, 135 insertions, 131 deletions
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
index c6ecb2e8..36d00328 100644
--- a/src/devices/nm-device-bond.c
+++ b/src/devices/nm-device-bond.c
@@ -214,7 +214,7 @@ apply_bonding_config (NMDeviceBond *self)
 	 *
 	 * arp_interval conflicts miimon > 0
 	 * arp_interval conflicts [ alb, tlb ]
-	 * arp_validate needs [ active-backup ]
+	 * arp_validate does not work with [ BOND_MODE_8023AD, BOND_MODE_TLB, BOND_MODE_ALB ]
 	 * downdelay needs miimon
 	 * updelay needs miimon
 	 * primary needs [ active-backup, tlb, alb ]
@@ -266,15 +266,8 @@ apply_bonding_config (NMDeviceBond *self)
 		 */
 	}
 
-	/* ARP validate: value > 0 only valid in active-backup mode */
 	value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_VALIDATE);
-	if (   value
-	    && !nm_streq (value, "0")
-	    && !nm_streq (value, "none")
-	    && mode == NM_BOND_MODE_ACTIVEBACKUP)
-		set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_ARP_VALIDATE, value);
-	else
-		set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_ARP_VALIDATE, "0");
+	set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_ARP_VALIDATE, value ?: "0");
 
 	/* Primary */
 	value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index 6b80c4ed..86e50c52 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -1242,7 +1242,7 @@ dcb_state (NMDevice *device, gboolean timeout)
 			break;
 		}
 		_LOGD (LOGD_DCB, "dcb_state() preconfig down falling through");
-		/* fall through */
+		/* fall-through */
 	case DCB_WAIT_CARRIER_PRECONFIG_UP:
 		if (timeout || carrier) {
 			_LOGD (LOGD_DCB, "dcb_state() preconfig up configuring DCB");
@@ -1266,7 +1266,7 @@ dcb_state (NMDevice *device, gboolean timeout)
 			break;
 		}
 		_LOGD (LOGD_DCB, "dcb_state() postconfig down falling through");
-		/* fall through */
+		/* fall-through */
 	case DCB_WAIT_CARRIER_POSTCONFIG_UP:
 		if (timeout || carrier) {
 			_LOGD (LOGD_DCB, "dcb_state() postconfig up starting IP");
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 3bbc9757..72ec29a1 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -8005,7 +8005,7 @@ dhcp4_state_changed (NMDhcpClient *client,
 		/* Ignore expiry before we even have a lease (NAK, old lease, etc) */
 		if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF)
 			break;
-		/* fall through */
+		/* fall-through */
 	case NM_DHCP_STATE_DONE:
 	case NM_DHCP_STATE_FAIL:
 	case NM_DHCP_STATE_TERMINATED:
@@ -8812,7 +8812,7 @@ dhcp6_state_changed (NMDhcpClient *client,
 		 */
 		if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF)
 			break;
-		/* fall through */
+		/* fall-through */
 	case NM_DHCP_STATE_DONE:
 	case NM_DHCP_STATE_FAIL:
 		dhcp6_fail (self, state);
@@ -13858,7 +13858,7 @@ device_ipx_changed (NMPlatform *platform,
 			                                           (gpointer) nmp_object_ref (NMP_OBJECT_UP_CAST (addr)));
 		}
 
-		/* fall through */
+		/* fall-through */
 	case NMP_OBJECT_TYPE_IP6_ROUTE:
 		if (!priv->queued_ip_config_id_6) {
 			priv->queued_ip_config_id_6 = g_idle_add (queued_ip6_config_change, self);
diff --git a/src/devices/ovs/nm-device-ovs-port.c b/src/devices/ovs/nm-device-ovs-port.c
index 0955e8a9..e0216377 100644
--- a/src/devices/ovs/nm-device-ovs-port.c
+++ b/src/devices/ovs/nm-device-ovs-port.c
@@ -86,6 +86,7 @@ add_iface_cb (GError *error, gpointer user_data)
 static gboolean
 enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure)
 {
+	NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT (device);
 	NMActiveConnection *ac_port = NULL;
 	NMActiveConnection *ac_bridge = NULL;
 	NMDevice *bridge_device;
@@ -95,10 +96,18 @@ enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection, gboo
 
 	ac_port = NM_ACTIVE_CONNECTION (nm_device_get_act_request (device));
 	ac_bridge = nm_active_connection_get_master (ac_port);
-	if (!ac_bridge)
-		ac_bridge = ac_port;
+	if (!ac_bridge) {
+		_LOGW (LOGD_DEVICE, "can't enslave %s: bridge active-connection not found",
+		       nm_device_get_iface (slave));
+		return FALSE;
+	}
 
 	bridge_device = nm_active_connection_get_device (ac_bridge);
+	if (!bridge_device) {
+		_LOGW (LOGD_DEVICE, "can't enslave %s: bridge device not found",
+		       nm_device_get_iface (slave));
+		return FALSE;
+	}
 
 	nm_ovsdb_add_interface (nm_ovsdb_get (),
 	                        nm_active_connection_get_applied_connection (ac_bridge),
diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c
index a1ae8671..947aa4c8 100644
--- a/src/devices/wwan/nm-modem-broadband.c
+++ b/src/devices/wwan/nm-modem-broadband.c
@@ -548,7 +548,7 @@ connect_context_step (NMModemBroadband *self)
 	switch (ctx->step) {
 	case CONNECT_STEP_FIRST:
 		ctx->step++;
-		/* fall through */
+		/* fall-through */
 
 	case CONNECT_STEP_WAIT_FOR_SIM:
 		if (MODEM_CAPS_3GPP (ctx->caps) && !self->_priv.sim_iface) {
@@ -556,7 +556,7 @@ connect_context_step (NMModemBroadband *self)
 			break;
 		}
 		ctx->step++;
-		/* fall through */
+		/* fall-through */
 
 	case CONNECT_STEP_UNLOCK:
 		if (   MODEM_CAPS_3GPP (ctx->caps)
@@ -577,7 +577,7 @@ connect_context_step (NMModemBroadband *self)
 			break;
 		}
 		ctx->step++;
-		/* fall through */
+		/* fall-through */
 	case CONNECT_STEP_WAIT_FOR_READY: {
 		GError *error = NULL;
 
@@ -605,7 +605,7 @@ connect_context_step (NMModemBroadband *self)
 
 		ctx->step++;
 	}
-		/* fall through */
+		/* fall-through */
 	case CONNECT_STEP_CONNECT:
 		if (!ctx->connect_properties)
 			break;
@@ -639,7 +639,7 @@ connect_context_step (NMModemBroadband *self)
 		}
 
 		ctx->step++;
-		/* fall through */
+		/* fall-through */
 
 	case CONNECT_STEP_LAST:
 		if (self->_priv.ipv4_config || self->_priv.ipv6_config)
diff --git a/src/dhcp/nm-dhcp-nettools.c b/src/dhcp/nm-dhcp-nettools.c
index 45ff46f5..622251a3 100644
--- a/src/dhcp/nm-dhcp-nettools.c
+++ b/src/dhcp/nm-dhcp-nettools.c
@@ -1073,6 +1073,7 @@ dhcp4_event_cb (GIOChannel *source,
 		 * a predefined number of times (possibly infinite).
 		 */
 		_LOGE ("error %d dispatching events", r);
+		priv->event_id = 0;
 		nm_dhcp_client_set_state (NM_DHCP_CLIENT (self), NM_DHCP_STATE_FAIL, NULL, NULL);
 		return G_SOURCE_REMOVE;
 	}
diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c
index c7ca0b47..d731e7bf 100644
--- a/src/dns/nm-dns-manager.c
+++ b/src/dns/nm-dns-manager.c
@@ -1803,7 +1803,7 @@ _check_resconf_immutable (NMDnsManagerResolvConfManager rc_manager)
 	case NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN:
 	case NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE:
 		nm_assert_not_reached ();
-		/* fall through */
+		/* fall-through */
 	case NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED:
 		return NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED;
 	default:
@@ -1823,7 +1823,7 @@ _check_resconf_immutable (NMDnsManagerResolvConfManager rc_manager)
 			case NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED:
 			case NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE:
 				nm_assert_not_reached ();
-				/* fall through */
+				/* fall-through */
 			case NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE:
 			case NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF:
 			case NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG:
diff --git a/src/nm-config.c b/src/nm-config.c
index a0995cf9..4ea97657 100644
--- a/src/nm-config.c
+++ b/src/nm-config.c
@@ -1355,7 +1355,7 @@ _string_append_val (GString *str, const char *value)
 		case '#':
 		case ':':
 			g_string_append_c (str, '+');
-			/* fall through */
+			/* fall-through */
 		default:
 			g_string_append_c (str, *value);
 		}
@@ -2298,6 +2298,8 @@ _config_device_state_data_new (int ifindex, GKeyFile *kf)
 	return device_state;
 }
 
+#define DEVICE_STATE_FILENAME_LEN_MAX 60
+
 /**
  * nm_config_device_state_load:
  * @ifindex: the ifindex for which the state is to load
@@ -2309,7 +2311,7 @@ NMConfigDeviceStateData *
 nm_config_device_state_load (int ifindex)
 {
 	NMConfigDeviceStateData *device_state;
-	char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR) + 60];
+	char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/") + DEVICE_STATE_FILENAME_LEN_MAX + 1];
 	gs_unref_keyfile GKeyFile *kf = NULL;
 	const char *nm_owned_str;
 
@@ -2393,7 +2395,7 @@ nm_config_device_state_write (int ifindex,
                               const char *next_server,
                               const char *root_path)
 {
-	char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR) + 60];
+	char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/") + DEVICE_STATE_FILENAME_LEN_MAX + 1];
 	GError *local = NULL;
 	gs_unref_keyfile GKeyFile *kf = NULL;
 
@@ -2476,35 +2478,43 @@ nm_config_device_state_write (int ifindex,
 }
 
 void
-nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes)
+nm_config_device_state_prune_stale (GHashTable *preserve_ifindexes,
+                                    NMPlatform *preserve_in_platform)
 {
 	GDir *dir;
 	const char *fn;
-	int ifindex;
-	gsize fn_len;
-	char buf[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/") + 30 + 3] = NM_CONFIG_DEVICE_STATE_DIR"/";
+	char buf[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/") + DEVICE_STATE_FILENAME_LEN_MAX + 1] = NM_CONFIG_DEVICE_STATE_DIR"/";
 	char *buf_p = &buf[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/")];
 
-	g_return_if_fail (seen_ifindexes);
-
 	dir = g_dir_open (NM_CONFIG_DEVICE_STATE_DIR, 0, NULL);
 	if (!dir)
 		return;
 
 	while ((fn = g_dir_read_name (dir))) {
+		int ifindex;
+		gsize fn_len;
+
 		ifindex = _device_state_parse_filename (fn);
 		if (ifindex <= 0)
 			continue;
-		if (g_hash_table_contains (seen_ifindexes, GINT_TO_POINTER (ifindex)))
+
+		if (   preserve_ifindexes
+		    && g_hash_table_contains (preserve_ifindexes, GINT_TO_POINTER (ifindex)))
+			continue;
+
+		if (   preserve_in_platform
+		    && nm_platform_link_get (preserve_in_platform, ifindex))
 			continue;
 
-		fn_len = strlen (fn) + 1;
+		fn_len = strlen (fn);
+		nm_assert (fn_len > 0);
 		nm_assert (&buf_p[fn_len] < &buf[G_N_ELEMENTS (buf)]);
-		memcpy (buf_p, fn, fn_len);
+		memcpy (buf_p, fn, fn_len + 1u);
 		nm_assert (({
 		                char bb[30];
-		                nm_sprintf_buf (bb, "%d", ifindex);
-		                nm_streq0 (bb, buf_p);
+
+		                nm_streq0 (nm_sprintf_buf (bb, "%d", ifindex),
+		                           buf_p);
 		           }));
 		_LOGT ("device-state: prune #%d (%s)", ifindex, buf);
 		(void) unlink (buf);
diff --git a/src/nm-config.h b/src/nm-config.h
index d9460ebb..b4478ceb 100644
--- a/src/nm-config.h
+++ b/src/nm-config.h
@@ -258,7 +258,8 @@ gboolean nm_config_device_state_write (int ifindex,
                                        const char *next_server,
                                        const char *root_path);
 
-void nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes);
+void nm_config_device_state_prune_stale (GHashTable *preserve_ifindexes,
+                                         NMPlatform *preserve_in_platform);
 
 const GHashTable *nm_config_device_state_get_all (NMConfig *self);
 const NMConfigDeviceStateData *nm_config_device_state_get (NMConfig *self,
diff --git a/src/nm-logging.c b/src/nm-logging.c
index 34dd2797..9221a6c8 100644
--- a/src/nm-logging.c
+++ b/src/nm-logging.c
@@ -729,6 +729,11 @@ _nm_log_impl (const char *file,
 			struct iovec *iov = iov_data;
 			char *iov_free_data[5];
 			char **iov_free = iov_free_data;
+			const LogDesc *diter;
+			NMLogDomain dom_all;
+			char s_log_domains_buf[NM_STRLEN ("NM_LOG_DOMAINS=") + sizeof (_all_logging_domains_to_str)];
+			char *s_log_domains;
+			gsize l_log_domains;
 
 			now = nm_utils_get_monotonic_timestamp_ns ();
 			boottime = nm_utils_monotonic_timestamp_as_boottime (now, 1);
@@ -737,25 +742,23 @@ _nm_log_impl (const char *file,
 			_iovec_set_format (iov++, iov_free++, "MESSAGE="MESSAGE_FMT, MESSAGE_ARG (g->prefix, tv, msg));
 			_iovec_set_string (iov++, syslog_identifier_full (g->syslog_identifier));
 			_iovec_set_format_a (iov++, 30, "SYSLOG_PID=%ld", (long) getpid ());
-			{
-				const LogDesc *diter;
-				NMLogDomain dom_all = domain;
-				char s_log_domains_buf[NM_STRLEN ("NM_LOG_DOMAINS=") + sizeof (_all_logging_domains_to_str)];
-				char *s_log_domains = s_log_domains_buf;
-				gsize l_log_domains = sizeof (s_log_domains_buf);
-
-				nm_utils_strbuf_append_str (&s_log_domains, &l_log_domains, "NM_LOG_DOMAINS=");
-				for (diter = &domain_desc[0]; dom_all != 0 && diter->name; diter++) {
-					if (!NM_FLAGS_ANY (dom_all, diter->num))
-						continue;
-					if (dom_all != domain)
-						nm_utils_strbuf_append_c (&s_log_domains, &l_log_domains, ',');
-					nm_utils_strbuf_append_str (&s_log_domains, &l_log_domains, diter->name);
-					dom_all &= ~diter->num;
-				}
-				nm_assert (l_log_domains > 0);
-				_iovec_set (iov++, s_log_domains_buf, s_log_domains - s_log_domains_buf);
+
+			dom_all = domain;
+			s_log_domains = s_log_domains_buf;
+			l_log_domains = sizeof (s_log_domains_buf);
+
+			nm_utils_strbuf_append_str (&s_log_domains, &l_log_domains, "NM_LOG_DOMAINS=");
+			for (diter = &domain_desc[0]; dom_all != 0 && diter->name; diter++) {
+				if (!NM_FLAGS_ANY (dom_all, diter->num))
+					continue;
+				if (dom_all != domain)
+					nm_utils_strbuf_append_c (&s_log_domains, &l_log_domains, ',');
+				nm_utils_strbuf_append_str (&s_log_domains, &l_log_domains, diter->name);
+				dom_all &= ~diter->num;
 			}
+			nm_assert (l_log_domains > 0);
+			_iovec_set (iov++, s_log_domains_buf, s_log_domains - s_log_domains_buf);
+
 			G_STATIC_ASSERT_EXPR (LOG_FAC (LOG_DAEMON) == 3);
 			_iovec_set_string_literal (iov++, "SYSLOG_FACILITY=3");
 			_iovec_set_format_str_a (iov++, 15, "NM_LOG_LEVEL=%s", level_desc[level].name);
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 6d3a5ddb..d7b2211e 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -50,6 +50,8 @@
 #include "nm-dispatcher.h"
 #include "NetworkManagerUtils.h"
 
+#define DEVICE_STATE_PRUNE_RATELIMIT_MAX 100u
+
 /*****************************************************************************/
 
 typedef struct {
@@ -168,9 +170,6 @@ typedef struct {
 
 	NMSettings *settings;
 
-	CList connection_changed_on_idle_lst;
-	guint connection_changed_on_idle_id;
-
 	RadioState radio_states[RFKILL_TYPE_MAX];
 	NMVpnManager *vpn_manager;
 
@@ -194,6 +193,8 @@ typedef struct {
 
 	NMConnectivityState connectivity_state;
 
+	guint8 device_state_prune_ratelimit_count;
+
 	bool startup:1;
 	bool devices_inited:1;
 
@@ -1517,8 +1518,22 @@ manager_device_state_changed (NMDevice *device,
 	if (NM_IN_SET (new_state,
 	               NM_DEVICE_STATE_UNMANAGED,
 	               NM_DEVICE_STATE_DISCONNECTED,
-	               NM_DEVICE_STATE_ACTIVATED))
-		nm_manager_write_device_state (self, device);
+	               NM_DEVICE_STATE_ACTIVATED)) {
+		nm_manager_write_device_state (self, device, NULL);
+
+		G_STATIC_ASSERT_EXPR (DEVICE_STATE_PRUNE_RATELIMIT_MAX < G_MAXUINT8);
+		if (priv->device_state_prune_ratelimit_count++ > DEVICE_STATE_PRUNE_RATELIMIT_MAX) {
+			/* We write the device state to /run. The state files are named after the
+			 * ifindex (which is assumed to be unique and not repeat -- in practice
+			 * it may repeat). So from time to time, we prune device state files
+			 * for interfaces that no longer exist.
+			 *
+			 * Otherwise, the files might pile up if you create (and destroy) a large
+			 * number of software devices. */
+			priv->device_state_prune_ratelimit_count = 0;
+			nm_config_device_state_prune_stale (NULL, priv->platform);
+		}
+	}
 
 	if (NM_IN_SET (new_state,
 	               NM_DEVICE_STATE_UNAVAILABLE,
@@ -2098,7 +2113,6 @@ static void
 connection_changed (NMManager *self,
                     NMSettingsConnection *sett_conn)
 {
-	NMManagerPrivate *priv;
 	NMConnection *connection;
 	NMDevice *device;
 
@@ -2106,11 +2120,6 @@ connection_changed (NMManager *self,
 	                  NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE))
 		return;
 
-	priv = NM_MANAGER_GET_PRIVATE (self);
-
-	if (!nm_settings_has_connection (priv->settings, sett_conn))
-		return;
-
 	connection = nm_settings_connection_get_connection (sett_conn);
 
 	if (!nm_connection_is_virtual (connection))
@@ -2126,46 +2135,12 @@ connection_changed (NMManager *self,
 	retry_connections_for_parent_device (self, device);
 }
 
-static gboolean
-connection_changed_on_idle_cb (gpointer user_data)
-{
-	NMManager *self = user_data;
-	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
-	NMCListElem *elem;
-
-	priv->connection_changed_on_idle_id = 0;
-
-	while ((elem = c_list_first_entry (&priv->connection_changed_on_idle_lst, NMCListElem, lst))) {
-		gs_unref_object NMSettingsConnection *sett_conn = NULL;
-
-		sett_conn = nm_c_list_elem_free_steal (elem);
-		connection_changed (self, sett_conn);
-	}
-
-	return G_SOURCE_REMOVE;
-}
-
-static void
-connection_changed_on_idle (NMManager *self,
-                            NMSettingsConnection *sett_conn)
-{
-	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
-
-	if (priv->connection_changed_on_idle_id == 0)
-		priv->connection_changed_on_idle_id = g_idle_add (connection_changed_on_idle_cb, self);
-
-	if (!nm_c_list_elem_find_first_ptr (&priv->connection_changed_on_idle_lst, sett_conn)) {
-		c_list_link_tail (&priv->connection_changed_on_idle_lst,
-		                  &nm_c_list_elem_new_stale (g_object_ref (sett_conn))->lst);
-	}
-}
-
 static void
 connection_added_cb (NMSettings *settings,
                      NMSettingsConnection *sett_conn,
                      NMManager *self)
 {
-	connection_changed_on_idle (self, sett_conn);
+	connection_changed (self, sett_conn);
 }
 
 static void
@@ -2174,7 +2149,7 @@ connection_updated_cb (NMSettings *settings,
                        guint update_reason_u,
                        NMManager *self)
 {
-	connection_changed_on_idle (self, sett_conn);
+	connection_changed (self, sett_conn);
 }
 
 /*****************************************************************************/
@@ -3377,7 +3352,7 @@ add:
 			_LOGI (LOGD_PLATFORM, "(%s): '%s' plugin not available; creating generic device",
 			       plink->name, nm_link_type_to_string (plink->type));
 			nm_plugin_missing = TRUE;
-			/* fall through */
+			/* fall-through */
 		default:
 			device = nm_device_generic_new (plink, nm_plugin_missing);
 			break;
@@ -6557,7 +6532,7 @@ start_factory (NMDeviceFactory *factory, gpointer user_data)
 }
 
 gboolean
-nm_manager_write_device_state (NMManager *self, NMDevice *device)
+nm_manager_write_device_state (NMManager *self, NMDevice *device, int *out_ifindex)
 {
 	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
 	int ifindex;
@@ -6573,6 +6548,8 @@ nm_manager_write_device_state (NMManager *self, NMDevice *device)
 	const char *next_server = NULL;
 	const char *root_path = NULL;
 
+	NM_SET_OUT (out_ifindex, 0);
+
 	ifindex = nm_device_get_ip_ifindex (device);
 	if (ifindex <= 0)
 		return FALSE;
@@ -6613,34 +6590,40 @@ nm_manager_write_device_state (NMManager *self, NMDevice *device)
 		next_server = nm_dhcp4_config_get_option (dhcp4_config, "next_server");
 	}
 
-	return nm_config_device_state_write (ifindex,
-	                                     managed_type,
-	                                     perm_hw_addr_fake,
-	                                     uuid,
-	                                     nm_owned,
-	                                     route_metric_default_aspired,
-	                                     route_metric_default_effective,
-	                                     next_server,
-	                                     root_path);
+	if (!nm_config_device_state_write (ifindex,
+	                                   managed_type,
+	                                   perm_hw_addr_fake,
+	                                   uuid,
+	                                   nm_owned,
+	                                   route_metric_default_aspired,
+	                                   route_metric_default_effective,
+	                                   next_server,
+	                                   root_path))
+		return FALSE;
+
+	NM_SET_OUT (out_ifindex, ifindex);
+	return TRUE;
 }
 
 void
 nm_manager_write_device_state_all (NMManager *self)
 {
 	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
-	gs_unref_hashtable GHashTable *seen_ifindexes = NULL;
+	gs_unref_hashtable GHashTable *preserve_ifindexes = NULL;
 	NMDevice *device;
 
-	seen_ifindexes = g_hash_table_new (nm_direct_hash, NULL);
+	preserve_ifindexes = g_hash_table_new (nm_direct_hash, NULL);
 
 	c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) {
-		if (nm_manager_write_device_state (self, device)) {
-			g_hash_table_add (seen_ifindexes,
-			                  GINT_TO_POINTER (nm_device_get_ip_ifindex (device)));
+		int ifindex;
+
+		if (nm_manager_write_device_state (self, device, &ifindex)) {
+			g_hash_table_add (preserve_ifindexes,
+			                  GINT_TO_POINTER (ifindex));
 		}
 	}
 
-	nm_config_device_state_prune_unseen (seen_ifindexes);
+	nm_config_device_state_prune_stale (preserve_ifindexes, NULL);
 }
 
 static gboolean
@@ -7511,7 +7494,6 @@ nm_manager_init (NMManager *self)
 	c_list_init (&priv->active_connections_lst_head);
 	c_list_init (&priv->async_op_lst_head);
 	c_list_init (&priv->delete_volatile_connection_lst_head);
-	c_list_init (&priv->connection_changed_on_idle_lst);
 
 	priv->platform = g_object_ref (NM_PLATFORM_GET);
 
@@ -7817,9 +7799,6 @@ dispose (GObject *object)
 		g_clear_object (&priv->policy);
 	}
 
-	nm_clear_g_source (&priv->connection_changed_on_idle_id);
-	nm_c_list_elem_free_all (&priv->connection_changed_on_idle_lst, g_object_unref);
-
 	if (priv->settings) {
 		g_signal_handlers_disconnect_by_func (priv->settings, settings_startup_complete_changed, self);
 		g_signal_handlers_disconnect_by_func (priv->settings, system_unmanaged_devices_changed_cb, self);
diff --git a/src/nm-manager.h b/src/nm-manager.h
index ad06e318..5873abd2 100644
--- a/src/nm-manager.h
+++ b/src/nm-manager.h
@@ -103,7 +103,7 @@ NMSettingsConnection **nm_manager_get_activatable_connections (NMManager *manage
                                                                guint *out_len);
 
 void          nm_manager_write_device_state_all (NMManager *manager);
-gboolean      nm_manager_write_device_state (NMManager *manager, NMDevice *device);
+gboolean      nm_manager_write_device_state (NMManager *manager, NMDevice *device, int *out_ifindex);
 
 /* Device handling */
 
diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h
index d52cc132..0c0796c3 100644
--- a/src/platform/nmp-object.h
+++ b/src/platform/nmp-object.h
@@ -496,10 +496,16 @@ _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX (NMPObjectType obj_type)
 	case NMP_OBJECT_TYPE_LNK_VXLAN:
 	case NMP_OBJECT_TYPE_LNK_WIREGUARD:
 		return TRUE;
-	default:
-		nm_assert (nmp_class_from_type (obj_type));
+
+	case NMP_OBJECT_TYPE_ROUTING_RULE:
 		return FALSE;
+
+	case NMP_OBJECT_TYPE_UNKNOWN:
+	case __NMP_OBJECT_TYPE_LAST:
+		break;
 	}
+	nm_assert_not_reached ();
+	return FALSE;
 }
 
 #define NMP_OBJECT_CAST_OBJECT(obj) \
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
index f328cc8f..90a1a2b8 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
@@ -1923,6 +1923,8 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
 	svSetValueStr (ifcfg, "BRIDGE", NULL);
 	svSetValueStr (ifcfg, "TEAM_MASTER_UUID", NULL);
 	svSetValueStr (ifcfg, "TEAM_MASTER", NULL);
+	svSetValueStr (ifcfg, "OVS_PORT_UUID", NULL);
+	svSetValueStr (ifcfg, "OVS_PORT", NULL);
 
 	master = nm_setting_connection_get_master (s_con);
 	if (master) {
diff --git a/src/tests/test-core.c b/src/tests/test-core.c
index f55f3dff..590f7c36 100644
--- a/src/tests/test-core.c
+++ b/src/tests/test-core.c
@@ -1536,7 +1536,7 @@ test_nm_utils_strbuf_append (void)
 					_strbuf_append_c (&t_buf, &t_len, str[0]);
 					break;
 				}
-				/* fall through */
+				/* fall-through */
 			case 1:
 				_strbuf_append_str (&t_buf, &t_len, str);
 				break;
@@ -1545,7 +1545,7 @@ test_nm_utils_strbuf_append (void)
 					_strbuf_append (&t_buf, &t_len, "%c", str[0]);
 					break;
 				}
-				/* fall through */
+				/* fall-through */
 			case 3:
 				_strbuf_append (&t_buf, &t_len, "%s", str);
 				break;
diff --git a/src/vpn/nm-vpn-connection.c b/src/vpn/nm-vpn-connection.c
index 6a25ddda..974009f9 100644
--- a/src/vpn/nm-vpn-connection.c
+++ b/src/vpn/nm-vpn-connection.c
@@ -619,7 +619,7 @@ _set_vpn_state (NMVpnConnection *self,
 		}
 
 		vpn_cleanup (self, parent_dev);
-		/* fall through */
+		/* fall-through */
 	default:
 		priv->secrets_idx = SECRETS_REQ_SYSTEM;
 		break;
@@ -1577,7 +1577,7 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
 			switch (g_variant_n_children (v)) {
 			case 5:
 				g_variant_get_child (v, 4, "u", &route.pref_src);
-				/* fall through */
+				/* fall-through */
 			case 4:
 				g_variant_get_child (v, 0, "u", &route.network);
 				g_variant_get_child (v, 1, "u", &plen);