From adcc52c3daafd71d5687a54cc1d9d62653ddd4b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Hor=C3=A1k?= Date: Tue, 22 Oct 2019 11:18:09 +0200 Subject: [PATCH 1/5] initrd: use proper interface when adding s390 specific details The current solution for s390 specific details relies on an interface to exist before adding the s390 details. It means the ip= option must precede the rd.znet= option. Also only a single interface can be configured. With this change the s390 details are put to the right interface and properly named interface is created if it hasn't existed yet. --- src/initrd/nmi-cmdline-reader.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index b607c6da62..3a3227254a 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -688,16 +688,33 @@ parse_rd_znet (GHashTable *connections, char *argument) const char *nettype; const char *subchannels[4] = { 0, 0, 0, 0 }; const char *tmp; + const char *ifname, *prefix; + const char *bus_id; + size_t bus_id_len; + size_t bus_id_start; NMConnection *connection; NMSettingWired *s_wired; nettype = get_word (&argument, ','); subchannels[0] = get_word (&argument, ','); - subchannels[1] = get_word (&argument, ','); - if (!nm_streq0 (nettype, "ctc")) - subchannels[2] = get_word (&argument, ','); - connection = get_conn (connections, NULL, NM_SETTING_WIRED_SETTING_NAME); + /* The following logic is taken from names_ccw() in systemd/src/udev/udev-builtin-net_id.c */ + bus_id = subchannels[0]; + bus_id_len = strlen (bus_id); + bus_id_start = strspn (bus_id, ".0"); + bus_id += bus_id_start < bus_id_len ? bus_id_start : bus_id_len - 1; + + subchannels[1] = get_word (&argument, ','); + + if (nm_streq0 (nettype, "ctc")) { + prefix = "sl"; + } else { + subchannels[2] = get_word (&argument, ','); + prefix = "en"; + } + + ifname = g_strdup_printf ("%sc%s", prefix, bus_id); + connection = get_conn (connections, ifname, NM_SETTING_WIRED_SETTING_NAME); s_wired = nm_connection_get_setting_wired (connection); g_object_set (s_wired, NM_SETTING_WIRED_S390_NETTYPE, nettype, From c27f5030e9dd5ec9065de439bc43330e84e0c273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Hor=C3=A1k?= Date: Tue, 22 Oct 2019 11:56:41 +0200 Subject: [PATCH 2/5] initrd/tests: use a valid combination of device and interface name for testing --- src/initrd/tests/test-cmdline-reader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c index e6fcad4c11..05b98d7fe0 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -786,7 +786,7 @@ test_rd_znet (void) { gs_unref_hashtable GHashTable *connections = NULL; const char *const*const ARGV = NM_MAKE_STRV ("ip=10.11.12.13::10.11.12.1:24:foo.example.com:enc800:none", - "rd.znet=ctc,0.0.0800,0.0.0801,layer2=0,portno=1"); + "rd.znet=qeth,0.0.0800,0.0.0801,0.0.0802,layer2=0,portno=1"); GHashTableIter h_iter; NMConnection *connection; NMSettingWired *s_wired; @@ -815,7 +815,8 @@ test_rd_znet (void) g_assert (v_subchannels); g_assert_cmpstr (v_subchannels[0], ==, "0.0.0800"); g_assert_cmpstr (v_subchannels[1], ==, "0.0.0801"); - g_assert_cmpstr (v_subchannels[2], ==, NULL); + g_assert_cmpstr (v_subchannels[2], ==, "0.0.0802"); + g_assert_cmpstr (v_subchannels[3], ==, NULL); g_assert_cmpint (nm_setting_wired_get_num_s390_options (s_wired), ==, G_N_ELEMENTS (s390_options)); for (i_s390_options_keys = 0; i_s390_options_keys < G_N_ELEMENTS (s390_options); i_s390_options_keys++) { From c7423dca894caa6083f0160c61eaa5e3fa724efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Hor=C3=A1k?= Date: Tue, 22 Oct 2019 16:56:38 +0200 Subject: [PATCH 3/5] initrd: prepare interface in rd.znet only if persistent interface names are enabled When processing the rd.znet option set the interface name only in case when the persistent interface names feature isn't disabled via net.ifnames=0 [lkundrak@v3.sk: minor tweaks to the net.ifnames=0 parsing] --- src/initrd/nmi-cmdline-reader.c | 40 +++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index 3a3227254a..76abb2bb77 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -683,27 +683,18 @@ parse_rd_peerdns (GHashTable *connections, char *argument) } static void -parse_rd_znet (GHashTable *connections, char *argument) +parse_rd_znet (GHashTable *connections, char *argument, gboolean net_ifnames) { const char *nettype; const char *subchannels[4] = { 0, 0, 0, 0 }; const char *tmp; - const char *ifname, *prefix; - const char *bus_id; - size_t bus_id_len; - size_t bus_id_start; + gs_free char *ifname = NULL; + const char *prefix; NMConnection *connection; NMSettingWired *s_wired; nettype = get_word (&argument, ','); subchannels[0] = get_word (&argument, ','); - - /* The following logic is taken from names_ccw() in systemd/src/udev/udev-builtin-net_id.c */ - bus_id = subchannels[0]; - bus_id_len = strlen (bus_id); - bus_id_start = strspn (bus_id, ".0"); - bus_id += bus_id_start < bus_id_len ? bus_id_start : bus_id_len - 1; - subchannels[1] = get_word (&argument, ','); if (nm_streq0 (nettype, "ctc")) { @@ -713,7 +704,20 @@ parse_rd_znet (GHashTable *connections, char *argument) prefix = "en"; } - ifname = g_strdup_printf ("%sc%s", prefix, bus_id); + if (net_ifnames == TRUE) { + const char *bus_id; + size_t bus_id_len; + size_t bus_id_start; + + /* The following logic is taken from names_ccw() in systemd/src/udev/udev-builtin-net_id.c */ + bus_id = subchannels[0]; + bus_id_len = strlen (bus_id); + bus_id_start = strspn (bus_id, ".0"); + bus_id += bus_id_start < bus_id_len ? bus_id_start : bus_id_len - 1; + + ifname = g_strdup_printf ("%sc%s", prefix, bus_id); + } + connection = get_conn (connections, ifname, NM_SETTING_WIRED_SETTING_NAME); s_wired = nm_connection_get_setting_wired (connection); g_object_set (s_wired, @@ -752,10 +756,18 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) gboolean ignore_bootif = FALSE; gboolean neednet = FALSE; gs_free char *bootif_val = NULL; + gboolean net_ifnames = TRUE; int i; connections = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_object_unref); + for (i = 0; argv[i]; i++) { + if (strcmp (argv[i], "net.ifnames=0") == 0) + net_ifnames = FALSE; + else if (g_str_has_prefix (argv[i], "net.ifnames=")) + net_ifnames = TRUE; + } + for (i = 0; argv[i]; i++) { gs_free char *argument_clone = NULL; char *argument; @@ -787,7 +799,7 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) else if (strcmp (tag, "rd.neednet") == 0) neednet = _nm_utils_ascii_str_to_bool (argument, TRUE); else if (strcmp (tag, "rd.znet") == 0) - parse_rd_znet (connections, argument); + parse_rd_znet (connections, argument, net_ifnames); else if (strcasecmp (tag, "BOOTIF") == 0) { nm_clear_g_free (&bootif_val); bootif_val = g_strdup (argument); From 22e388d90e4ffbddbe44cfaef0c3e15782e5576a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Hor=C3=A1k?= Date: Wed, 23 Oct 2019 11:56:47 +0200 Subject: [PATCH 4/5] initrd: handle rd.znet with legacy interface names Handle rd.znet with legacy interface names too, the index for eth or ctc corresponds to the position on the command line. --- src/initrd/nmi-cmdline-reader.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index 76abb2bb77..a4f4687651 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -692,16 +692,29 @@ parse_rd_znet (GHashTable *connections, char *argument, gboolean net_ifnames) const char *prefix; NMConnection *connection; NMSettingWired *s_wired; + static int count_ctc = 0; + static int count_eth = 0; + int index; nettype = get_word (&argument, ','); subchannels[0] = get_word (&argument, ','); subchannels[1] = get_word (&argument, ','); if (nm_streq0 (nettype, "ctc")) { - prefix = "sl"; + if (net_ifnames == TRUE) { + prefix = "sl"; + } else { + prefix = "ctc"; + index = count_ctc++; + } } else { subchannels[2] = get_word (&argument, ','); - prefix = "en"; + if (net_ifnames == TRUE) { + prefix = "en"; + } else { + prefix = "eth"; + index = count_eth++; + } } if (net_ifnames == TRUE) { @@ -716,6 +729,8 @@ parse_rd_znet (GHashTable *connections, char *argument, gboolean net_ifnames) bus_id += bus_id_start < bus_id_len ? bus_id_start : bus_id_len - 1; ifname = g_strdup_printf ("%sc%s", prefix, bus_id); + } else { + ifname = g_strdup_printf ("%s%d", prefix, index); } connection = get_conn (connections, ifname, NM_SETTING_WIRED_SETTING_NAME); From 927ae6d92787131420de7192b1d68141b800ece0 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 4 Nov 2019 16:18:24 +0100 Subject: [PATCH 5/5] initrd/tests: test that we generate the s390 interface names correctly --- src/initrd/tests/test-cmdline-reader.c | 83 ++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 10 deletions(-) diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c index 05b98d7fe0..a69c374147 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -786,9 +786,10 @@ test_rd_znet (void) { gs_unref_hashtable GHashTable *connections = NULL; const char *const*const ARGV = NM_MAKE_STRV ("ip=10.11.12.13::10.11.12.1:24:foo.example.com:enc800:none", - "rd.znet=qeth,0.0.0800,0.0.0801,0.0.0802,layer2=0,portno=1"); - GHashTableIter h_iter; + "rd.znet=qeth,0.0.0800,0.0.0801,0.0.0802,layer2=0,portno=1", + "rd.znet=ctc,0.0.0600,0.0.0601,layer2=0,portno=0"); NMConnection *connection; + NMSettingConnection *s_con; NMSettingWired *s_wired; const char *const*v_subchannels; const NMUtilsNamedValue s390_options[] = { @@ -799,15 +800,17 @@ test_rd_znet (void) connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV); g_assert (connections); - g_assert_cmpint (g_hash_table_size (connections), ==, 1); - - g_hash_table_iter_init (&h_iter, connections); - if (!g_hash_table_iter_next (&h_iter, NULL, (gpointer *) &connection)) - g_assert_not_reached (); - if (g_hash_table_iter_next (&h_iter, NULL, NULL)) - g_assert_not_reached (); + g_assert_cmpint (g_hash_table_size (connections), ==, 2); + connection = g_hash_table_lookup (connections, "enc800"); g_assert (NM_IS_CONNECTION (connection)); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (NM_IS_SETTING_CONNECTION (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), ==, "enc800"); + g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "enc800"); + s_wired = nm_connection_get_setting_wired (connection); g_assert (NM_IS_SETTING_WIRED (s_wired)); @@ -839,8 +842,67 @@ test_rd_znet (void) } nmtst_assert_connection_verifies_without_normalization (connection); + + connection = g_hash_table_lookup (connections, "slc600"); + g_assert (NM_IS_CONNECTION (connection)); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (NM_IS_SETTING_CONNECTION (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), ==, "slc600"); + g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "slc600"); + + s_wired = nm_connection_get_setting_wired (connection); + g_assert (NM_IS_SETTING_WIRED (s_wired)); + + v_subchannels = nm_setting_wired_get_s390_subchannels (s_wired); + g_assert (v_subchannels); + g_assert_cmpstr (v_subchannels[0], ==, "0.0.0600"); + g_assert_cmpstr (v_subchannels[1], ==, "0.0.0601"); + g_assert_cmpstr (v_subchannels[2], ==, NULL); + + nmtst_assert_connection_verifies_without_normalization (connection); } +static void +test_rd_znet_legacy (void) +{ + gs_unref_hashtable GHashTable *connections = NULL; + const char *const*const ARGV = NM_MAKE_STRV ("ip=10.11.12.13::10.11.12.1:24:foo.example.com:eth0:none", + "rd.znet=qeth,0.0.0800,0.0.0801,0.0.0802,layer2=0,portno=1", + "rd.znet=ctc,0.0.0600,0.0.0601,layer2=0,portno=0", + "net.ifnames=0"); + NMConnection *connection; + NMSettingConnection *s_con; + + connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV); + g_assert (connections); + g_assert_cmpint (g_hash_table_size (connections), ==, 2); + + connection = g_hash_table_lookup (connections, "eth0"); + g_assert (NM_IS_CONNECTION (connection)); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (NM_IS_SETTING_CONNECTION (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), ==, "eth0"); + g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "eth0"); + + nmtst_assert_connection_verifies_without_normalization (connection); + + connection = g_hash_table_lookup (connections, "ctc0"); + g_assert (NM_IS_CONNECTION (connection)); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (NM_IS_SETTING_CONNECTION (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), ==, "ctc0"); + g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "ctc0"); + + nmtst_assert_connection_verifies_without_normalization (connection); +} + + NMTST_DEFINE (); int main (int argc, char **argv) @@ -863,7 +925,8 @@ int main (int argc, char **argv) g_test_add_func ("/initrd/cmdline/bridge/default", test_bridge_default); g_test_add_func ("/initrd/cmdline/ibft", test_ibft); g_test_add_func ("/initrd/cmdline/ignore_extra", test_ignore_extra); - g_test_add_func ("/initrd/cmdline/rd_zdnet", test_rd_znet); + g_test_add_func ("/initrd/cmdline/rd_znet", test_rd_znet); + g_test_add_func ("/initrd/cmdline/rd_znet/legacy", test_rd_znet_legacy); return g_test_run (); }