diff options
Diffstat (limited to 'src/nm-initrd-generator')
| -rw-r--r-- | src/nm-initrd-generator/nmi-cmdline-reader.c | 249 | ||||
| -rw-r--r-- | src/nm-initrd-generator/tests/test-cmdline-reader.c | 302 |
2 files changed, 312 insertions, 239 deletions
diff --git a/src/nm-initrd-generator/nmi-cmdline-reader.c b/src/nm-initrd-generator/nmi-cmdline-reader.c index a8501336..8fafb08f 100644 --- a/src/nm-initrd-generator/nmi-cmdline-reader.c +++ b/src/nm-initrd-generator/nmi-cmdline-reader.c @@ -364,7 +364,7 @@ reader_read_all_connections_from_fw(Reader *reader, const char *sysfs_dir) gs_free const char ** keys = NULL; ibft = nmi_ibft_read(sysfs_dir); - keys = nm_utils_strdict_get_keys(ibft, TRUE, &length); + keys = nm_strdict_get_keys(ibft, TRUE, &length); for (i = 0; i < length; i++) { gs_unref_object NMConnection *connection = NULL; @@ -394,6 +394,121 @@ reader_read_all_connections_from_fw(Reader *reader, const char *sysfs_dir) reader_add_connection(reader, "ofw", dt_connection); } +#define _strv_is_same_unordered(strv, ...) \ + nm_strv_is_same_unordered(NM_CAST_STRV_CC(strv), -1, NM_MAKE_STRV(__VA_ARGS__), -1) + +static void +_strv_remove(const char **strv, const char *needle) +{ + gssize idx; + gsize len; + gsize i; + + idx = nm_strv_find_first(strv, -1, needle); + if (idx < 0) + return; + + /* Remove element at idx, by shifting the remaining ones + * (including the terminating NULL). */ + len = NM_PTRARRAY_LEN(strv); + for (i = idx; i < len; i++) + strv[i] = strv[i + 1]; +} + +static const char * +_parse_ip_method(const char *kind) +{ + const char *const KINDS[] = { + "none", + "dhcp", + "dhcp6", + "link6", + "auto", + "ibft", + }; + gs_free char * kind_to_free = NULL; + gs_free const char **strv = NULL; + gsize i; + + kind = nm_strstrip_avoid_copy_a(300, kind, &kind_to_free); + + if (nm_str_is_empty(kind)) { + /* Dracut defaults empty/missing to "dhcp". We treat them differently, as it + * depends on whether we have IP addresses too. + * https://github.com/dracutdevs/dracut/blob/3cc9f1c10c67dcdb5254e0eb69f19e9ab22abf20/modules.d/35network-legacy/parse-ip-opts.sh#L62 */ + return "auto"; + } + + for (i = 0; i < G_N_ELEMENTS(KINDS); i++) { + if (nm_streq(kind, KINDS[i])) + return KINDS[i]; + } + + /* the following are (currently) treated as aliases. */ + if (nm_streq(kind, "fw")) + return "ibft"; + if (nm_streq(kind, "single-dhcp")) + return "dhcp"; + if (nm_streq(kind, "off")) + return "none"; + if (nm_streq(kind, "auto6")) + return "dhcp6"; + if (NM_IN_STRSET(kind, "on", "any")) + return "auto"; + + if (!strchr(kind, ',')) + return NULL; + + /* dracut also supports combinations, separated by comma. We don't + * support arbitrary combinations, but accept specific subsets. */ + strv = nm_strsplit_set_full(kind, ",", NM_STRSPLIT_SET_FLAGS_STRSTRIP); + if (!strv) + return NULL; + + /* first normalize the strv array by replacing all entries by their + * normalized kind. */ + for (i = 0; strv[i]; i++) { + strv[i] = _parse_ip_method(strv[i]); + if (!strv[i]) { + /* Unknown key. Not recognized. */ + return NULL; + } + } + + /* sort list and remove duplicates. */ + nm_strv_sort(strv, -1); + nm_strv_cleanup_const(strv, TRUE, TRUE); + + if (nm_strv_find_first(strv, -1, "auto") >= 0) { + /* if "auto" is present, then "dhcp4", "dhcp6", and "local6" is implied. */ + _strv_remove(strv, "dhcp4"); + _strv_remove(strv, "dhcp6"); + _strv_remove(strv, "local6"); + } else if (nm_strv_find_first(strv, -1, "dhcp6") >= 0) { + /* if "dhcp6" is present, then "local6" is implied. */ + _strv_remove(strv, "local6"); + } + + if (strv[0] && !strv[1]) { + /* there is only one value left. It's good. */ + return strv[0]; + } + + /* only certain combinations are allowed... those are listed + * and mapped to a canonical value. + */ + if (_strv_is_same_unordered(strv, "dhcp", "dhcp6")) + return "dhcp4+auto6"; + /* For the moment, this maps to "auto". This might be revisited + * in the future to add new kinds like "dhcp+local6" + */ + if (_strv_is_same_unordered(strv, "dhcp", "local6")) + return "auto"; + + /* undetected. */ + return NULL; +} + static void reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) { @@ -403,7 +518,8 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) gs_unref_hashtable GHashTable *ibft = NULL; const char * tmp; const char * tmp2; - const char * kind = NULL; + const char * tmp3; + const char * kind; const char * client_ip = NULL; const char * peer = NULL; const char * gateway_ip = NULL; @@ -432,24 +548,17 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) tmp = get_word(&argument, ':'); if (!*argument) { /* ip={dhcp|on|any|dhcp6|auto6|link6|ibft} */ - kind = tmp; + kind = _parse_ip_method(tmp); + if (!kind) { + /* invalid method. We treat it as "auto". */ + kind = "auto"; + } } else { tmp2 = get_word(&argument, ':'); - if (NM_IN_STRSET(tmp2, - "none", - "off", - "dhcp", - "single-dhcp", - "on" - "any", - "dhcp6", - "auto", - "auto6", - "link6", - "ibft")) { + if (!nm_str_is_empty(tmp2) && (tmp3 = _parse_ip_method(tmp2))) { /* <ifname>:{none|off|dhcp|on|any|dhcp6|auto|auto6|link6|ibft} */ iface_spec = tmp; - kind = tmp2; + kind = tmp3; } else { /* <client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<kind> */ client_ip = tmp; @@ -466,7 +575,12 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) netmask = get_word(&argument, ':'); client_hostname = get_word(&argument, ':'); iface_spec = get_word(&argument, ':'); - kind = get_word(&argument, ':'); + tmp2 = get_word(&argument, ':'); + kind = _parse_ip_method(tmp2); + if (!kind) { + /* invalid method. We treat that as "auto". */ + kind = "auto"; + } } if (client_hostname && !nm_sd_hostname_is_valid(client_hostname, FALSE)) @@ -495,7 +609,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) } } - if (iface_spec == NULL && NM_IN_STRSET(kind, "fw", "ibft")) { + if (iface_spec == NULL && nm_streq(kind, "ibft")) { reader_read_all_connections_from_fw(reader, sysfs_dir); return; } @@ -592,7 +706,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) } /* Dynamic IP configuration configured explicitly. */ - if (NM_IN_STRSET(kind, "none", "off")) { + if (nm_streq(kind, "none")) { if (nm_setting_ip_config_get_num_addresses(s_ip6) == 0) { g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, @@ -605,7 +719,7 @@ 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", "single-dhcp")) { + } else if (nm_streq(kind, "dhcp")) { g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, @@ -618,7 +732,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); } - } else if (NM_IN_STRSET(kind, "auto6", "dhcp6")) { + } else if (nm_streq(kind, "dhcp6")) { g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, @@ -631,7 +745,17 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NULL); } - } else if (nm_streq0(kind, "link6")) { + } else if (nm_streq(kind, "dhcp4+auto6")) { + /* 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_streq(kind, "link6")) { g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL, @@ -644,7 +768,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NULL); } - } else if (nm_streq0(kind, "ibft")) { + } else if (nm_streq(kind, "ibft")) { NMSettingWired *s_wired; const char * mac = NULL; const char * ifname; @@ -684,6 +808,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) } } } else { + nm_assert(nm_streq(kind, "auto")); clear_ip4_required_timeout = FALSE; } @@ -1059,60 +1184,60 @@ reader_parse_rd_znet(Reader *reader, char *argument, gboolean net_ifnames) static void reader_parse_ethtool(Reader *reader, char *argument) { - const char * interface = NULL; - NMConnection * connection = NULL; - NMSettingWired *s_wired = NULL; - const char * autoneg_str = NULL; - gboolean autoneg = FALSE; - const char * speed_str = NULL; - guint speed = 0; + NMConnection * connection; + NMSettingWired *s_wired; + const char * autoneg_str; + const char * speed_str; + const char * interface; + int autoneg; + guint speed; interface = get_word(&argument, ':'); if (!interface) { - _LOGW(LOGD_CORE, "Impossible to set rd.ethtool options: invalid format"); + _LOGW(LOGD_CORE, "rd.ethtool: interface unspecified. Ignore"); return; } - if (!*argument) { - _LOGW(LOGD_CORE, "Could not find rd.ethtool options to set"); - return; - } - - connection = reader_get_connection(reader, interface, NM_SETTING_WIRED_SETTING_NAME, TRUE); - s_wired = nm_connection_get_setting_wired(connection); - autoneg_str = get_word(&argument, ':'); + speed_str = get_word(&argument, ':'); + + autoneg = -1; if (autoneg_str) { autoneg = _nm_utils_ascii_str_to_bool(autoneg_str, -1); if (autoneg == -1) - _LOGW(LOGD_CORE, - "Invalid value for rd.ethtool.autoneg, rd.ethtool.autoneg was not set"); - else - g_object_set(s_wired, NM_SETTING_WIRED_AUTO_NEGOTIATE, autoneg, NULL); + _LOGW(LOGD_CORE, "rd.ethtool: autoneg invalid. Must be boolean or empty"); } - if (!*argument) - return; - speed_str = get_word(&argument, ':'); + speed = 0; if (speed_str) { - speed = _nm_utils_ascii_str_to_int64(speed_str, 10, 0, G_MAXUINT32, -1); - if (speed == -1) - _LOGW(LOGD_CORE, "Invalid value for rd.ethtool.speed, rd.ethtool.speed was not set"); - else - g_object_set(s_wired, - NM_SETTING_WIRED_SPEED, - speed, - NM_SETTING_WIRED_DUPLEX, - "full", - NULL); + speed = _nm_utils_ascii_str_to_int64(speed_str, 10, 0, G_MAXUINT32, 0); + if (errno) + _LOGW(LOGD_CORE, "rd.ethtool: speed invalid. Must be an integer or empty"); } - if (!*argument) - return; - else + if (speed == 0 && autoneg == FALSE) { _LOGW(LOGD_CORE, - "Invalid extra argument '%s' for rd.ethtool, this value was not set", - argument); + "rd.ethtool: autoneg ignored. Cannot disable autoneg without setting speed"); + } + + connection = reader_get_connection(reader, interface, NM_SETTING_WIRED_SETTING_NAME, TRUE); + + if (autoneg != -1 || speed != 0) { + if (autoneg == -1) + autoneg = FALSE; + s_wired = nm_connection_get_setting_wired(connection); + g_object_set(s_wired, + NM_SETTING_WIRED_AUTO_NEGOTIATE, + (gboolean) autoneg, + NM_SETTING_WIRED_SPEED, + speed, + NM_SETTING_WIRED_DUPLEX, + speed == 0 ? NULL : "full", + NULL); + } + + if (*argument) + _LOGW(LOGD_CORE, "rd.ethtool: extra argument ignored"); } static void @@ -1239,7 +1364,7 @@ nmi_cmdline_reader_parse(const char * sysfs_dir, _nm_utils_ascii_str_to_int64(argument, 10, 1, G_MAXINT32, dhcp_num_tries); } else if (nm_streq(tag, "rd.net.dhcp.vendor-class")) { if (nm_utils_validate_dhcp4_vendor_class_id(argument, NULL)) - nm_utils_strdup_reset(&reader->dhcp4_vci, argument); + nm_strdup_reset(&reader->dhcp4_vci, argument); } else if (nm_streq(tag, "rd.net.timeout.carrier")) { reader->carrier_timeout_sec = _nm_utils_ascii_str_to_int64(argument, 10, 0, G_MAXINT32, 0); diff --git a/src/nm-initrd-generator/tests/test-cmdline-reader.c b/src/nm-initrd-generator/tests/test-cmdline-reader.c index e2a37c58..2cb1b2f4 100644 --- a/src/nm-initrd-generator/tests/test-cmdline-reader.c +++ b/src/nm-initrd-generator/tests/test-cmdline-reader.c @@ -140,7 +140,7 @@ static void test_dhcp_with_hostname(void) { gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("ip=::::host1::dhcp"); + const char *const * ARGV = NM_MAKE_STRV("ip=::::host1::dhcp,dhcp6"); NMConnection * connection; NMSettingConnection * s_con; NMSettingWired * s_wired; @@ -191,7 +191,7 @@ test_dhcp_with_hostname(void) static void test_dhcp_with_mtu(void) { - const char *const *ARGV0 = NM_MAKE_STRV("ip=:dhcp:1499"); + const char *const *ARGV0 = NM_MAKE_STRV("ip=:dhcp6,dhcp:1499"); const char *const *ARGV1 = NM_MAKE_STRV("ip=::::::dhcp:1499"); const char *const *ARGV[] = {ARGV0, ARGV1}; guint i; @@ -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 @@ -2272,203 +2278,145 @@ test_carrier_timeout(void) g_assert_cmpint(carrier_timeout_sec, ==, 20); } -/* Obs1.: this function is implemented as macro, and not as a function, - * to show the correct line in g_assert() debug */ -#define _ethtool_connection_check_and_get(connection) \ - ({ \ - NMSettingWired *_s_wired = NULL; \ - NMConnection * _connection = connection; \ - \ - g_assert(nm_connection_get_setting_connection(_connection)); \ - g_assert(nm_connection_is_type(_connection, NM_SETTING_WIRED_SETTING_NAME)); \ - g_assert(nm_connection_get_setting_ip4_config(_connection)); \ - g_assert(nm_connection_get_setting_ip6_config(_connection)); \ - _s_wired = nm_connection_get_setting_wired(_connection); \ - g_assert(NM_IS_SETTING_WIRED(_s_wired)); \ - \ - _s_wired; \ - }) +#define _ethtool_check_inval(arg) \ + G_STMT_START \ + { \ + gs_unref_hashtable GHashTable *_connections2 = NULL; \ + \ + _connections2 = _parse_cons(NM_MAKE_STRV(arg)); \ + \ + g_test_assert_expected_messages(); \ + \ + g_assert_cmpint(g_hash_table_size(_connections2), ==, 0); \ + } \ + G_STMT_END + +#define _ethtool_check_v(strv, autoneg, speed) \ + G_STMT_START \ + { \ + gs_unref_object NMConnection *_connection = NULL; \ + NMSettingWired * _s_wired; \ + typeof(speed) _speed = speed; \ + \ + _connection = _parse_con(strv, "eth0"); \ + \ + g_test_assert_expected_messages(); \ + \ + g_assert(nm_connection_get_setting_connection(_connection)); \ + g_assert(nm_connection_is_type(_connection, NM_SETTING_WIRED_SETTING_NAME)); \ + g_assert(nm_connection_get_setting_ip4_config(_connection)); \ + g_assert(nm_connection_get_setting_ip6_config(_connection)); \ + _s_wired = nm_connection_get_setting_wired(_connection); \ + g_assert(NM_IS_SETTING_WIRED(_s_wired)); \ + \ + g_assert_cmpint(nm_setting_wired_get_auto_negotiate(_s_wired), ==, (autoneg)); \ + g_assert_cmpint(nm_setting_wired_get_speed(_s_wired), ==, _speed); \ + g_assert_cmpstr(nm_setting_wired_get_duplex(_s_wired), ==, (_speed == 0 ? NULL : "full")); \ + } \ + G_STMT_END + +#define _ethtool_check(arg, autoneg, speed) \ + _ethtool_check_v(NM_MAKE_STRV("" arg ""), (autoneg), (speed)) static void test_rd_ethtool(void) { - const char *const *ARGV = NULL; - NMConnection * connection = NULL; - GHashTable * connections = NULL; - NMSettingWired * s_wired = NULL; + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: interface unspecified. Ignore"); + _ethtool_check_inval("rd.ethtool="); - ARGV = NM_MAKE_STRV("rd.ethtool="); - NMTST_EXPECT_NM_WARN("cmdline-reader: Impossible to set rd.ethtool options: invalid format"); - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 0); - g_hash_table_unref(connections); - g_test_assert_expected_messages(); + _ethtool_check("rd.ethtool=eth0", FALSE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0"); - NMTST_EXPECT_NM_WARN("cmdline-reader: Could not find rd.ethtool options to set"); - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 0); - g_hash_table_unref(connections); - g_test_assert_expected_messages(); + _ethtool_check("rd.ethtool=eth0:", FALSE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0:"); - NMTST_EXPECT_NM_WARN("cmdline-reader: Could not find rd.ethtool options to set"); - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 0); - g_hash_table_unref(connections); - g_test_assert_expected_messages(); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: interface unspecified. Ignore"); + _ethtool_check_inval("rd.ethtool=::"); - ARGV = NM_MAKE_STRV("rd.ethtool=::"); - NMTST_EXPECT_NM_WARN("cmdline-reader: Impossible to set rd.ethtool options: invalid format"); - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 0); - g_test_assert_expected_messages(); - g_hash_table_unref(connections); + _ethtool_check("rd.ethtool=eth0:on", TRUE, 0); + _ethtool_check("rd.ethtool=eth0:on:", TRUE, 0); + _ethtool_check("rd.ethtool=eth0:on::", TRUE, 0); + _ethtool_check("rd.ethtool=eth0:on:0:", TRUE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0:on"); - connection = _parse_con(ARGV, "eth0"); - s_wired = _ethtool_connection_check_and_get(connection); - g_assert(nm_setting_wired_get_auto_negotiate(s_wired)); - g_object_unref(connection); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: autoneg ignored. Cannot disable autoneg " + "without setting speed"); + _ethtool_check("rd.ethtool=eth0:off", FALSE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0:off"); - connection = _parse_con(ARGV, "eth0"); - s_wired = _ethtool_connection_check_and_get(connection); - g_assert(!nm_setting_wired_get_auto_negotiate(s_wired)); - g_object_unref(connection); + _ethtool_check("rd.ethtool=eth0:true", TRUE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0:true"); - connection = _parse_con(ARGV, "eth0"); - s_wired = _ethtool_connection_check_and_get(connection); - g_assert(nm_setting_wired_get_auto_negotiate(s_wired)); - g_object_unref(connection); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: autoneg ignored. Cannot disable autoneg " + "without setting speed"); + _ethtool_check("rd.ethtool=eth0:false", FALSE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0:false"); - connection = _parse_con(ARGV, "eth0"); - s_wired = _ethtool_connection_check_and_get(connection); - g_assert(!nm_setting_wired_get_auto_negotiate(s_wired)); - g_object_unref(connection); + _ethtool_check("rd.ethtool=eth0:1", TRUE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0:1"); - connection = _parse_con(ARGV, "eth0"); - s_wired = _ethtool_connection_check_and_get(connection); - g_assert(nm_setting_wired_get_auto_negotiate(s_wired)); - g_object_unref(connection); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: autoneg ignored. Cannot disable autoneg " + "without setting speed"); + _ethtool_check("rd.ethtool=eth0:0", FALSE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0:0"); - connection = _parse_con(ARGV, "eth0"); - s_wired = _ethtool_connection_check_and_get(connection); - g_assert(!nm_setting_wired_get_auto_negotiate(s_wired)); - g_object_unref(connection); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: autoneg invalid. Must be boolean or empty"); + _ethtool_check("rd.ethtool=eth0:randomstring", FALSE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0:randomstring"); - NMTST_EXPECT_NM_WARN( - "cmdline-reader: Invalid value for rd.ethtool.autoneg, rd.ethtool.autoneg was not set"); - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_test_assert_expected_messages(); - g_hash_table_unref(connections); + _ethtool_check("rd.ethtool=eth0::", FALSE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0::"); - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_hash_table_unref(connections); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: speed invalid. Must be an integer or empty"); + _ethtool_check("rd.ethtool=eth0::astring", FALSE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0::astring"); - NMTST_EXPECT_NM_WARN( - "cmdline-reader: Invalid value for rd.ethtool.speed, rd.ethtool.speed was not set"); - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_test_assert_expected_messages(); - g_hash_table_unref(connections); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: speed invalid. Must be an integer or empty"); + _ethtool_check("rd.ethtool=eth0::1000000000000000000000000000000000000", FALSE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0::1000000000000000000000000000000000000"); - NMTST_EXPECT_NM_WARN( - "cmdline-reader: Invalid value for rd.ethtool.speed, rd.ethtool.speed was not set"); - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_test_assert_expected_messages(); - g_hash_table_unref(connections); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: speed invalid. Must be an integer or empty"); + _ethtool_check("rd.ethtool=eth0::0.67", FALSE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0::0.67"); - NMTST_EXPECT_NM_WARN( - "cmdline-reader: Invalid value for rd.ethtool.speed, rd.ethtool.speed was not set"); - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_test_assert_expected_messages(); - g_hash_table_unref(connections); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: speed invalid. Must be an integer or empty"); + _ethtool_check("rd.ethtool=eth0::-23", FALSE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0::-23"); - NMTST_EXPECT_NM_WARN( - "cmdline-reader: Invalid value for rd.ethtool.speed, rd.ethtool.speed was not set"); - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_test_assert_expected_messages(); - g_hash_table_unref(connections); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: speed invalid. Must be an integer or empty"); + _ethtool_check("rd.ethtool=eth0::-23:", FALSE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0:1:10"); - connection = _parse_con(ARGV, "eth0"); - s_wired = _ethtool_connection_check_and_get(connection); - g_assert(nm_setting_wired_get_auto_negotiate(s_wired)); - g_assert_cmpint(nm_setting_wired_get_speed(s_wired), ==, 10); - g_assert_cmpstr(nm_setting_wired_get_duplex(s_wired), ==, "full"); - g_object_unref(connection); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: speed invalid. Must be an integer or empty"); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: extra argument ignored"); + _ethtool_check("rd.ethtool=eth0::-23::", FALSE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0::100"); - connection = _parse_con(ARGV, "eth0"); - s_wired = _ethtool_connection_check_and_get(connection); - g_assert(!nm_setting_wired_get_auto_negotiate(s_wired)); - g_assert_cmpint(nm_setting_wired_get_speed(s_wired), ==, 100); - g_assert_cmpstr(nm_setting_wired_get_duplex(s_wired), ==, "full"); - g_object_unref(connection); - - ARGV = NM_MAKE_STRV("rd.ethtool=eth0:::bogus"); - NMTST_EXPECT_NM_WARN( - "cmdline-reader: Invalid extra argument 'bogus' for rd.ethtool, this value was not set"); - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_test_assert_expected_messages(); - g_hash_table_unref(connections); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: speed invalid. Must be an integer or empty"); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: extra argument ignored"); + _ethtool_check("rd.ethtool=eth0::-23::foo", FALSE, 0); - ARGV = NM_MAKE_STRV("rd.ethtool=eth0::10:bogus"); - NMTST_EXPECT_NM_WARN( - "cmdline-reader: Invalid extra argument 'bogus' for rd.ethtool, this value was not set"); - connection = _parse_con(ARGV, "eth0"); - s_wired = _ethtool_connection_check_and_get(connection); - g_assert(!nm_setting_wired_get_auto_negotiate(s_wired)); - g_assert_cmpint(nm_setting_wired_get_speed(s_wired), ==, 10); - g_assert_cmpstr(nm_setting_wired_get_duplex(s_wired), ==, "full"); - g_test_assert_expected_messages(); - g_object_unref(connection); - - ARGV = NM_MAKE_STRV("rd.ethtool=eth0:on:100:bogus"); - NMTST_EXPECT_NM_WARN( - "cmdline-reader: Invalid extra argument 'bogus' for rd.ethtool, this value was not set"); - connection = _parse_con(ARGV, "eth0"); - s_wired = _ethtool_connection_check_and_get(connection); - g_assert(nm_setting_wired_get_auto_negotiate(s_wired)); - g_assert_cmpint(nm_setting_wired_get_speed(s_wired), ==, 100); - g_assert_cmpstr(nm_setting_wired_get_duplex(s_wired), ==, "full"); - g_test_assert_expected_messages(); - g_object_unref(connection); - - ARGV = NM_MAKE_STRV("rd.ethtool=eth0:on:100:bogus"); - NMTST_EXPECT_NM_WARN( - "cmdline-reader: Invalid extra argument 'bogus' for rd.ethtool, this value was not set"); - connection = _parse_con(ARGV, "eth0"); - s_wired = _ethtool_connection_check_and_get(connection); - g_assert(nm_setting_wired_get_auto_negotiate(s_wired)); - g_assert_cmpint(nm_setting_wired_get_speed(s_wired), ==, 100); - g_assert_cmpstr(nm_setting_wired_get_duplex(s_wired), ==, "full"); - g_test_assert_expected_messages(); - g_object_unref(connection); - - ARGV = NM_MAKE_STRV("rd.ethtool=:::"); - NMTST_EXPECT_NM_WARN("cmdline-reader: Impossible to set rd.ethtool options: invalid format"); - connections = _parse_cons(ARGV); - g_assert_cmpint(g_hash_table_size(connections), ==, 0); - g_test_assert_expected_messages(); - g_hash_table_unref(connections); + _ethtool_check("rd.ethtool=eth0:1:10", TRUE, 10); + + _ethtool_check("rd.ethtool=eth0::100", FALSE, 100); + + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: extra argument ignored"); + _ethtool_check("rd.ethtool=eth0:::bogus", FALSE, 0); + + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: extra argument ignored"); + _ethtool_check("rd.ethtool=eth0::10:bogus", FALSE, 10); + + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: extra argument ignored"); + _ethtool_check("rd.ethtool=eth0:on:100:bogus", TRUE, 100); + + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: interface unspecified. Ignore"); + _ethtool_check_inval("rd.ethtool=:::"); + + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: autoneg ignored. Cannot disable autoneg " + "without setting speed"); + _ethtool_check_v(NM_MAKE_STRV("rd.ethtool=eth0:off:0", "rd.ethtool=eth0:on"), TRUE, 0); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: autoneg ignored. Cannot disable autoneg " + "without setting speed"); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: autoneg ignored. Cannot disable autoneg " + "without setting speed"); + _ethtool_check_v(NM_MAKE_STRV("rd.ethtool=eth0:off:0", "rd.ethtool=eth0:off"), FALSE, 0); + _ethtool_check_v(NM_MAKE_STRV("rd.ethtool=eth0:on:0", "rd.ethtool=eth0:on"), TRUE, 0); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: autoneg ignored. Cannot disable autoneg " + "without setting speed"); + _ethtool_check_v(NM_MAKE_STRV("rd.ethtool=eth0:on:0", "rd.ethtool=eth0:off"), FALSE, 0); + _ethtool_check_v(NM_MAKE_STRV("rd.ethtool=eth0:off:100", "rd.ethtool=eth0:on"), TRUE, 0); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: autoneg ignored. Cannot disable autoneg " + "without setting speed"); + _ethtool_check_v(NM_MAKE_STRV("rd.ethtool=eth0:off:100", "rd.ethtool=eth0:off"), FALSE, 0); + _ethtool_check_v(NM_MAKE_STRV("rd.ethtool=eth0:on:100", "rd.ethtool=eth0:on"), TRUE, 0); + NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool: autoneg ignored. Cannot disable autoneg " + "without setting speed"); + _ethtool_check_v(NM_MAKE_STRV("rd.ethtool=eth0:on:100", "rd.ethtool=eth0:off"), FALSE, 0); + _ethtool_check_v(NM_MAKE_STRV("rd.ethtool=eth0:off:100", "rd.ethtool=eth0:"), FALSE, 100); } /*****************************************************************************/ |