nm-initrd-generator: add kernel command line options ethtool autoneg, speed and duplex to configure NICs
Merge Request !941
This commit is contained in:
@@ -1170,6 +1170,97 @@ reader_parse_rd_znet(Reader *reader, char *argument, gboolean net_ifnames)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
reader_parse_ethtool(Reader *reader, char *argument)
|
||||
{
|
||||
NMConnection * connection = NULL;
|
||||
NMSettingWired *s_wired = NULL;
|
||||
const char * read = NULL;
|
||||
const char * interface = NULL;
|
||||
gboolean autoneg = FALSE;
|
||||
guint speed = 0;
|
||||
|
||||
interface = get_word(&argument, ':');
|
||||
if (!interface) {
|
||||
_LOGW(LOGD_CORE, "Impossible to set rd.ethtool options: invalid format");
|
||||
return;
|
||||
}
|
||||
if (!*argument)
|
||||
return;
|
||||
|
||||
read = get_word(&argument, ':');
|
||||
if (read) {
|
||||
autoneg = _nm_utils_ascii_str_to_bool(read, -1);
|
||||
if (autoneg == -1)
|
||||
_LOGW(LOGD_CORE, "rd.ethtool autoneg was not set, invalid value");
|
||||
else {
|
||||
connection =
|
||||
reader_get_connection(reader, interface, NM_SETTING_WIRED_SETTING_NAME, TRUE);
|
||||
s_wired = nm_connection_get_setting_wired(connection);
|
||||
g_object_set(s_wired, NM_SETTING_WIRED_AUTO_NEGOTIATE, autoneg, NULL);
|
||||
}
|
||||
}
|
||||
if (!*argument)
|
||||
return;
|
||||
|
||||
read = get_word(&argument, ':');
|
||||
if (read) {
|
||||
speed = _nm_utils_ascii_str_to_int64(read, 10, 0, G_MAXUINT32, -1);
|
||||
if (speed == -1) {
|
||||
_LOGW(LOGD_CORE,
|
||||
"rd.ethtool speed was not set, invalid value. Then, duplex was disregarded.");
|
||||
/* Duplex does not need to be evaluated after, because it can't be set without speed value */
|
||||
return;
|
||||
} else {
|
||||
connection =
|
||||
reader_get_connection(reader, interface, NM_SETTING_WIRED_SETTING_NAME, TRUE);
|
||||
s_wired = nm_connection_get_setting_wired(connection);
|
||||
/* duplex option is available for legacy purposes */
|
||||
/* speed must be always set having duplex set, otherwise it will fail in verifications */
|
||||
|
||||
if (*argument) {
|
||||
/* duplex value was informed, and has a valid value */
|
||||
if (NM_IN_STRSET(argument, "half", "full"))
|
||||
g_object_set(s_wired,
|
||||
NM_SETTING_WIRED_SPEED,
|
||||
speed,
|
||||
NM_SETTING_WIRED_DUPLEX,
|
||||
argument,
|
||||
NULL);
|
||||
|
||||
/* duplex value was informed, and does not have a valid value */
|
||||
else {
|
||||
_LOGW(LOGD_CORE,
|
||||
"rd.ethtool.duplex has a invalid format, duplex was set as default:full");
|
||||
g_object_set(s_wired,
|
||||
NM_SETTING_WIRED_SPEED,
|
||||
speed,
|
||||
NM_SETTING_WIRED_DUPLEX,
|
||||
"full",
|
||||
NULL);
|
||||
}
|
||||
} else {
|
||||
/* duplex value was not informed, then it will have default 'full' value */
|
||||
g_object_set(s_wired,
|
||||
NM_SETTING_WIRED_SPEED,
|
||||
speed,
|
||||
NM_SETTING_WIRED_DUPLEX,
|
||||
"full",
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* Duplex does not need to be evaluated alone - it can't be set without speed value */
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!*argument)
|
||||
return;
|
||||
else {
|
||||
/* Duplex does not need to be evaluated, because it can't be set without speed value */
|
||||
_LOGW(LOGD_CORE, "rd.ethtool.duplex needs rd.ethtool.speed value to be set");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_normalize_conn(gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
@@ -1351,7 +1442,8 @@ nmi_cmdline_reader_parse(const char * sysfs_dir,
|
||||
} else if (g_ascii_strcasecmp(tag, "BOOTIF") == 0) {
|
||||
nm_clear_g_free(&bootif_val);
|
||||
bootif_val = g_strdup(argument);
|
||||
}
|
||||
} else if (nm_streq(tag, "rd.ethtool"))
|
||||
reader_parse_ethtool(reader, argument);
|
||||
}
|
||||
|
||||
for (i = 0; i < reader->vlan_parents->len; i++) {
|
||||
|
@@ -2262,6 +2262,193 @@ 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 g_assert() line on 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(_s_wired); \
|
||||
\
|
||||
_s_wired; \
|
||||
})
|
||||
|
||||
static void
|
||||
test_rd_ethtool(void)
|
||||
{
|
||||
const char *const *ARGV = NULL;
|
||||
NMConnection * connection = NULL;
|
||||
GHashTable * connections = NULL;
|
||||
NMSettingWired * s_wired = NULL;
|
||||
|
||||
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();
|
||||
|
||||
ARGV = NM_MAKE_STRV("rd.ethtool=eth0");
|
||||
connections = _parse_cons(ARGV);
|
||||
g_assert_cmpint(g_hash_table_size(connections), ==, 0);
|
||||
g_hash_table_unref(connections);
|
||||
|
||||
ARGV = NM_MAKE_STRV("rd.ethtool=eth0:");
|
||||
connections = _parse_cons(ARGV);
|
||||
g_assert_cmpint(g_hash_table_size(connections), ==, 0);
|
||||
g_hash_table_unref(connections);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
ARGV = NM_MAKE_STRV("rd.ethtool=eth0:randomstring");
|
||||
NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool autoneg was not set, invalid value");
|
||||
connections = _parse_cons(ARGV);
|
||||
g_assert_cmpint(g_hash_table_size(connections), ==, 0);
|
||||
g_test_assert_expected_messages();
|
||||
g_hash_table_unref(connections);
|
||||
|
||||
ARGV = NM_MAKE_STRV("rd.ethtool=eth0::");
|
||||
connections = _parse_cons(ARGV);
|
||||
g_assert_cmpint(g_hash_table_size(connections), ==, 0);
|
||||
g_hash_table_unref(connections);
|
||||
|
||||
ARGV = NM_MAKE_STRV("rd.ethtool=eth0::astring");
|
||||
NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool speed was not set, invalid value. Then, "
|
||||
"duplex was disregarded.");
|
||||
connections = _parse_cons(ARGV);
|
||||
g_assert_cmpint(g_hash_table_size(connections), ==, 0);
|
||||
g_test_assert_expected_messages();
|
||||
g_hash_table_unref(connections);
|
||||
|
||||
ARGV = NM_MAKE_STRV("rd.ethtool=eth0::1000000000000000000000000000000000000");
|
||||
NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool speed was not set, invalid value. Then, "
|
||||
"duplex was disregarded.");
|
||||
connections = _parse_cons(ARGV);
|
||||
g_assert_cmpint(g_hash_table_size(connections), ==, 0);
|
||||
g_test_assert_expected_messages();
|
||||
g_hash_table_unref(connections);
|
||||
|
||||
ARGV = NM_MAKE_STRV("rd.ethtool=eth0::0.67");
|
||||
NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool speed was not set, invalid value. Then, "
|
||||
"duplex was disregarded.");
|
||||
connections = _parse_cons(ARGV);
|
||||
g_assert_cmpint(g_hash_table_size(connections), ==, 0);
|
||||
g_test_assert_expected_messages();
|
||||
g_hash_table_unref(connections);
|
||||
|
||||
ARGV = NM_MAKE_STRV("rd.ethtool=eth0::-23");
|
||||
NMTST_EXPECT_NM_WARN("cmdline-reader: rd.ethtool speed was not set, invalid value. Then, "
|
||||
"duplex was disregarded.");
|
||||
connections = _parse_cons(ARGV);
|
||||
g_assert_cmpint(g_hash_table_size(connections), ==, 0);
|
||||
g_test_assert_expected_messages();
|
||||
g_hash_table_unref(connections);
|
||||
|
||||
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);
|
||||
|
||||
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:::half");
|
||||
NMTST_EXPECT_NM_WARN(
|
||||
"cmdline-reader: rd.ethtool.duplex needs rd.ethtool.speed value to be set");
|
||||
connections = _parse_cons(ARGV);
|
||||
g_assert_cmpint(g_hash_table_size(connections), ==, 0);
|
||||
g_test_assert_expected_messages();
|
||||
g_hash_table_unref(connections);
|
||||
|
||||
ARGV = NM_MAKE_STRV("rd.ethtool=eth0::10:half");
|
||||
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), ==, "half");
|
||||
g_object_unref(connection);
|
||||
|
||||
ARGV = NM_MAKE_STRV("rd.ethtool=eth0:on:100:full");
|
||||
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:on:100:anyvalue");
|
||||
NMTST_EXPECT_NM_WARN(
|
||||
"cmdline-reader: rd.ethtool.duplex has a invalid format, duplex was set as default:full");
|
||||
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);
|
||||
}
|
||||
|
||||
NMTST_DEFINE();
|
||||
|
||||
int
|
||||
@@ -2316,6 +2503,7 @@ main(int argc, char **argv)
|
||||
g_test_add_func("/initrd/cmdline/infiniband/mac", test_infiniband_mac);
|
||||
g_test_add_func("/initrd/cmdline/infiniband/pkey", test_infiniband_pkey);
|
||||
g_test_add_func("/initrd/cmdline/carrier_timeout", test_carrier_timeout);
|
||||
g_test_add_func("/initrd/cmdline/rd_ethtool", test_rd_ethtool);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
Reference in New Issue
Block a user