From 02adbf5124c657850b8d448d5fa7e0fe1c1b8407 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 13 Oct 2021 15:02:56 +0200 Subject: [PATCH] initrd: handle ip=dhcp,dhcp6 specially With "ip=dhcp,dhcp6" the legacy dracut module does first DHCPv4 and then IPv6 autoconf (even if DHCPv4 succeeded) [1]. In this way, there is the guarantee that an address family is always configured if the network supports it. Currently "ip=dhcp,dhcp6" is treated a bit differently by NM, which generates a connection with only ipv4.required-timeout=20s. Therefore it's possible that NM in initrd quits (or signals startup-complete) without an IPv6 even if the network is configured for IPv6. Make NM's behavior similar to the legacy module by also setting an ipv6.required-timeout for "ip=dhcp,dhcp6". Note that if the command line contains "rd.neednet=1" without an "ip=" argument, we still generate a default connection with IPv4 preferred over IPv6 (i.e. only ipv4.required-timeout set). That's similar to what the legacy module does [2]. See [3] for a description of different scenarios for "rd.neednet=1". [1] https://github.com/dracutdevs/dracut/blob/055/modules.d/35network-legacy/ifup.sh#L459-L484 [2] https://github.com/dracutdevs/dracut/blob/055/modules.d/35network-legacy/ifup.sh#L529-L537 [3] https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/729 https://bugzilla.redhat.com/show_bug.cgi?id=1961666 https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/994 (cherry picked from commit 28770eb394e64fb1a5553f55bfc2ba8d0f6fb573) --- src/nm-initrd-generator/nmi-cmdline-reader.c | 12 ++++++++++++ src/nm-initrd-generator/tests/test-cmdline-reader.c | 8 +++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/nm-initrd-generator/nmi-cmdline-reader.c b/src/nm-initrd-generator/nmi-cmdline-reader.c index a85013360d..249f53de41 100644 --- a/src/nm-initrd-generator/nmi-cmdline-reader.c +++ b/src/nm-initrd-generator/nmi-cmdline-reader.c @@ -443,6 +443,8 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) "on" "any", "dhcp6", + "dhcp,dhcp6", + "dhcp6,dhcp", "auto", "auto6", "link6", @@ -631,6 +633,16 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NULL); } + } else if (NM_IN_STRSET(kind, "dhcp,dhcp6", "dhcp6,dhcp")) { + /* Both DHCPv4 and IPv6 autoconf are enabled, and + * each of them is tried for at least IP_REQUIRED_TIMEOUT_MSEC, + * even if the other one completes before. + */ + clear_ip4_required_timeout = FALSE; + g_object_set(s_ip6, + NM_SETTING_IP_CONFIG_REQUIRED_TIMEOUT, + NMI_IP_REQUIRED_TIMEOUT_MSEC, + NULL); } else if (nm_streq0(kind, "link6")) { g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, diff --git a/src/nm-initrd-generator/tests/test-cmdline-reader.c b/src/nm-initrd-generator/tests/test-cmdline-reader.c index e2a37c5835..e33918f98d 100644 --- a/src/nm-initrd-generator/tests/test-cmdline-reader.c +++ b/src/nm-initrd-generator/tests/test-cmdline-reader.c @@ -300,7 +300,7 @@ test_dhcp_timeout(void) static void test_if_auto_with_mtu(void) { - const char *const *ARGV = NM_MAKE_STRV("ip=eth0:auto:1666", "="); + const char *const *ARGV = NM_MAKE_STRV("ip=eth0:dhcp,dhcp6:1666", "="); gs_unref_object NMConnection *connection = NULL; NMSettingConnection * s_con; NMSettingWired * s_wired; @@ -324,11 +324,17 @@ test_if_auto_with_mtu(void) g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); g_assert_cmpint(nm_setting_ip_config_get_dhcp_timeout(s_ip4), ==, 90); + g_assert_cmpint(nm_setting_ip_config_get_required_timeout(s_ip4), + ==, + NMI_IP_REQUIRED_TIMEOUT_MSEC); s_ip6 = nm_connection_get_setting_ip6_config(connection); g_assert(s_ip6); g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); + g_assert_cmpint(nm_setting_ip_config_get_required_timeout(s_ip6), + ==, + NMI_IP_REQUIRED_TIMEOUT_MSEC); } static void