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 28770eb394)
This commit is contained in:
Beniamino Galvani 2021-10-13 15:02:56 +02:00
parent 77a2a53e8a
commit 02adbf5124
2 changed files with 19 additions and 1 deletions

View file

@ -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,

View file

@ -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