From deff651704cf46e6860bb7dd7af91b257ed7b52a 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. (cherry picked from commit adcc52c3daafd71d5687a54cc1d9d62653ddd4b7) --- 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 8ae6aa3685..9c927c44b3 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -695,16 +695,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 31d44a28e13ecf9a4f355a927ea567ea926e435a 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 (cherry picked from commit c27f5030e9dd5ec9065de439bc43330e84e0c273) --- 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 a8a6e82527..ed6a928fc3 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -801,7 +801,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; @@ -830,7 +830,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 72fcf35cb62294ad566effd98dd0abf97a62482a 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] (cherry picked from commit c7423dca894caa6083f0160c61eaa5e3fa724efd) --- 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 9c927c44b3..0614fee1e2 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -690,27 +690,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")) { @@ -720,7 +711,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, @@ -759,10 +763,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; @@ -794,7 +806,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 56026dd3dd3a8c7a81e7a81b3f3d2d2e822dcd27 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. (cherry picked from commit 22e388d90e4ffbddbe44cfaef0c3e15782e5576a) --- 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 0614fee1e2..b90ee2038d 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -699,16 +699,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) { @@ -723,6 +736,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 4c7d12cb29ee77b5573f85b1eaeb3ba8f53eca9a 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 (cherry picked from commit 927ae6d92787131420de7192b1d68141b800ece0) --- 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 ed6a928fc3..5ac82f5029 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -801,9 +801,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[] = { @@ -814,15 +815,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)); @@ -854,8 +857,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) @@ -878,7 +940,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 (); }