From 0ae9e9ec5eddbfd34f073a60819e02aa648e312c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 22 Jul 2020 12:24:59 +0200 Subject: [PATCH 1/4] shared: add nm_strv_ptrarray_ensure() and nm_strv_ptrarray_find_first() helpers (cherry picked from commit 99296d4c6caee60065286210f1f5fb4d653861bd) --- shared/nm-glib-aux/nm-shared-utils.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h index 34737e61a3..d1347c63bf 100644 --- a/shared/nm-glib-aux/nm-shared-utils.h +++ b/shared/nm-glib-aux/nm-shared-utils.h @@ -1776,6 +1776,17 @@ GSource *nm_utils_g_main_context_create_integrate_source (GMainContext *internal /*****************************************************************************/ +static inline GPtrArray * +nm_strv_ptrarray_ensure (GPtrArray **p_arr) +{ + nm_assert (p_arr); + + if (G_UNLIKELY (!*p_arr)) + *p_arr = g_ptr_array_new_with_free_func (g_free); + + return *p_arr; +} + static inline void nm_strv_ptrarray_add_string_take (GPtrArray *cmd, char *str) @@ -1814,6 +1825,22 @@ nm_strv_ptrarray_take_gstring (GPtrArray *cmd, FALSE)); } +static inline gssize +nm_strv_ptrarray_find_first (const GPtrArray *strv, + const char *str) +{ + if (!strv) + return -1; + return nm_utils_strv_find_first ((char **) strv->pdata, strv->len, str); +} + +static inline gboolean +nm_strv_ptrarray_contains (const GPtrArray *strv, + const char *str) +{ + return nm_strv_ptrarray_find_first (strv, str) >= 0; +} + /*****************************************************************************/ int nm_utils_getpagesize (void); From d7361496a207b3476c0da34e7dcc08394914b9a7 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 19 Nov 2020 11:06:04 +0100 Subject: [PATCH 2/4] initrd: add test for prefixed address in ip= argument (cherry picked from commit 584e9048b3dd7e8c550e56d2da5398516398be0f) (cherry picked from commit 58a6697e96b19707b0bd07e11c2c646982739e95) --- src/initrd/tests/test-cmdline-reader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c index 540b7bca8b..68b1ed441c 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -383,7 +383,7 @@ static void test_multiple_merge (void) { gs_unref_hashtable GHashTable *connections = NULL; - const char *const*ARGV = NM_MAKE_STRV ("ip=192.0.2.2:::::eth0", + const char *const*ARGV = NM_MAKE_STRV ("ip=192.0.2.2/16:::::eth0", "ip=[2001:db8::2]:::56::eth0"); NMConnection *connection; NMSettingConnection *s_con; @@ -418,6 +418,7 @@ test_multiple_merge (void) ip_addr = nm_setting_ip_config_get_address (s_ip4, 0); g_assert (ip_addr); g_assert_cmpstr (nm_ip_address_get_address (ip_addr), ==, "192.0.2.2"); + g_assert_cmpint (nm_ip_address_get_prefix (ip_addr), ==, 16); s_ip6 = nm_connection_get_setting_ip6_config (connection); g_assert (s_ip6); From a2ce810b87981f586e4acb993f7658c1da06b67e Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Tue, 17 Nov 2020 11:10:54 +0100 Subject: [PATCH 3/4] initrd: fix parsing of ip= argument with dotted interface name The command line parser looks for a dot or a colon to determine whether the first token in a ip= argument is a IPv4 address (dot), an IPv6 address (colon) or an interface name (none). This strategy doesn't work for interface names containing a dot (typically VLANs). Instead, try to parse the IPv4/IPv6 address in the token; if this fails then consider the token as an interface name. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/581 (cherry picked from commit 4aa902ecf537fbf14fd483a336b83b2139025681) (cherry picked from commit f766b3cbae0db7e3b7421bfdffc1d6182717e05c) --- src/initrd/nm-initrd-generator.h | 24 ++++++++----- src/initrd/nmi-cmdline-reader.c | 39 +++++++++----------- src/initrd/nmi-ibft-reader.c | 4 +-- src/initrd/tests/test-cmdline-reader.c | 49 ++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 34 deletions(-) diff --git a/src/initrd/nm-initrd-generator.h b/src/initrd/nm-initrd-generator.h index 8e17f04555..e7647edd7f 100644 --- a/src/initrd/nm-initrd-generator.h +++ b/src/initrd/nm-initrd-generator.h @@ -11,17 +11,23 @@ #define NMI_WAIT_DEVICE_TIMEOUT_MS 60000 -static inline gboolean -guess_ip_address_family (const char *str) +static inline int +get_ip_address_family (const char *str, gboolean with_prefix) { - if (str == NULL) - return AF_UNSPEC; - else if (strchr (str, '.')) - return AF_INET; - else if (strchr (str, ':')) - return AF_INET6; - else + int addr_family; + + if (!str) return AF_UNSPEC; + + if (with_prefix) { + if (nm_utils_parse_inaddr_prefix_bin (AF_UNSPEC, str, &addr_family, NULL, NULL)) + return addr_family; + } else { + if (nm_utils_parse_inaddr_bin (AF_UNSPEC, str, &addr_family, NULL)) + return addr_family; + } + + return AF_UNSPEC; } GHashTable *nmi_ibft_read (const char *sysfs_dir); diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index 316d7930fd..73002b7e21 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -385,7 +385,7 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument) /* ip={dhcp|on|any|dhcp6|auto6|ibft} */ kind = tmp; } else { - client_ip_family = guess_ip_address_family (tmp); + client_ip_family = get_ip_address_family (tmp, TRUE); if (client_ip_family != AF_UNSPEC) { /* :[]:::: */ client_ip = tmp; @@ -411,11 +411,11 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument) kind = get_word (&argument, ':'); tmp = get_word (&argument, ':'); - dns_addr_family[0] = guess_ip_address_family (tmp); + dns_addr_family[0] = get_ip_address_family (tmp, FALSE); if (dns_addr_family[0] != AF_UNSPEC) { dns[0] = tmp; dns[1] = get_word (&argument, ':'); - dns_addr_family[1] = guess_ip_address_family (dns[1]); + dns_addr_family[1] = get_ip_address_family (dns[1], FALSE); if (*argument) _LOGW (LOGD_CORE, "Ignoring extra: '%s'.", argument); } else { @@ -475,9 +475,8 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument) _LOGW (LOGD_CORE, "Invalid address '%s': %s", client_ip, error->message); g_clear_error (&error); } - } else { - _LOGW (LOGD_CORE, "Unrecognized address: %s", client_ip); - } + } else + nm_assert_not_reached (); if (address) { switch (client_ip_family) { @@ -496,7 +495,7 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument) nm_setting_ip_config_add_address (s_ip6, address); break; default: - _LOGW (LOGD_CORE, "Unknown address family: %s", client_ip); + nm_assert_not_reached (); break; } nm_ip_address_unref (address); @@ -579,22 +578,16 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument) _LOGW (LOGD_CORE, "Ignoring peer: %s (not implemented)\n", peer); if (gateway_ip && *gateway_ip) { - int addr_family = guess_ip_address_family (gateway_ip); - - if (nm_utils_ipaddr_is_valid (addr_family, gateway_ip)) { - switch (addr_family) { - case AF_INET: - g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL); - break; - case AF_INET6: - g_object_set (s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL); - break; - default: - _LOGW (LOGD_CORE, "Unknown address family: %s", gateway_ip); - break; - } - } else { + switch (get_ip_address_family (gateway_ip, FALSE)) { + case AF_INET: + g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL); + break; + case AF_INET6: + g_object_set (s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL); + break; + default: _LOGW (LOGD_CORE, "Invalid gateway: %s", gateway_ip); + break; } } @@ -893,7 +886,7 @@ reader_add_nameservers (Reader *reader, GPtrArray *nameservers) for (i = 0; i < nameservers->len; i++) { ns = nameservers->pdata[i]; - addr_family = guess_ip_address_family (ns); + addr_family = get_ip_address_family (ns, FALSE); if (addr_family == AF_UNSPEC) { _LOGW (LOGD_CORE, "Unknown address family: %s", ns); continue; diff --git a/src/initrd/nmi-ibft-reader.c b/src/initrd/nmi-ibft-reader.c index fe6f6432a4..bdb99e67ef 100644 --- a/src/initrd/nmi-ibft-reader.c +++ b/src/initrd/nmi-ibft-reader.c @@ -162,9 +162,9 @@ ip_setting_add_from_block (GHashTable *nic, NULL); } - family = guess_ip_address_family (s_ipaddr); + family = get_ip_address_family (s_ipaddr, FALSE); if (family == AF_UNSPEC) - family = guess_ip_address_family (s_gateway); + family = get_ip_address_family (s_gateway, FALSE); switch (family) { case AF_INET: diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c index 68b1ed441c..81a7fe2410 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -1107,6 +1107,54 @@ test_team (void) g_assert_cmpint (nm_setting_connection_get_multi_connect (s_con), ==, NM_CONNECTION_MULTI_CONNECT_SINGLE); } +static void +test_vlan (void) +{ + const char *const *ARGV0 = NM_MAKE_STRV ("ip=eth0.100:dhcp", "vlan=eth0.100:eth0"); + const char *const *ARGV1 = NM_MAKE_STRV ("vlan=eth0.100:eth0", "ip=eth0.100:dhcp"); + const char *const *ARGV[] = {ARGV0, ARGV1}; + guint i; + + for (i = 0; i < G_N_ELEMENTS (ARGV); i++) { + gs_unref_hashtable GHashTable *connections = NULL; + NMConnection *connection; + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; + NMSettingVlan *s_vlan; + gs_free char *hostname = NULL; + + connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV[i], &hostname); + g_assert (connections); + g_assert_cmpint (g_hash_table_size (connections), ==, 1); + g_assert_cmpstr (hostname, ==, NULL); + + connection = g_hash_table_lookup (connections, "eth0.100"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + g_assert_cmpstr (nm_connection_get_connection_type (connection), + ==, + NM_SETTING_VLAN_SETTING_NAME); + g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth0.100"); + + s_vlan = nm_connection_get_setting_vlan (connection); + g_assert (s_vlan); + g_assert_cmpstr (nm_setting_vlan_get_parent (s_vlan), ==, "eth0"); + g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 100); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip4); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), + ==, + NM_SETTING_IP4_CONFIG_METHOD_AUTO); + + 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); + } +} + static void test_ibft_ip_dev (void) { @@ -1719,6 +1767,7 @@ int main (int argc, char **argv) g_test_add_func ("/initrd/cmdline/bond/ip", test_bond_ip); g_test_add_func ("/initrd/cmdline/bond/default", test_bond_default); g_test_add_func ("/initrd/cmdline/team", test_team); + g_test_add_func ("/initrd/cmdline/vlan", test_vlan); g_test_add_func ("/initrd/cmdline/bridge", test_bridge); g_test_add_func ("/initrd/cmdline/bridge/default", test_bridge_default); g_test_add_func ("/initrd/cmdline/bridge/ip", test_bridge_ip); From 6e4345baac776a1b715a4173539171d4ecdd07af Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 18 Nov 2020 14:27:19 +0100 Subject: [PATCH 4/4] initrd: disable ipv4 and ipv6 by default for vlan parent connection Change the generator to disable by default IP configuration for the parent connection of a VLAN, because that is what a user would expect and what the legacy module does. Of course if the user explicitly configures DHCP or an address for the parent interface, that overrides the default. Note that now the generator always creates a connection for the parent interface. Before this commit, it did only when there was an explicit ip= argument for the parent interface. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/509 (cherry picked from commit f2e51ace6815bd1bd264101694b8dc65226ddd90) (cherry picked from commit 4b0007b0370badc2fcefe529a6e680e8ffe2d9e7) --- src/initrd/nmi-cmdline-reader.c | 40 ++++- src/initrd/tests/test-cmdline-reader.c | 198 ++++++++++++++++++++++++- 2 files changed, 232 insertions(+), 6 deletions(-) diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index 73002b7e21..fcced3fe20 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -21,6 +21,8 @@ typedef struct { GHashTable *hash; GPtrArray *array; + GPtrArray *vlan_parents; + GHashTable *explicit_ip_connections; NMConnection *bootdev_connection; /* connection for bootdev=$ifname */ NMConnection *default_connection; /* connection not bound to any ifname */ char *hostname; @@ -38,7 +40,9 @@ reader_new (void) reader = g_slice_new (Reader); *reader = (Reader) { - .hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_object_unref), + .hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_object_unref), + .explicit_ip_connections = g_hash_table_new_full (nm_direct_hash, NULL, g_object_unref, NULL), + .vlan_parents = g_ptr_array_new_with_free_func (g_free), .array = g_ptr_array_new (), }; @@ -51,6 +55,8 @@ reader_destroy (Reader *reader, gboolean free_hash) gs_unref_hashtable GHashTable *hash = NULL; g_ptr_array_unref (reader->array); + g_ptr_array_unref (reader->vlan_parents); + g_hash_table_unref (reader->explicit_ip_connections); hash = g_steal_pointer (&reader->hash); nm_clear_g_free (&reader->hostname); nm_clear_g_free (&reader->dhcp4_vci); @@ -436,6 +442,8 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument) else connection = reader_get_default_connection (reader); + g_hash_table_add (reader->explicit_ip_connections, g_object_ref (connection)); + s_ip4 = nm_connection_get_setting_ip4_config (connection); s_ip6 = nm_connection_get_setting_ip6_config (connection); @@ -789,6 +797,9 @@ reader_parse_vlan (Reader *reader, char *argument) if (argument && *argument) _LOGW (LOGD_CORE, "Ignoring extra: '%s'.", argument); + + if (!nm_strv_ptrarray_contains (reader->vlan_parents, phy)) + g_ptr_array_add (reader->vlan_parents, g_strdup (phy)); } static void @@ -1031,6 +1042,33 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv, char ** } } + for (i = 0; i < reader->vlan_parents->len; i++) { + NMConnection *connection; + NMSettingIPConfig *s_ip; + + /* Disable IP configuration for parent connections of VLANs, + * unless those interfaces were explicitly configured otherwise. */ + + connection = reader_get_connection (reader, reader->vlan_parents->pdata[i], NULL, TRUE); + if (!g_hash_table_contains (reader->explicit_ip_connections, connection)) { + s_ip = nm_connection_get_setting_ip4_config (connection); + if (s_ip) { + g_object_set (s_ip, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_DISABLED, + NULL); + } + + s_ip = nm_connection_get_setting_ip6_config (connection); + if (s_ip) { + g_object_set (s_ip, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP6_CONFIG_METHOD_DISABLED, + NULL); + } + } + } + if (ignore_bootif) nm_clear_g_free (&bootif_val); if (bootif_val) { diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c index 81a7fe2410..c3fbc5ba4a 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -482,7 +482,7 @@ test_bootdev (void) connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname); g_assert (connections); - g_assert_cmpint (g_hash_table_size (connections), ==, 2); + g_assert_cmpint (g_hash_table_size (connections), ==, 3); g_assert_cmpstr (hostname, ==, NULL); connection = g_hash_table_lookup (connections, "ens3"); @@ -505,6 +505,18 @@ test_bootdev (void) g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_VLAN_SETTING_NAME); g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "vlan2"); g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "vlan2"); + + connection = g_hash_table_lookup (connections, "ens5"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), + ==, + NM_SETTING_WIRED_SETTING_NAME); + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "ens5"); + g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "ens5"); } static void @@ -1125,13 +1137,14 @@ test_vlan (void) connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV[i], &hostname); g_assert (connections); - g_assert_cmpint (g_hash_table_size (connections), ==, 1); + g_assert_cmpint (g_hash_table_size (connections), ==, 2); g_assert_cmpstr (hostname, ==, NULL); + /* VLAN eth0.100 */ connection = g_hash_table_lookup (connections, "eth0.100"); g_assert (connection); nmtst_assert_connection_verifies_without_normalization (connection); - g_assert_cmpstr (nm_connection_get_connection_type (connection), + g_assert_cmpstr (nm_connection_get_connection_type(connection), ==, NM_SETTING_VLAN_SETTING_NAME); g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth0.100"); @@ -1144,14 +1157,187 @@ test_vlan (void) s_ip4 = nm_connection_get_setting_ip4_config (connection); g_assert (s_ip4); g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), - ==, - NM_SETTING_IP4_CONFIG_METHOD_AUTO); + ==, + NM_SETTING_IP4_CONFIG_METHOD_AUTO); 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); + + /* Ethernet eth0 */ + connection = g_hash_table_lookup (connections, "eth0"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + g_assert_cmpstr (nm_connection_get_connection_type (connection), + ==, + NM_SETTING_WIRED_SETTING_NAME); + g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth0"); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip4); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), + ==, + NM_SETTING_IP4_CONFIG_METHOD_DISABLED); + + 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_DISABLED); + } +} + +static void +test_vlan_with_dhcp_on_parent (void) +{ + const char *const *ARGV0 = NM_MAKE_STRV ("vlan=eth0.100:eth0", "ip=eth0:dhcp"); + const char *const *ARGV1 = NM_MAKE_STRV ("ip=eth0:dhcp", "vlan=eth0.100:eth0"); + const char *const *ARGV[] = {ARGV0, ARGV1}; + guint i; + + for (i = 0; i < G_N_ELEMENTS (ARGV); i++) { + gs_unref_hashtable GHashTable *connections = NULL; + NMConnection *connection; + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; + NMSettingVlan *s_vlan; + gs_free char *hostname = NULL; + + connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV[i], &hostname); + g_assert (connections); + g_assert_cmpint (g_hash_table_size (connections), ==, 2); + g_assert_cmpstr (hostname, ==, NULL); + + /* VLAN eth0.100 */ + connection = g_hash_table_lookup (connections, "eth0.100"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + g_assert_cmpstr (nm_connection_get_connection_type (connection), + ==, + NM_SETTING_VLAN_SETTING_NAME); + g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth0.100"); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip4); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), + ==, + NM_SETTING_IP4_CONFIG_METHOD_AUTO); + + 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); + + s_vlan = nm_connection_get_setting_vlan (connection); + g_assert (s_vlan); + g_assert_cmpstr (nm_setting_vlan_get_parent (s_vlan), ==, "eth0"); + g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 100); + + /* Ethernet eth0 */ + connection = g_hash_table_lookup (connections, "eth0"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + g_assert_cmpstr (nm_connection_get_connection_type (connection), + ==, + NM_SETTING_WIRED_SETTING_NAME); + g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth0"); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip4); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), + ==, + NM_SETTING_IP4_CONFIG_METHOD_AUTO); + + 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); + } +} + +static void +test_vlan_over_bond (void) +{ + const char *const *ARGV0 = NM_MAKE_STRV ("ip=1.2.3.4:::24::vlan1:none", + "bond=bond2:ens3,ens4:mode=active-backup", + "vlan=vlan1:bond2"); + const char *const *ARGV1 = NM_MAKE_STRV ("vlan=vlan1:bond2", + "ip=1.2.3.4:::24::vlan1:none", + "bond=bond2:ens3,ens4:mode=active-backup"); + const char *const *ARGV2 = NM_MAKE_STRV ("bond=bond2:ens3,ens4:mode=active-backup", + "ip=1.2.3.4:::24::vlan1:none", + "vlan=vlan1:bond2"); + const char *const *ARGV[] = {ARGV0, ARGV1, ARGV2}; + guint i; + + for (i = 0; i < G_N_ELEMENTS (ARGV); i++) { + gs_unref_hashtable GHashTable *connections = NULL; + NMConnection *connection; + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; + NMSettingVlan *s_vlan; + gs_free char *hostname = NULL; + + connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV[i], &hostname); + g_assert (connections); + g_assert_cmpint (g_hash_table_size (connections), ==, 4); + g_assert_cmpstr (hostname, ==, NULL); + + /* VLAN vlan1 */ + connection = g_hash_table_lookup (connections, "vlan1"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + g_assert_cmpstr (nm_connection_get_connection_type (connection), + ==, + NM_SETTING_VLAN_SETTING_NAME); + g_assert_cmpstr (nm_connection_get_id (connection), ==, "vlan1"); + + s_ip4 = nm_connection_get_setting_ip4_config(connection); + g_assert (s_ip4); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), + ==, + NM_SETTING_IP4_CONFIG_METHOD_MANUAL); + + 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_DISABLED); + s_vlan = nm_connection_get_setting_vlan (connection); + g_assert (s_vlan); + g_assert_cmpstr(nm_setting_vlan_get_parent (s_vlan), ==, "bond2"); + g_assert_cmpint(nm_setting_vlan_get_id (s_vlan), ==, 1); + + /* Bond bond2 */ + connection = g_hash_table_lookup (connections, "bond2"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + g_assert_cmpstr (nm_connection_get_connection_type (connection), + ==, + NM_SETTING_BOND_SETTING_NAME); + g_assert_cmpstr(nm_connection_get_id (connection), ==, "bond2"); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip4); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), + ==, + NM_SETTING_IP4_CONFIG_METHOD_DISABLED); + + 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_DISABLED); + + /* Ethernet ens3 and ens4 */ + connection = g_hash_table_lookup (connections, "ens3"); + g_assert (connection); + connection = g_hash_table_lookup (connections, "ens4"); + g_assert (connection); } } @@ -1768,6 +1954,8 @@ int main (int argc, char **argv) g_test_add_func ("/initrd/cmdline/bond/default", test_bond_default); g_test_add_func ("/initrd/cmdline/team", test_team); g_test_add_func ("/initrd/cmdline/vlan", test_vlan); + g_test_add_func ("/initrd/cmdline/vlan/dhcp-on-parent", test_vlan_with_dhcp_on_parent); + g_test_add_func ("/initrd/cmdline/vlan/over-bond", test_vlan_over_bond); g_test_add_func ("/initrd/cmdline/bridge", test_bridge); g_test_add_func ("/initrd/cmdline/bridge/default", test_bridge_default); g_test_add_func ("/initrd/cmdline/bridge/ip", test_bridge_ip);