Blame SOURCES/1014-settings-fix-wait-device-timeout-rh1853348.patch

724c96
From 707e63e684e3cbd3dff986a26ca725329c5e70f5 Mon Sep 17 00:00:00 2001
724c96
From: Beniamino Galvani <bgalvani@redhat.com>
724c96
Date: Wed, 5 Aug 2020 13:26:34 +0200
724c96
Subject: [PATCH 1/7] initrd: disable STP on bridges
724c96
724c96
NM enables by default STP on bridges, which causes a forwarding delay
724c96
of 15 seconds on boot. Disable it.
724c96
724c96
(cherry picked from commit 0a006c04121a13221de585d3f778c5341f36b504)
724c96
(cherry picked from commit e2830af77a981fef5b7ea7e54dc13de17231fee9)
724c96
---
724c96
 src/initrd/nmi-cmdline-reader.c        | 12 +++++++++---
724c96
 src/initrd/tests/test-cmdline-reader.c |  1 +
724c96
 2 files changed, 10 insertions(+), 3 deletions(-)
724c96
724c96
diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c
724c96
index 17f9e1dfd2a9..8ba6dbb827b6 100644
724c96
--- a/src/initrd/nmi-cmdline-reader.c
724c96
+++ b/src/initrd/nmi-cmdline-reader.c
724c96
@@ -584,7 +584,6 @@ reader_parse_master (Reader *reader,
724c96
 {
724c96
 	NMConnection *connection;
724c96
 	NMSettingConnection *s_con;
724c96
-	NMSettingBond *s_bond;
724c96
 	gs_free char *master_to_free = NULL;
724c96
 	const char *master;
724c96
 	char *slaves;
724c96
@@ -603,8 +602,15 @@ reader_parse_master (Reader *reader,
724c96
 	s_con = nm_connection_get_setting_connection (connection);
724c96
 	master = nm_setting_connection_get_uuid (s_con);
724c96
 
724c96
-	if (nm_streq (type_name, NM_SETTING_BOND_SETTING_NAME)) {
724c96
-		s_bond = (NMSettingBond *)nm_connection_get_setting_by_name (connection, type_name);
724c96
+	if (nm_streq (type_name, NM_SETTING_BRIDGE_SETTING_NAME)) {
724c96
+		NMSettingBridge *s_bridge = nm_connection_get_setting_bridge (connection);
724c96
+
724c96
+		/* Avoid the forwarding delay */
724c96
+		g_object_set (s_bridge,
724c96
+		              NM_SETTING_BRIDGE_STP, FALSE,
724c96
+		              NULL);
724c96
+	} else if (nm_streq (type_name, NM_SETTING_BOND_SETTING_NAME)) {
724c96
+		NMSettingBond *s_bond = nm_connection_get_setting_bond (connection);
724c96
 
724c96
 		opts = get_word (&argument, ':');
724c96
 		while (opts && *opts) {
724c96
diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c
724c96
index 04594c48bee6..074654d347d8 100644
724c96
--- a/src/initrd/tests/test-cmdline-reader.c
724c96
+++ b/src/initrd/tests/test-cmdline-reader.c
724c96
@@ -774,6 +774,7 @@ test_bridge (void)
724c96
 
724c96
 	s_bridge = nm_connection_get_setting_bridge (connection);
724c96
 	g_assert (s_bridge);
724c96
+	g_assert_cmpint (nm_setting_bridge_get_stp (s_bridge), ==, FALSE);
724c96
 
724c96
 	connection = g_hash_table_lookup (connections, "eth0");
724c96
 	g_assert (connection);
724c96
-- 
724c96
2.26.2
724c96
724c96
724c96
From 43d1669601cc106e354bbbb1fc94240a0275c9e9 Mon Sep 17 00:00:00 2001
724c96
From: Beniamino Galvani <bgalvani@redhat.com>
724c96
Date: Wed, 5 Aug 2020 16:57:41 +0200
724c96
Subject: [PATCH 2/7] initrd: wait for bootdev or all devices if rd.neednet=1
724c96
724c96
The network-legacy dracut module waits for all ethernet devices if the
724c96
command line contains rd.neednet=1. It also waits for the device
724c96
specified by 'bootdev='.
724c96
724c96
Do the same.
724c96
724c96
https://bugzilla.redhat.com/show_bug.cgi?id=1853348
724c96
(cherry picked from commit f114e16fddf854d72a8b08318359569cd83245e3)
724c96
(cherry picked from commit 98ccd2a10e89d6d251a519eb63d085b2f327bad8)
724c96
---
724c96
 src/initrd/nm-initrd-generator.h       |  2 +
724c96
 src/initrd/nmi-cmdline-reader.c        | 35 +++++++++++--
724c96
 src/initrd/tests/test-cmdline-reader.c | 70 ++++++++++++++++++++++++++
724c96
 3 files changed, 104 insertions(+), 3 deletions(-)
724c96
724c96
diff --git a/src/initrd/nm-initrd-generator.h b/src/initrd/nm-initrd-generator.h
724c96
index 9719992125ea..8e17f0455574 100644
724c96
--- a/src/initrd/nm-initrd-generator.h
724c96
+++ b/src/initrd/nm-initrd-generator.h
724c96
@@ -9,6 +9,8 @@
724c96
 #include "nm-connection.h"
724c96
 #include "nm-utils.h"
724c96
 
724c96
+#define NMI_WAIT_DEVICE_TIMEOUT_MS 60000
724c96
+
724c96
 static inline gboolean
724c96
 guess_ip_address_family (const char *str)
724c96
 {
724c96
diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c
724c96
index 8ba6dbb827b6..85be9f132eda 100644
724c96
--- a/src/initrd/nmi-cmdline-reader.c
724c96
+++ b/src/initrd/nmi-cmdline-reader.c
724c96
@@ -873,6 +873,30 @@ reader_add_nameservers (Reader *reader, GPtrArray *nameservers)
724c96
 	}
724c96
 }
724c96
 
724c96
+static void
724c96
+connection_set_needed (NMConnection *connection)
724c96
+{
724c96
+	NMSettingConnection *s_con;
724c96
+
724c96
+	s_con = nm_connection_get_setting_connection (connection);
724c96
+	if (!nm_streq0 (nm_setting_connection_get_connection_type (s_con),
724c96
+	                NM_SETTING_WIRED_SETTING_NAME))
724c96
+		return;
724c96
+
724c96
+	if (nm_str_is_empty (nm_setting_connection_get_interface_name (s_con)))
724c96
+		return;
724c96
+
724c96
+	g_object_set (s_con,
724c96
+	              NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT, NMI_WAIT_DEVICE_TIMEOUT_MS,
724c96
+	              NULL);
724c96
+}
724c96
+
724c96
+static void
724c96
+connection_set_needed_cb (gpointer key, gpointer value, gpointer user_data)
724c96
+{
724c96
+	connection_set_needed (value);
724c96
+}
724c96
+
724c96
 GHashTable *
724c96
 nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv, char **hostname)
724c96
 {
724c96
@@ -1007,11 +1031,16 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv, char **
724c96
 
724c96
 		connection = reader_get_connection (reader, bootdev, NULL, TRUE);
724c96
 		reader->bootdev_connection = connection;
724c96
+		connection_set_needed (connection);
724c96
 	}
724c96
 
724c96
-	if (neednet && g_hash_table_size (reader->hash) == 0) {
724c96
-		/* Make sure there's some connection. */
724c96
-		reader_get_default_connection (reader);
724c96
+	if (neednet) {
724c96
+		if (g_hash_table_size (reader->hash) == 0) {
724c96
+			/* Make sure there's some connection. */
724c96
+			reader_get_default_connection (reader);
724c96
+		}
724c96
+
724c96
+		g_hash_table_foreach (reader->hash, connection_set_needed_cb, NULL);
724c96
 	}
724c96
 
724c96
 	if (routes)
724c96
diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c
724c96
index 074654d347d8..7787cf5ea043 100644
724c96
--- a/src/initrd/tests/test-cmdline-reader.c
724c96
+++ b/src/initrd/tests/test-cmdline-reader.c
724c96
@@ -49,6 +49,7 @@ test_auto (void)
724c96
 	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Wired Connection");
724c96
 	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, 0);
724c96
 	g_assert_cmpint (nm_setting_connection_get_multi_connect (s_con), ==, NM_CONNECTION_MULTI_CONNECT_MULTIPLE);
724c96
+	g_assert_cmpint (nm_setting_connection_get_wait_device_timeout (s_con), ==, -1);
724c96
 
724c96
 	g_assert (nm_setting_connection_get_autoconnect (s_con));
724c96
 
724c96
@@ -190,6 +191,7 @@ test_if_ip4_manual (void)
724c96
 	                                       "ip=203.0.113.2::203.0.113.1:26:"
724c96
 	                                       "hostname1.example.com:eth4");
724c96
 	NMConnection *connection;
724c96
+	NMSettingConnection *s_con;
724c96
 	NMSettingIPConfig *s_ip4;
724c96
 	NMSettingIPConfig *s_ip6;
724c96
 	NMIPAddress *ip_addr;
724c96
@@ -205,6 +207,10 @@ test_if_ip4_manual (void)
724c96
 	nmtst_assert_connection_verifies_without_normalization (connection);
724c96
 	g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth3");
724c96
 
724c96
+	s_con = nm_connection_get_setting_connection (connection);
724c96
+	g_assert (s_con);
724c96
+	g_assert_cmpint (nm_setting_connection_get_wait_device_timeout (s_con), ==, -1);
724c96
+
724c96
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
724c96
 	g_assert (s_ip4);
724c96
 	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
724c96
@@ -294,6 +300,7 @@ test_multiple_merge (void)
724c96
 	const char *const*ARGV = NM_MAKE_STRV ("ip=192.0.2.2:::::eth0",
724c96
 	                                       "ip=[2001:db8::2]:::::eth0");
724c96
 	NMConnection *connection;
724c96
+	NMSettingConnection *s_con;
724c96
 	NMSettingWired *s_wired;
724c96
 	NMSettingIPConfig *s_ip4;
724c96
 	NMSettingIPConfig *s_ip6;
724c96
@@ -310,6 +317,10 @@ test_multiple_merge (void)
724c96
 	nmtst_assert_connection_verifies_without_normalization (connection);
724c96
 	g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth0");
724c96
 
724c96
+	s_con = nm_connection_get_setting_connection (connection);
724c96
+	g_assert (s_con);
724c96
+	g_assert_cmpint (nm_setting_connection_get_wait_device_timeout (s_con), ==, -1);
724c96
+
724c96
 	s_wired = nm_connection_get_setting_wired (connection);
724c96
 	g_assert (s_wired);
724c96
 
724c96
@@ -341,6 +352,7 @@ test_multiple_bootdev (void)
724c96
 	                                       "ip=eth4:dhcp",
724c96
 	                                       "bootdev=eth4");
724c96
 	NMConnection *connection;
724c96
+	NMSettingConnection *s_con;
724c96
 	NMSettingIPConfig *s_ip4;
724c96
 	NMSettingIPConfig *s_ip6;
724c96
 	gs_free char *hostname = NULL;
724c96
@@ -352,12 +364,18 @@ test_multiple_bootdev (void)
724c96
 
724c96
 	connection = g_hash_table_lookup (connections, "eth3");
724c96
 	g_assert (connection);
724c96
+	s_con = nm_connection_get_setting_connection (connection);
724c96
+	g_assert (s_con);
724c96
+	g_assert_cmpint (nm_setting_connection_get_wait_device_timeout (s_con), ==, -1);
724c96
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
724c96
 	g_assert (s_ip6);
724c96
 	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
724c96
 
724c96
 	connection = g_hash_table_lookup (connections, "eth4");
724c96
 	g_assert (connection);
724c96
+	s_con = nm_connection_get_setting_connection (connection);
724c96
+	g_assert (s_con);
724c96
+	g_assert_cmpint (nm_setting_connection_get_wait_device_timeout (s_con), ==, NMI_WAIT_DEVICE_TIMEOUT_MS);
724c96
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
724c96
 	g_assert (s_ip4);
724c96
 	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
724c96
@@ -388,6 +406,7 @@ test_bootdev (void)
724c96
 	g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
724c96
 	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "ens3");
724c96
 	g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "ens3");
724c96
+	g_assert_cmpint (nm_setting_connection_get_wait_device_timeout(s_con), ==, NMI_WAIT_DEVICE_TIMEOUT_MS);
724c96
 
724c96
 	connection = g_hash_table_lookup (connections, "vlan2");
724c96
 	g_assert (connection);
724c96
@@ -1255,6 +1274,56 @@ test_bootif_ip (void)
724c96
 	g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6));
724c96
 }
724c96
 
724c96
+static void
724c96
+test_neednet (void)
724c96
+{
724c96
+	gs_unref_hashtable GHashTable *connections = NULL;
724c96
+	const char *const*ARGV = NM_MAKE_STRV ("rd.neednet",
724c96
+	                                       "ip=eno1:dhcp",
724c96
+	                                       "ip=172.25.1.100::172.25.1.1:24::eno2",
724c96
+	                                       "bridge=br0:eno3");
724c96
+	NMConnection *connection;
724c96
+	NMSettingConnection *s_con;
724c96
+	gs_free char *hostname = NULL;
724c96
+
724c96
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
724c96
+	g_assert (connections);
724c96
+	g_assert_cmpint (g_hash_table_size (connections), ==, 4);
724c96
+	g_assert_cmpstr (hostname, ==, NULL);
724c96
+
724c96
+	connection = g_hash_table_lookup (connections, "eno1");
724c96
+	g_assert (connection);
724c96
+	nmtst_assert_connection_verifies_without_normalization (connection);
724c96
+	s_con = nm_connection_get_setting_connection (connection);
724c96
+	g_assert (s_con);
724c96
+	g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "eno1");
724c96
+	g_assert_cmpint (nm_setting_connection_get_wait_device_timeout (s_con), ==, NMI_WAIT_DEVICE_TIMEOUT_MS);
724c96
+
724c96
+	connection = g_hash_table_lookup (connections, "eno2");
724c96
+	g_assert (connection);
724c96
+	nmtst_assert_connection_verifies_without_normalization (connection);
724c96
+	s_con = nm_connection_get_setting_connection (connection);
724c96
+	g_assert (s_con);
724c96
+	g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "eno2");
724c96
+	g_assert_cmpint (nm_setting_connection_get_wait_device_timeout (s_con), ==, NMI_WAIT_DEVICE_TIMEOUT_MS);
724c96
+
724c96
+	connection = g_hash_table_lookup (connections, "eno3");
724c96
+	g_assert (connection);
724c96
+	nmtst_assert_connection_verifies_without_normalization (connection);
724c96
+	s_con = nm_connection_get_setting_connection (connection);
724c96
+	g_assert (s_con);
724c96
+	g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "eno3");
724c96
+	g_assert_cmpint (nm_setting_connection_get_wait_device_timeout (s_con), ==, NMI_WAIT_DEVICE_TIMEOUT_MS);
724c96
+
724c96
+	connection = g_hash_table_lookup (connections, "br0");
724c96
+	g_assert (connection);
724c96
+	nmtst_assert_connection_verifies_without_normalization (connection);
724c96
+	s_con = nm_connection_get_setting_connection (connection);
724c96
+	g_assert (s_con);
724c96
+	g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "br0");
724c96
+	g_assert_cmpint (nm_setting_connection_get_wait_device_timeout (s_con), ==, -1);
724c96
+}
724c96
+
724c96
 static void
724c96
 test_bootif_no_ip (void)
724c96
 {
724c96
@@ -1451,6 +1520,7 @@ int main (int argc, char **argv)
724c96
 	g_test_add_func ("/initrd/cmdline/bootif/no_ip", test_bootif_no_ip);
724c96
 	g_test_add_func ("/initrd/cmdline/bootif/hwtype", test_bootif_hwtype);
724c96
 	g_test_add_func ("/initrd/cmdline/bootif/off", test_bootif_off);
724c96
+	g_test_add_func ("/initrd/cmdline/neednet", test_neednet);
724c96
 
724c96
 	return g_test_run ();
724c96
 }
724c96
-- 
724c96
2.26.2
724c96
724c96
724c96
From 38da5dabaccc377695e6cc4d3621cdf0f12b28e1 Mon Sep 17 00:00:00 2001
724c96
From: Thomas Haller <thaller@redhat.com>
724c96
Date: Tue, 11 Aug 2020 15:32:46 +0200
724c96
Subject: [PATCH 3/7] settings: let NMSettings reference NMManager
724c96
724c96
NMSettings needs access to the list of all devices, which is tracked
724c96
by NMManager. Of course, this ties NMSettings and NMManager closer
724c96
together. Note that NMManager already owns a reference to NMSettings,
724c96
so they are in fact related.
724c96
724c96
The alternatives of just letting NMSettings reference NMManager (and
724c96
vice versa) would be more complicated, and likely not help to simplify
724c96
the code (on the contrary).
724c96
724c96
(cherry picked from commit d27a6055b9094163356ae2c650c566307df9a93c)
724c96
(cherry picked from commit 1745b4e0c0895df61cd4117b304dfa4e9a1d8c53)
724c96
---
724c96
 src/nm-manager.c           |  2 +-
724c96
 src/settings/nm-settings.c | 44 ++++++++++++++++++++++++++++++++++++--
724c96
 src/settings/nm-settings.h |  3 ++-
724c96
 3 files changed, 45 insertions(+), 4 deletions(-)
724c96
724c96
diff --git a/src/nm-manager.c b/src/nm-manager.c
724c96
index d687fcd7f219..6095f2687153 100644
724c96
--- a/src/nm-manager.c
724c96
+++ b/src/nm-manager.c
724c96
@@ -7455,7 +7455,7 @@ constructed (GObject *object)
724c96
 
724c96
 	G_OBJECT_CLASS (nm_manager_parent_class)->constructed (object);
724c96
 
724c96
-	priv->settings = nm_settings_new ();
724c96
+	priv->settings = nm_settings_new (self);
724c96
 
724c96
 	nm_dbus_object_export (NM_DBUS_OBJECT (priv->settings));
724c96
 
724c96
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
724c96
index 0a1e7b47d6c4..85c5e5e77f85 100644
724c96
--- a/src/settings/nm-settings.c
724c96
+++ b/src/settings/nm-settings.c
724c96
@@ -60,6 +60,7 @@
724c96
 #include "plugins/keyfile/nms-keyfile-storage.h"
724c96
 #include "nm-agent-manager.h"
724c96
 #include "nm-config.h"
724c96
+#include "nm-manager.h"
724c96
 #include "nm-audit-manager.h"
724c96
 #include "NetworkManagerUtils.h"
724c96
 #include "nm-dispatcher.h"
724c96
@@ -324,6 +325,7 @@ _sett_conn_entry_find_shadowed_storage (SettConnEntry *sett_conn_entry,
724c96
 /*****************************************************************************/
724c96
 
724c96
 NM_GOBJECT_PROPERTIES_DEFINE (NMSettings,
724c96
+	PROP_MANAGER,
724c96
 	PROP_UNMANAGED_SPECS,
724c96
 	PROP_HOSTNAME,
724c96
 	PROP_CAN_MODIFY,
724c96
@@ -348,6 +350,8 @@ typedef struct {
724c96
 
724c96
 	NMPlatform *platform;
724c96
 
724c96
+	NMManager *manager;
724c96
+
724c96
 	NMHostnameManager *hostname_manager;
724c96
 
724c96
 	NMSessionMonitor *session_monitor;
724c96
@@ -3805,6 +3809,26 @@ get_property (GObject *object, guint prop_id,
724c96
 	}
724c96
 }
724c96
 
724c96
+static void
724c96
+set_property (GObject *object, guint prop_id,
724c96
+              const GValue *value, GParamSpec *pspec)
724c96
+{
724c96
+	NMSettings *self = NM_SETTINGS (object);
724c96
+	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
724c96
+
724c96
+	switch (prop_id) {
724c96
+	case PROP_MANAGER:
724c96
+		/* construct-only */
724c96
+		priv->manager = g_value_get_pointer (value);
724c96
+		nm_assert (NM_IS_MANAGER (priv->manager));
724c96
+		g_object_add_weak_pointer (G_OBJECT (priv->manager), (gpointer *) &priv->manager);
724c96
+		break;
724c96
+	default:
724c96
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
724c96
+		break;
724c96
+	}
724c96
+}
724c96
+
724c96
 /*****************************************************************************/
724c96
 
724c96
 static void
724c96
@@ -3833,9 +3857,13 @@ nm_settings_init (NMSettings *self)
724c96
 }
724c96
 
724c96
 NMSettings *
724c96
-nm_settings_new (void)
724c96
+nm_settings_new (NMManager *manager)
724c96
 {
724c96
-	return g_object_new (NM_TYPE_SETTINGS, NULL);
724c96
+	nm_assert (NM_IS_MANAGER (manager));
724c96
+
724c96
+	return g_object_new (NM_TYPE_SETTINGS,
724c96
+	                     NM_SETTINGS_MANAGER, manager,
724c96
+	                     NULL);
724c96
 }
724c96
 
724c96
 static void
724c96
@@ -3915,6 +3943,11 @@ finalize (GObject *object)
724c96
 	g_clear_object (&priv->config);
724c96
 
724c96
 	g_clear_object (&priv->platform);
724c96
+
724c96
+	if (priv->manager) {
724c96
+		g_object_remove_weak_pointer (G_OBJECT (priv->manager), (gpointer *) &priv->manager);
724c96
+		priv->manager = NULL;
724c96
+	}
724c96
 }
724c96
 
724c96
 static const GDBusSignalInfo signal_info_new_connection = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT (
724c96
@@ -4051,9 +4084,16 @@ nm_settings_class_init (NMSettingsClass *class)
724c96
 	dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_settings);
724c96
 
724c96
 	object_class->get_property = get_property;
724c96
+	object_class->set_property = set_property;
724c96
 	object_class->dispose = dispose;
724c96
 	object_class->finalize = finalize;
724c96
 
724c96
+	obj_properties[PROP_MANAGER] =
724c96
+	    g_param_spec_pointer (NM_SETTINGS_MANAGER, "", "",
724c96
+	                          G_PARAM_CONSTRUCT_ONLY |
724c96
+	                          G_PARAM_WRITABLE |
724c96
+	                          G_PARAM_STATIC_STRINGS);
724c96
+
724c96
 	obj_properties[PROP_UNMANAGED_SPECS] =
724c96
 	    g_param_spec_boxed (NM_SETTINGS_UNMANAGED_SPECS, "", "",
724c96
 	                        G_TYPE_STRV,
724c96
diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h
724c96
index aa7e36e09395..b7baf4373280 100644
724c96
--- a/src/settings/nm-settings.h
724c96
+++ b/src/settings/nm-settings.h
724c96
@@ -26,6 +26,7 @@
724c96
 #define NM_SETTINGS_CAN_MODIFY       "can-modify"
724c96
 #define NM_SETTINGS_CONNECTIONS      "connections"
724c96
 #define NM_SETTINGS_STARTUP_COMPLETE "startup-complete"
724c96
+#define NM_SETTINGS_MANAGER          "manager"
724c96
 
724c96
 #define NM_SETTINGS_SIGNAL_CONNECTION_ADDED              "connection-added"
724c96
 #define NM_SETTINGS_SIGNAL_CONNECTION_UPDATED            "connection-updated"
724c96
@@ -53,7 +54,7 @@ GType nm_settings_get_type (void);
724c96
 NMSettings *nm_settings_get (void);
724c96
 #define NM_SETTINGS_GET (nm_settings_get ())
724c96
 
724c96
-NMSettings *nm_settings_new (void);
724c96
+NMSettings *nm_settings_new (NMManager *manager);
724c96
 
724c96
 gboolean nm_settings_start (NMSettings *self, GError **error);
724c96
 
724c96
-- 
724c96
2.26.2
724c96
724c96
724c96
From bc8ea71287204996830a4f02657d4d036e8c85ff Mon Sep 17 00:00:00 2001
724c96
From: Thomas Haller <thaller@redhat.com>
724c96
Date: Tue, 11 Aug 2020 15:34:59 +0200
724c96
Subject: [PATCH 4/7] settings: rework wait-device-timeout handling and
724c96
 consider device compatibility
724c96
724c96
A profile can configure "connection.wait-device-timeout" to indicate
724c96
that startup complete is blocked until a suitable device around.
724c96
This is useful for NetworkManager-wait-online and initrd mode.
724c96
724c96
Previously, we looked at NMPlatform whether a link with matching
724c96
interface-name was present. That is wrong because it cannot handle
724c96
profiles that rely on "ethernet.mac-address" setting or other "match"
724c96
settings. Also, the mere presence of the link does not yet mean
724c96
that the NMDevice was created and ready. In fact, there is a race here:
724c96
NMPlatform indicates that the device is ready (unblocking NMSettings),
724c96
but there is no corresponding NMDevice yet which keeps NetworkManager
724c96
busy to block startup complete.
724c96
724c96
Rework this. Now, only check whether there is a compatible device for
724c96
the profile.
724c96
724c96
Since we wait for compatible devices, it works now not only for the
724c96
interface name. Note that we do some optimizations so that we don't have
724c96
to re-evaluate all profiles (w.r.t. all devices) whenever something on the
724c96
device changes: we only care about this when all devices finally become
724c96
ready.
724c96
724c96
Also, we no longer start the timeout for "connection.wait-device-timeout"
724c96
when the profile appears. Instead, there is one system-wide start time
724c96
(NMSettingsPrivate.startup_complete_start_timestamp_msec). That simplifies
724c96
code and makes sense: we start waiting when NetworkManager is starting, not
724c96
when the profile gets added. Also, we wait for all profiles to become
724c96
ready together.
724c96
724c96
(cherry picked from commit 3df662f534c49c9df3e16808be125a562c97d954)
724c96
(cherry picked from commit 7ab8c5ba252e38b5cdeb958a7753df5fee1c55db)
724c96
---
724c96
 clients/common/settings-docs.h.in  |   2 +-
724c96
 libnm-core/nm-setting-connection.c |  23 +-
724c96
 src/nm-manager.c                   |  32 ++-
724c96
 src/settings/nm-settings.c         | 336 +++++++++++++++--------------
724c96
 src/settings/nm-settings.h         |   3 +-
724c96
 5 files changed, 209 insertions(+), 187 deletions(-)
724c96
724c96
diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in
724c96
index 7b891500d8c9..606a1b95c5df 100644
724c96
--- a/clients/common/settings-docs.h.in
724c96
+++ b/clients/common/settings-docs.h.in
724c96
@@ -171,7 +171,7 @@
724c96
 #define DESCRIBE_DOC_NM_SETTING_CONNECTION_TIMESTAMP N_("The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved).")
724c96
 #define DESCRIBE_DOC_NM_SETTING_CONNECTION_TYPE N_("Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, \"802-3-ethernet\" or \"802-11-wireless\" or \"bluetooth\", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, \"vpn\" or \"bridge\", etc).")
724c96
 #define DESCRIBE_DOC_NM_SETTING_CONNECTION_UUID N_("A universally unique identifier for the connection, for example generated with libuuid.  It should be assigned when the connection is created, and never changed as long as the connection still applies to the same network.  For example, it should not be changed when the \"id\" property or NMSettingIP4Config changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband network provider, or \"type\" property changes. The UUID must be in the format \"2815492f-7e56-435e-b2e9-246bd7cdc664\" (ie, contains only hexadecimal characters and \"-\").")
724c96
-#define DESCRIBE_DOC_NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT N_("Timeout in milliseconds to wait for device at startup. During boot, devices may take a while to be detected by the driver. This property will cause to delay NetworkManager-wait-online.service and nm-online to give the device a chance to appear. Note that this property only works together with NMSettingConnection:interface-name to identify the device that will be waited for. The value 0 means no wait time. The default value is -1, which currently has the same meaning as no wait time.")
724c96
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT N_("Timeout in milliseconds to wait for device at startup. During boot, devices may take a while to be detected by the driver. This property will cause to delay NetworkManager-wait-online.service and nm-online to give the device a chance to appear. This works by waiting for the given timeout until a compatible device for the profile is available and managed. The value 0 means no wait time. The default value is -1, which currently has the same meaning as no wait time.")
724c96
 #define DESCRIBE_DOC_NM_SETTING_CONNECTION_ZONE N_("The trust level of a the connection.  Free form case-insensitive string (for example \"Home\", \"Work\", \"Public\").  NULL or unspecified zone means the connection will be placed in the default zone as defined by the firewall. When updating this property on a currently activated connection, the change takes effect immediately.")
724c96
 #define DESCRIBE_DOC_NM_SETTING_DCB_APP_FCOE_FLAGS N_("Specifies the NMSettingDcbFlags for the DCB FCoE application.  Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).")
724c96
 #define DESCRIBE_DOC_NM_SETTING_DCB_APP_FCOE_MODE N_("The FCoE controller mode; either \"fabric\" (default) or \"vn2vn\".")
724c96
diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c
724c96
index 018129bef200..03f8fb23c099 100644
724c96
--- a/libnm-core/nm-setting-connection.c
724c96
+++ b/libnm-core/nm-setting-connection.c
724c96
@@ -689,7 +689,7 @@ nm_setting_connection_is_slave_type (NMSettingConnection *setting,
724c96
  * @setting: the #NMSettingConnection
724c96
  *
724c96
  * Returns: the %NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT property with
724c96
- *   the timeout in milli seconds. -1 is the default.
724c96
+ *   the timeout in milliseconds. -1 is the default.
724c96
  *
724c96
  * Since: 1.20
724c96
  */
724c96
@@ -1218,20 +1218,6 @@ after_interface_name:
724c96
 		return FALSE;
724c96
 	}
724c96
 
724c96
-	if (   priv->wait_device_timeout != -1
724c96
-	    && !priv->interface_name) {
724c96
-		/* currently, only waiting by interface-name is implemented. Hence reject
724c96
-		 * configurations that are not implemented (yet). */
724c96
-		g_set_error (error,
724c96
-		             NM_CONNECTION_ERROR,
724c96
-		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
724c96
-		             _("wait-device-timeout requires %s"),
724c96
-		             NM_SETTING_CONNECTION_INTERFACE_NAME);
724c96
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME,
724c96
-		                NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT);
724c96
-		return FALSE;
724c96
-	}
724c96
-
724c96
 	if (priv->mud_url) {
724c96
 		if (!priv->mud_url[0]) {
724c96
 			g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
724c96
@@ -2314,10 +2300,9 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass)
724c96
 	 * Timeout in milliseconds to wait for device at startup.
724c96
 	 * During boot, devices may take a while to be detected by the driver.
724c96
 	 * This property will cause to delay NetworkManager-wait-online.service
724c96
-	 * and nm-online to give the device a chance to appear.
724c96
-	 *
724c96
-	 * Note that this property only works together with NMSettingConnection:interface-name
724c96
-	 * to identify the device that will be waited for.
724c96
+	 * and nm-online to give the device a chance to appear. This works by
724c96
+	 * waiting for the given timeout until a compatible device for the
724c96
+	 * profile is available and managed.
724c96
 	 *
724c96
 	 * The value 0 means no wait time. The default value is -1, which
724c96
 	 * currently has the same meaning as no wait time.
724c96
diff --git a/src/nm-manager.c b/src/nm-manager.c
724c96
index 6095f2687153..778e3b946ac9 100644
724c96
--- a/src/nm-manager.c
724c96
+++ b/src/nm-manager.c
724c96
@@ -1561,13 +1561,6 @@ check_if_startup_complete (NMManager *self)
724c96
 	if (!priv->devices_inited)
724c96
 		return;
724c96
 
724c96
-	reason = nm_settings_get_startup_complete_blocked_reason (priv->settings);
724c96
-	if (reason) {
724c96
-		_LOGD (LOGD_CORE, "startup complete is waiting for connection (%s)",
724c96
-		       reason);
724c96
-		return;
724c96
-	}
724c96
-
724c96
 	c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) {
724c96
 		reason = nm_device_has_pending_action_reason (device);
724c96
 		if (reason) {
724c96
@@ -1578,6 +1571,31 @@ check_if_startup_complete (NMManager *self)
724c96
 		}
724c96
 	}
724c96
 
724c96
+	/* All NMDevice must be ready. But also NMSettings tracks profiles that wait for
724c96
+	 * ready devices via "connection.wait-device-timeout".
724c96
+	 *
724c96
+	 * Note that we only re-check nm_settings_get_startup_complete_blocked_reason() when
724c96
+	 * all of the devices become ready (again).
724c96
+	 *
724c96
+	 * For example, assume we have device "eth1" and "profile-eth2" which waits for "eth2".
724c96
+	 * If "eth1" is ready (no pending action), we only need to re-evaluate "profile-eth2"
724c96
+	 * if we have another device ("eth2"), that becomes non-ready (had pending actions)
724c96
+	 * and again become ready. We don't need to check "profile-eth2" until "eth2" becomes
724c96
+	 * non-ready.
724c96
+	 * That is why nm_settings_get_startup_complete_blocked_reason() only has any significance
724c96
+	 * if all devices are ready too. It allows us to cut down the number of checks whether
724c96
+	 * NMSettings is ready. That's because we don't need to re-evaluate on minor changes of
724c96
+	 * a device, only when all devices become managed and ready. */
724c96
+
724c96
+	g_signal_handlers_block_by_func (priv->settings, settings_startup_complete_changed, self);
724c96
+	reason = nm_settings_get_startup_complete_blocked_reason (priv->settings, TRUE);
724c96
+	g_signal_handlers_unblock_by_func (priv->settings, settings_startup_complete_changed, self);
724c96
+	if (reason) {
724c96
+		_LOGD (LOGD_CORE, "startup complete is waiting for connection (%s)",
724c96
+		       reason);
724c96
+		return;
724c96
+	}
724c96
+
724c96
 	_LOGI (LOGD_CORE, "startup complete");
724c96
 
724c96
 	priv->startup = FALSE;
724c96
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
724c96
index 85c5e5e77f85..ef86d2d2c836 100644
724c96
--- a/src/settings/nm-settings.c
724c96
+++ b/src/settings/nm-settings.c
724c96
@@ -376,9 +376,9 @@ typedef struct {
724c96
 	GSList *unmanaged_specs;
724c96
 	GSList *unrecognized_specs;
724c96
 
724c96
+	gint64 startup_complete_start_timestamp_msec;
724c96
 	GHashTable *startup_complete_idx;
724c96
-	NMSettingsConnection *startup_complete_blocked_by;
724c96
-	gulong startup_complete_platform_change_id;
724c96
+	CList startup_complete_scd_lst_head;
724c96
 	guint startup_complete_timeout_id;
724c96
 
724c96
 	guint connections_len;
724c96
@@ -427,7 +427,7 @@ static void default_wired_clear_tag (NMSettings *self,
724c96
 static void _clear_connections_cached_list (NMSettingsPrivate *priv);
724c96
 
724c96
 static void _startup_complete_check (NMSettings *self,
724c96
-                                     gint64 now_us);
724c96
+                                     gint64 now_msec);
724c96
 
724c96
 /*****************************************************************************/
724c96
 
724c96
@@ -465,34 +465,51 @@ _emit_connection_flags_changed (NMSettings *self,
724c96
 
724c96
 typedef struct {
724c96
 	NMSettingsConnection *sett_conn;
724c96
-	gint64 start_at;
724c96
-	gint64 timeout;
724c96
+	CList scd_lst;
724c96
+	gint64 timeout_msec;
724c96
 } StartupCompleteData;
724c96
 
724c96
 static void
724c96
 _startup_complete_data_destroy (StartupCompleteData *scd)
724c96
 {
724c96
+	c_list_unlink_stale (&scd->scd_lst);
724c96
 	g_object_unref (scd->sett_conn);
724c96
-	g_slice_free (StartupCompleteData, scd);
724c96
+	nm_g_slice_free (scd);
724c96
 }
724c96
 
724c96
 static gboolean
724c96
-_startup_complete_check_is_ready (NMPlatform *platform,
724c96
+_startup_complete_check_is_ready (NMSettings *self,
724c96
                                   NMSettingsConnection *sett_conn)
724c96
 {
724c96
-	const NMPlatformLink *plink;
724c96
-	const char *ifname;
724c96
+	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
724c96
+	NMConnection *conn;
724c96
+	const CList *tmp_lst;
724c96
+	NMDevice *device;
724c96
+
724c96
+	if (!priv->manager)
724c96
+		return TRUE;
724c96
+
724c96
+	conn = nm_settings_connection_get_connection (sett_conn);
724c96
 
724c96
-	/* FIXME: instead of just looking for the interface name, it would be better
724c96
-	 *        to wait for a device that is compatible with the profile. */
724c96
+	nm_manager_for_each_device (priv->manager, device, tmp_lst) {
724c96
 
724c96
-	ifname = nm_connection_get_interface_name (nm_settings_connection_get_connection (sett_conn));
724c96
+		if (!nm_device_is_real (device))
724c96
+			continue;
724c96
+
724c96
+		if (   nm_device_get_state (device) < NM_DEVICE_STATE_UNAVAILABLE
724c96
+		    || nm_device_has_pending_action (device)) {
724c96
+			/* while a device is not yet available and still has a pending
724c96
+			 * action itself, it's not a suitable candidate. */
724c96
+			continue;
724c96
+		}
724c96
+
724c96
+		if (!nm_device_check_connection_compatible (device, conn, NULL))
724c96
+			continue;
724c96
 
724c96
-	if (!ifname)
724c96
 		return TRUE;
724c96
+	}
724c96
 
724c96
-	plink = nm_platform_link_get_by_ifname (platform, ifname);
724c96
-	return plink && plink->initialized;
724c96
+	return FALSE;
724c96
 }
724c96
 
724c96
 static gboolean
724c96
@@ -506,117 +523,98 @@ _startup_complete_timeout_cb (gpointer user_data)
724c96
 	return G_SOURCE_REMOVE;
724c96
 }
724c96
 
724c96
-static void
724c96
-_startup_complete_platform_change_cb (NMPlatform *platform,
724c96
-                                      int obj_type_i,
724c96
-                                      int ifindex,
724c96
-                                      const NMPlatformLink *link,
724c96
-                                      int change_type_i,
724c96
-                                      NMSettings *self)
724c96
-{
724c96
-	const NMPlatformSignalChangeType change_type = change_type_i;
724c96
-	NMSettingsPrivate *priv;
724c96
-	const char *ifname;
724c96
-
724c96
-	if (change_type == NM_PLATFORM_SIGNAL_REMOVED)
724c96
-		return;
724c96
-
724c96
-	if (!link->initialized)
724c96
-		return;
724c96
-
724c96
-	priv = NM_SETTINGS_GET_PRIVATE (self);
724c96
-
724c96
-	ifname = nm_connection_get_interface_name (nm_settings_connection_get_connection (priv->startup_complete_blocked_by));
724c96
-	if (   ifname
724c96
-	    && !nm_streq (ifname, link->name))
724c96
-		return;
724c96
-
724c96
-	nm_assert (priv->startup_complete_timeout_id > 0);
724c96
-
724c96
-	nm_clear_g_source (&priv->startup_complete_timeout_id);
724c96
-	priv->startup_complete_timeout_id = g_idle_add (_startup_complete_timeout_cb, self);
724c96
-}
724c96
-
724c96
 static void
724c96
 _startup_complete_check (NMSettings *self,
724c96
-                         gint64 now_us)
724c96
+                         gint64 now_msec)
724c96
 {
724c96
 	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
724c96
-	gint64 next_expiry;
724c96
+	StartupCompleteData *scd_not_ready;
724c96
+	StartupCompleteData *scd_safe;
724c96
 	StartupCompleteData *scd;
724c96
-	NMSettingsConnection *next_sett_conn = NULL;
724c96
-	GHashTableIter iter;
724c96
+	gint64 elapsed_msec;
724c96
+	CList ready_lst;
724c96
+
724c96
+	if (priv->startup_complete_start_timestamp_msec == 0) {
724c96
+		/* we are already done for good or didn't start yet. */
724c96
+		return;
724c96
+	}
724c96
 
724c96
 	if (!priv->started) {
724c96
-		/* before we are started, we don't setup the timers... */
724c96
+		/* before we are started there is no need to evaluate our list because
724c96
+		 * we are anyway blocking startup-complete. */
724c96
 		return;
724c96
 	}
724c96
 
724c96
-	if (!priv->startup_complete_idx)
724c96
+	if (c_list_is_empty (&priv->startup_complete_scd_lst_head))
724c96
 		goto ready;
724c96
 
724c96
-	if (!now_us)
724c96
-		now_us = nm_utils_get_monotonic_timestamp_usec ();
724c96
+	nm_utils_get_monotonic_timestamp_msec_cached (&now_msec);
724c96
 
724c96
-	next_expiry = 0;
724c96
+	elapsed_msec = now_msec - priv->startup_complete_start_timestamp_msec;
724c96
 
724c96
-	g_hash_table_iter_init (&iter, priv->startup_complete_idx);
724c96
-	while (g_hash_table_iter_next (&iter, (gpointer *) &scd, NULL)) {
724c96
-		gint64 expiry;
724c96
-
724c96
-		if (scd->start_at == 0) {
724c96
-			/* once ready, the decision is remembered and there is nothing
724c96
-			 * left to check. */
724c96
-			continue;
724c96
-		}
724c96
+	/* We search the entire list whether they all timed-out or found a compatible device.
724c96
+	 * We do that by appending elements that are ready to the end of the list, so that
724c96
+	 * we hopefully keep testing the elements that are ready already (and can shortcut
724c96
+	 * the test in common cases).
724c96
+	 *
724c96
+	 * Note that all profiles that we wait for need to have their dependencies satisfied
724c96
+	 * at the same time. For example, consider connection A is waiting for device A' which is ready.
724c96
+	 * Connection B waits for device B', which isn't ready. Once B'/B becomes ready, A/A' must
724c96
+	 * still be ready. Otherwise, we would wait for A/A' to become ready again. */
724c96
+	scd_not_ready = NULL;
724c96
+	c_list_init (&ready_lst);
724c96
+	c_list_for_each_entry_safe (scd, scd_safe, &priv->startup_complete_scd_lst_head, scd_lst) {
724c96
 
724c96
-		expiry = scd->start_at + scd->timeout;
724c96
-		if (expiry <= now_us) {
724c96
-			scd->start_at = 0;
724c96
-			continue;
724c96
-		}
724c96
+		if (scd->timeout_msec <= elapsed_msec)
724c96
+			goto next_with_ready;
724c96
 
724c96
-		if (_startup_complete_check_is_ready (priv->platform, scd->sett_conn)) {
724c96
-			scd->start_at = 0;
724c96
-			continue;
724c96
-		}
724c96
+		if (_startup_complete_check_is_ready (self, scd->sett_conn))
724c96
+			goto next_with_ready;
724c96
 
724c96
-		next_expiry = expiry;
724c96
-		next_sett_conn = scd->sett_conn;
724c96
-		/* we found one timeout for which to wait. that's good enough. */
724c96
+		scd_not_ready = scd;
724c96
 		break;
724c96
+
724c96
+next_with_ready:
724c96
+		/* this element is ready. We move it to a temporary list, so that we
724c96
+		 * can reorder the list (to next time evaluate the non-ready element first). */
724c96
+		nm_c_list_move_tail (&ready_lst, &scd->scd_lst);
724c96
 	}
724c96
+	c_list_splice (&priv->startup_complete_scd_lst_head, &ready_lst);
724c96
 
724c96
 	nm_clear_g_source (&priv->startup_complete_timeout_id);
724c96
-	nm_g_object_ref_set (&priv->startup_complete_blocked_by, next_sett_conn);
724c96
-	if (next_expiry > 0) {
724c96
-		nm_assert (priv->startup_complete_blocked_by);
724c96
-		if (priv->startup_complete_platform_change_id == 0) {
724c96
-			priv->startup_complete_platform_change_id = g_signal_connect (priv->platform,
724c96
-			                                                              NM_PLATFORM_SIGNAL_LINK_CHANGED,
724c96
-			                                                              G_CALLBACK (_startup_complete_platform_change_cb),
724c96
-			                                                              self);
724c96
-		}
724c96
-		priv->startup_complete_timeout_id = g_timeout_add (NM_MIN (3600u*1000u, (next_expiry - now_us) / 1000u),
724c96
+
724c96
+	if (scd_not_ready) {
724c96
+		gint64 timeout_msec;
724c96
+
724c96
+		timeout_msec = priv->startup_complete_start_timestamp_msec + scd_not_ready->timeout_msec - nm_utils_get_monotonic_timestamp_msec ();
724c96
+		priv->startup_complete_timeout_id = g_timeout_add (NM_CLAMP (0, timeout_msec, 60000),
724c96
 		                                                   _startup_complete_timeout_cb,
724c96
 		                                                   self);
724c96
-		_LOGT ("startup-complete: wait for device \"%s\" due to connection %s (%s)",
724c96
-		       nm_connection_get_interface_name (nm_settings_connection_get_connection (priv->startup_complete_blocked_by)),
724c96
-		       nm_settings_connection_get_uuid (priv->startup_complete_blocked_by),
724c96
-		       nm_settings_connection_get_id (priv->startup_complete_blocked_by));
724c96
+		_LOGT ("startup-complete: wait for suitable device for connection \"%s\" (%s) which has \"connection.wait-device-timeout\" set",
724c96
+		       nm_settings_connection_get_id (scd_not_ready->sett_conn),
724c96
+		       nm_settings_connection_get_uuid (scd_not_ready->sett_conn));
724c96
 		return;
724c96
 	}
724c96
 
724c96
-	nm_clear_pointer (&priv->startup_complete_idx, g_hash_table_destroy);
724c96
-	nm_clear_g_signal_handler (priv->platform, &priv->startup_complete_platform_change_id);
724c96
+	if (_LOGW_ENABLED ()) {
724c96
+		c_list_for_each_entry (scd, &priv->startup_complete_scd_lst_head, scd_lst) {
724c96
+			if (!_startup_complete_check_is_ready (self, scd->sett_conn)) {
724c96
+				_LOGW ("startup-complete: profile \"%s\" (%s) was waiting for non-existing device (with timeout \"connection.wait-device-timeout=%"G_GINT64_FORMAT"\")",
724c96
+				       nm_settings_connection_get_id (scd->sett_conn),
724c96
+				       nm_settings_connection_get_uuid (scd->sett_conn),
724c96
+				       scd->timeout_msec);
724c96
+			}
724c96
+		}
724c96
+	}
724c96
 
724c96
 ready:
724c96
-	_LOGT ("startup-complete: ready, no profiles to wait for");
724c96
+	nm_clear_pointer (&priv->startup_complete_idx, g_hash_table_destroy);
724c96
+	nm_assert (c_list_is_empty (&priv->startup_complete_scd_lst_head));
724c96
 	nm_assert (priv->started);
724c96
-	nm_assert (!priv->startup_complete_blocked_by);
724c96
+	_LOGT ("startup-complete: ready, no more profiles to wait for");
724c96
+	priv->startup_complete_start_timestamp_msec = 0;
724c96
 	nm_assert (!priv->startup_complete_idx);
724c96
 	nm_assert (priv->startup_complete_timeout_id == 0);
724c96
-	nm_assert (priv->startup_complete_platform_change_id == 0);
724c96
 	_notify (self, PROP_STARTUP_COMPLETE);
724c96
 }
724c96
 
724c96
@@ -626,75 +624,95 @@ _startup_complete_notify_connection (NMSettings *self,
724c96
                                      gboolean forget)
724c96
 {
724c96
 	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
724c96
-	gint64 timeout;
724c96
-	gint64 now_us = 0;
724c96
-
724c96
-	nm_assert (   !priv->started
724c96
-	           || priv->startup_complete_idx);
724c96
-
724c96
-	timeout = 0;
724c96
-	if (!forget) {
724c96
-		NMSettingConnection *s_con;
724c96
-		gint32 v;
724c96
-
724c96
-		s_con = nm_connection_get_setting_connection (nm_settings_connection_get_connection (sett_conn));
724c96
-		v = nm_setting_connection_get_wait_device_timeout (s_con);
724c96
-		if (v > 0) {
724c96
-			nm_assert (nm_setting_connection_get_interface_name (s_con));
724c96
-			timeout = ((gint64) v) * 1000;
724c96
-		}
724c96
+	StartupCompleteData *scd;
724c96
+	gint64 timeout_msec;
724c96
+	gint64 now_msec = 0;
724c96
+	NMSettingConnection *s_con;
724c96
+	gint32 v;
724c96
+
724c96
+	nm_assert (priv->startup_complete_start_timestamp_msec != 0);
724c96
+
724c96
+	if (forget) {
724c96
+		if (!priv->startup_complete_idx)
724c96
+			return;
724c96
+		if (!g_hash_table_remove (priv->startup_complete_idx, &sett_conn))
724c96
+			return;
724c96
+		goto check;
724c96
 	}
724c96
 
724c96
-	if (timeout == 0) {
724c96
-		if (   !priv->startup_complete_idx
724c96
-		    || !g_hash_table_remove (priv->startup_complete_idx, &sett_conn))
724c96
+	s_con = nm_connection_get_setting_connection (nm_settings_connection_get_connection (sett_conn));
724c96
+	v = nm_setting_connection_get_wait_device_timeout (s_con);
724c96
+	if (v > 0)
724c96
+		timeout_msec = v;
724c96
+	else
724c96
+		timeout_msec = 0;
724c96
+
724c96
+	if (!priv->startup_complete_idx) {
724c96
+		nm_assert (!priv->started);
724c96
+
724c96
+		if (timeout_msec == 0)
724c96
+			return;
724c96
+
724c96
+		priv->startup_complete_idx = g_hash_table_new_full (nm_pdirect_hash,
724c96
+		                                                    nm_pdirect_equal,
724c96
+		                                                    NULL,
724c96
+		                                                    (GDestroyNotify) _startup_complete_data_destroy);
724c96
+		scd = NULL;
724c96
+	} else
724c96
+		scd = g_hash_table_lookup (priv->startup_complete_idx, &sett_conn);
724c96
+
724c96
+	if (!scd) {
724c96
+		if (timeout_msec == 0)
724c96
 			return;
724c96
+		scd = g_slice_new (StartupCompleteData);
724c96
+		*scd = (StartupCompleteData) {
724c96
+			.sett_conn    = g_object_ref (sett_conn),
724c96
+			.timeout_msec = timeout_msec,
724c96
+		};
724c96
+		g_hash_table_add (priv->startup_complete_idx, scd);
724c96
+		c_list_link_tail (&priv->startup_complete_scd_lst_head, &scd->scd_lst);
724c96
 	} else {
724c96
-		StartupCompleteData *scd;
724c96
-
724c96
-		if (!priv->startup_complete_idx) {
724c96
-			nm_assert (!priv->started);
724c96
-			priv->startup_complete_idx = g_hash_table_new_full (nm_pdirect_hash,
724c96
-			                                                    nm_pdirect_equal,
724c96
-			                                                    NULL,
724c96
-			                                                    (GDestroyNotify) _startup_complete_data_destroy);
724c96
-			scd = NULL;
724c96
-		} else
724c96
-			scd = g_hash_table_lookup (priv->startup_complete_idx, &sett_conn);
724c96
-		if (!scd) {
724c96
-			now_us = nm_utils_get_monotonic_timestamp_usec ();
724c96
-			scd = g_slice_new (StartupCompleteData);
724c96
-			*scd = (StartupCompleteData) {
724c96
-				.sett_conn = g_object_ref (sett_conn),
724c96
-				.start_at  = now_us,
724c96
-				.timeout   = timeout,
724c96
-			};
724c96
-			g_hash_table_add (priv->startup_complete_idx, scd);
724c96
-		} else {
724c96
-			if (scd->start_at == 0) {
724c96
-				/* the entry already is ready and no longer relevant. Ignore it. */
724c96
-				return;
724c96
-			}
724c96
-			scd->timeout = timeout;
724c96
-		}
724c96
+		scd->timeout_msec = timeout_msec;
724c96
+		nm_c_list_move_front (&priv->startup_complete_scd_lst_head, &scd->scd_lst);
724c96
 	}
724c96
 
724c96
-	_startup_complete_check (self, now_us);
724c96
+check:
724c96
+	_startup_complete_check (self, now_msec);
724c96
 }
724c96
 
724c96
 const char *
724c96
-nm_settings_get_startup_complete_blocked_reason (NMSettings *self)
724c96
+nm_settings_get_startup_complete_blocked_reason (NMSettings *self,
724c96
+                                                 gboolean force_reload)
724c96
 {
724c96
 	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
724c96
-	const char *uuid = NULL;
724c96
+	StartupCompleteData *scd;
724c96
+	const char *uuid;
724c96
 
724c96
-	if (priv->started) {
724c96
-		if (!priv->startup_complete_idx)
724c96
-			return NULL;
724c96
-		if (priv->startup_complete_blocked_by)
724c96
-			uuid = nm_settings_connection_get_uuid (priv->startup_complete_blocked_by);
724c96
-	}
724c96
-	return uuid ?: "unknown";
724c96
+	if (priv->startup_complete_start_timestamp_msec == 0)
724c96
+		goto out_done;
724c96
+
724c96
+	if (force_reload)
724c96
+		_startup_complete_check (self, 0);
724c96
+
724c96
+	if (c_list_is_empty (&priv->startup_complete_scd_lst_head))
724c96
+		goto out_done;
724c96
+
724c96
+	scd = c_list_first_entry (&priv->startup_complete_scd_lst_head, StartupCompleteData, scd_lst);
724c96
+
724c96
+	nm_assert (scd);
724c96
+	nm_assert (NM_IS_SETTINGS_CONNECTION (scd->sett_conn));
724c96
+	nm_assert (scd == nm_g_hash_table_lookup (priv->startup_complete_idx, &scd->sett_conn));
724c96
+
724c96
+	uuid = nm_settings_connection_get_uuid (scd->sett_conn);
724c96
+	if (uuid)
724c96
+		return uuid;
724c96
+
724c96
+	g_return_val_if_reached ("settings-starting");
724c96
+
724c96
+out_done:
724c96
+	if (!priv->started)
724c96
+		return "settings-starting";
724c96
+	return NULL;
724c96
 }
724c96
 
724c96
 /*****************************************************************************/
724c96
@@ -1142,8 +1160,7 @@ _connection_changed_update (NMSettings *self,
724c96
 		_emit_connection_updated (self, sett_conn, update_reason);
724c96
 	}
724c96
 
724c96
-	if (   !priv->started
724c96
-	    || priv->startup_complete_idx) {
724c96
+	if (priv->startup_complete_start_timestamp_msec != 0) {
724c96
 		if (nm_settings_has_connection (self, sett_conn))
724c96
 			_startup_complete_notify_connection (self, sett_conn, FALSE);
724c96
 	}
724c96
@@ -1217,8 +1234,7 @@ _connection_changed_delete (NMSettings *self,
724c96
 	nm_key_file_db_remove_key (priv->kf_db_timestamps, uuid);
724c96
 	nm_key_file_db_remove_key (priv->kf_db_seen_bssids, uuid);
724c96
 
724c96
-	if (   !priv->started
724c96
-	    || priv->startup_complete_idx)
724c96
+	if (priv->startup_complete_start_timestamp_msec != 0)
724c96
 		_startup_complete_notify_connection (self, sett_conn, TRUE);
724c96
 }
724c96
 
724c96
@@ -3715,6 +3731,8 @@ nm_settings_start (NMSettings *self, GError **error)
724c96
 
724c96
 	nm_assert (!priv->started);
724c96
 
724c96
+	priv->startup_complete_start_timestamp_msec = nm_utils_get_monotonic_timestamp_msec ();
724c96
+
724c96
 	priv->hostname_manager = g_object_ref (nm_hostname_manager_get ());
724c96
 
724c96
 	priv->kf_db_timestamps = nm_key_file_db_new (NMSTATEDIR "/timestamps",
724c96
@@ -3801,7 +3819,7 @@ get_property (GObject *object, guint prop_id,
724c96
 		g_value_take_boxed (value, nm_utils_strv_make_deep_copied (strv));
724c96
 		break;
724c96
 	case PROP_STARTUP_COMPLETE:
724c96
-		g_value_set_boolean (value, !nm_settings_get_startup_complete_blocked_reason (self));
724c96
+		g_value_set_boolean (value, !nm_settings_get_startup_complete_blocked_reason (self, FALSE));
724c96
 		break;
724c96
 	default:
724c96
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
724c96
@@ -3838,6 +3856,7 @@ nm_settings_init (NMSettings *self)
724c96
 
724c96
 	c_list_init (&priv->auth_lst_head);
724c96
 	c_list_init (&priv->connections_lst_head);
724c96
+	c_list_init (&priv->startup_complete_scd_lst_head);
724c96
 
724c96
 	c_list_init (&priv->sce_dirty_lst_head);
724c96
 	priv->sce_idx = g_hash_table_new_full (nm_pstr_hash, nm_pstr_equal,
724c96
@@ -3877,9 +3896,8 @@ dispose (GObject *object)
724c96
 	nm_assert (g_hash_table_size (priv->sce_idx) == 0);
724c96
 
724c96
 	nm_clear_g_source (&priv->startup_complete_timeout_id);
724c96
-	nm_clear_g_signal_handler (priv->platform, &priv->startup_complete_platform_change_id);
724c96
 	nm_clear_pointer (&priv->startup_complete_idx, g_hash_table_destroy);
724c96
-	g_clear_object (&priv->startup_complete_blocked_by);
724c96
+	nm_assert (c_list_is_empty (&priv->startup_complete_scd_lst_head));
724c96
 
724c96
 	while ((iter = c_list_first (&priv->auth_lst_head)))
724c96
 		nm_auth_chain_destroy (nm_auth_chain_parent_lst_entry (iter));
724c96
diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h
724c96
index b7baf4373280..35c62ff71dd2 100644
724c96
--- a/src/settings/nm-settings.h
724c96
+++ b/src/settings/nm-settings.h
724c96
@@ -123,7 +123,8 @@ void nm_settings_device_added (NMSettings *self, NMDevice *device);
724c96
 
724c96
 void nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean quitting);
724c96
 
724c96
-const char *nm_settings_get_startup_complete_blocked_reason (NMSettings *self);
724c96
+const char *nm_settings_get_startup_complete_blocked_reason (NMSettings *self,
724c96
+                                                             gboolean force_reload);
724c96
 
724c96
 void nm_settings_kf_db_write (NMSettings *settings);
724c96
 
724c96
-- 
724c96
2.26.2
724c96
724c96
724c96
From 8ffcba687043cded8cd229d0ea2546654ef25e04 Mon Sep 17 00:00:00 2001
724c96
From: Thomas Haller <thaller@redhat.com>
724c96
Date: Thu, 13 Aug 2020 10:09:09 +0200
724c96
Subject: [PATCH 5/7] settings: suppress wrong warning about
724c96
 wait-device-timeout for devices that are still busy
724c96
724c96
Imagine we wait for a device, the device appears and starts activating.
724c96
That might take a while (during which it has a pending action). In the
724c96
meantime, the "connection.wait-device-timeout" timeout expires.
724c96
724c96
Now we want to log a warning about profiles that don't have their
724c96
device upon timeout. However, that the device is still busy at that
724c96
point is irrelevant. Skip logging a message about those profiles.
724c96
724c96
Fixes: 3df662f534c4 ('settings: rework wait-device-timeout handling and consider device compatibility')
724c96
(cherry picked from commit d9568ca3ee810897633bbc05f4f01e416add8182)
724c96
(cherry picked from commit 4e6fcb4a71f708dc06117584799015644abca81f)
724c96
---
724c96
 src/settings/nm-settings.c | 10 ++++++----
724c96
 1 file changed, 6 insertions(+), 4 deletions(-)
724c96
724c96
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
724c96
index ef86d2d2c836..4573d5f78ac3 100644
724c96
--- a/src/settings/nm-settings.c
724c96
+++ b/src/settings/nm-settings.c
724c96
@@ -479,7 +479,8 @@ _startup_complete_data_destroy (StartupCompleteData *scd)
724c96
 
724c96
 static gboolean
724c96
 _startup_complete_check_is_ready (NMSettings *self,
724c96
-                                  NMSettingsConnection *sett_conn)
724c96
+                                  NMSettingsConnection *sett_conn,
724c96
+                                  gboolean ignore_pending_actions)
724c96
 {
724c96
 	NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
724c96
 	NMConnection *conn;
724c96
@@ -497,7 +498,8 @@ _startup_complete_check_is_ready (NMSettings *self,
724c96
 			continue;
724c96
 
724c96
 		if (   nm_device_get_state (device) < NM_DEVICE_STATE_UNAVAILABLE
724c96
-		    || nm_device_has_pending_action (device)) {
724c96
+		    || (   !ignore_pending_actions
724c96
+		        && nm_device_has_pending_action (device))) {
724c96
 			/* while a device is not yet available and still has a pending
724c96
 			 * action itself, it's not a suitable candidate. */
724c96
 			continue;
724c96
@@ -568,7 +570,7 @@ _startup_complete_check (NMSettings *self,
724c96
 		if (scd->timeout_msec <= elapsed_msec)
724c96
 			goto next_with_ready;
724c96
 
724c96
-		if (_startup_complete_check_is_ready (self, scd->sett_conn))
724c96
+		if (_startup_complete_check_is_ready (self, scd->sett_conn, FALSE))
724c96
 			goto next_with_ready;
724c96
 
724c96
 		scd_not_ready = scd;
724c96
@@ -598,7 +600,7 @@ next_with_ready:
724c96
 
724c96
 	if (_LOGW_ENABLED ()) {
724c96
 		c_list_for_each_entry (scd, &priv->startup_complete_scd_lst_head, scd_lst) {
724c96
-			if (!_startup_complete_check_is_ready (self, scd->sett_conn)) {
724c96
+			if (!_startup_complete_check_is_ready (self, scd->sett_conn, TRUE)) {
724c96
 				_LOGW ("startup-complete: profile \"%s\" (%s) was waiting for non-existing device (with timeout \"connection.wait-device-timeout=%"G_GINT64_FORMAT"\")",
724c96
 				       nm_settings_connection_get_id (scd->sett_conn),
724c96
 				       nm_settings_connection_get_uuid (scd->sett_conn),
724c96
-- 
724c96
2.26.2
724c96
724c96
724c96
From 3f1067a30b23e9eec12d1e39233604c6962c963d Mon Sep 17 00:00:00 2001
724c96
From: Thomas Haller <thaller@redhat.com>
724c96
Date: Wed, 12 Aug 2020 17:35:25 +0200
724c96
Subject: [PATCH 6/7] initrd: always set "connection.wait-device-timeout" even
724c96
 if profile has no interface-name set
724c96
724c96
Since commit 3df662f534c4 ('settings: rework wait-device-timeout
724c96
handling and consider device compatibility'), "connection.wait-device-timeout"
724c96
works with profiles in general and doesn't require an interface-name
724c96
set.
724c96
724c96
Remove that restriction and let initrd generator create profiles that
724c96
always wait.
724c96
724c96
(cherry picked from commit 52af5e901e4e5e7727ae83db18a37730b5f898fe)
724c96
(cherry picked from commit f0d8d6f15778ffa861312c0c5a22f6bffe07c359)
724c96
---
724c96
 src/initrd/nmi-cmdline-reader.c | 5 +----
724c96
 1 file changed, 1 insertion(+), 4 deletions(-)
724c96
724c96
diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c
724c96
index 85be9f132eda..be39ef896fb4 100644
724c96
--- a/src/initrd/nmi-cmdline-reader.c
724c96
+++ b/src/initrd/nmi-cmdline-reader.c
724c96
@@ -883,11 +883,8 @@ connection_set_needed (NMConnection *connection)
724c96
 	                NM_SETTING_WIRED_SETTING_NAME))
724c96
 		return;
724c96
 
724c96
-	if (nm_str_is_empty (nm_setting_connection_get_interface_name (s_con)))
724c96
-		return;
724c96
-
724c96
 	g_object_set (s_con,
724c96
-	              NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT, NMI_WAIT_DEVICE_TIMEOUT_MS,
724c96
+	              NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT, (int) NMI_WAIT_DEVICE_TIMEOUT_MS,
724c96
 	              NULL);
724c96
 }
724c96
 
724c96
-- 
724c96
2.26.2
724c96
724c96
724c96
From 98fca91c687084a80231d5f797f3257cc826a7fd Mon Sep 17 00:00:00 2001
724c96
From: Thomas Haller <thaller@redhat.com>
724c96
Date: Wed, 12 Aug 2020 16:57:02 +0200
724c96
Subject: [PATCH 7/7] rhel8: revert changes to translated strings in libnm/docs
724c96
724c96
---
724c96
 clients/common/settings-docs.h.in  | 2 +-
724c96
 libnm-core/nm-setting-connection.c | 9 +++++----
724c96
 2 files changed, 6 insertions(+), 5 deletions(-)
724c96
724c96
diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in
724c96
index 606a1b95c5df..7b891500d8c9 100644
724c96
--- a/clients/common/settings-docs.h.in
724c96
+++ b/clients/common/settings-docs.h.in
724c96
@@ -171,7 +171,7 @@
724c96
 #define DESCRIBE_DOC_NM_SETTING_CONNECTION_TIMESTAMP N_("The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved).")
724c96
 #define DESCRIBE_DOC_NM_SETTING_CONNECTION_TYPE N_("Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, \"802-3-ethernet\" or \"802-11-wireless\" or \"bluetooth\", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, \"vpn\" or \"bridge\", etc).")
724c96
 #define DESCRIBE_DOC_NM_SETTING_CONNECTION_UUID N_("A universally unique identifier for the connection, for example generated with libuuid.  It should be assigned when the connection is created, and never changed as long as the connection still applies to the same network.  For example, it should not be changed when the \"id\" property or NMSettingIP4Config changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband network provider, or \"type\" property changes. The UUID must be in the format \"2815492f-7e56-435e-b2e9-246bd7cdc664\" (ie, contains only hexadecimal characters and \"-\").")
724c96
-#define DESCRIBE_DOC_NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT N_("Timeout in milliseconds to wait for device at startup. During boot, devices may take a while to be detected by the driver. This property will cause to delay NetworkManager-wait-online.service and nm-online to give the device a chance to appear. This works by waiting for the given timeout until a compatible device for the profile is available and managed. The value 0 means no wait time. The default value is -1, which currently has the same meaning as no wait time.")
724c96
+#define DESCRIBE_DOC_NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT N_("Timeout in milliseconds to wait for device at startup. During boot, devices may take a while to be detected by the driver. This property will cause to delay NetworkManager-wait-online.service and nm-online to give the device a chance to appear. Note that this property only works together with NMSettingConnection:interface-name to identify the device that will be waited for. The value 0 means no wait time. The default value is -1, which currently has the same meaning as no wait time.")
724c96
 #define DESCRIBE_DOC_NM_SETTING_CONNECTION_ZONE N_("The trust level of a the connection.  Free form case-insensitive string (for example \"Home\", \"Work\", \"Public\").  NULL or unspecified zone means the connection will be placed in the default zone as defined by the firewall. When updating this property on a currently activated connection, the change takes effect immediately.")
724c96
 #define DESCRIBE_DOC_NM_SETTING_DCB_APP_FCOE_FLAGS N_("Specifies the NMSettingDcbFlags for the DCB FCoE application.  Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).")
724c96
 #define DESCRIBE_DOC_NM_SETTING_DCB_APP_FCOE_MODE N_("The FCoE controller mode; either \"fabric\" (default) or \"vn2vn\".")
724c96
diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c
724c96
index 03f8fb23c099..fd2309e76cc6 100644
724c96
--- a/libnm-core/nm-setting-connection.c
724c96
+++ b/libnm-core/nm-setting-connection.c
724c96
@@ -689,7 +689,7 @@ nm_setting_connection_is_slave_type (NMSettingConnection *setting,
724c96
  * @setting: the #NMSettingConnection
724c96
  *
724c96
  * Returns: the %NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT property with
724c96
- *   the timeout in milliseconds. -1 is the default.
724c96
+ *   the timeout in milli seconds. -1 is the default.
724c96
  *
724c96
  * Since: 1.20
724c96
  */
724c96
@@ -2300,9 +2300,10 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass)
724c96
 	 * Timeout in milliseconds to wait for device at startup.
724c96
 	 * During boot, devices may take a while to be detected by the driver.
724c96
 	 * This property will cause to delay NetworkManager-wait-online.service
724c96
-	 * and nm-online to give the device a chance to appear. This works by
724c96
-	 * waiting for the given timeout until a compatible device for the
724c96
-	 * profile is available and managed.
724c96
+	 * and nm-online to give the device a chance to appear.
724c96
+	 *
724c96
+	 * Note that this property only works together with NMSettingConnection:interface-name
724c96
+	 * to identify the device that will be waited for.
724c96
 	 *
724c96
 	 * The value 0 means no wait time. The default value is -1, which
724c96
 	 * currently has the same meaning as no wait time.
724c96
-- 
724c96
2.26.2
724c96