summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFrancesco Giudici <fgiudici@redhat.com>2016-09-14 17:48:13 +0200
committerFrancesco Giudici <fgiudici@redhat.com>2016-11-22 15:24:47 +0100
commit12b9d30ae625000c578d6b4f4bcf8c3a119132dc (patch)
treeba9b27b777761c52ad75e96e7b44847ad2869fe0 /src
parentde88a467757d619429f5b74c4d683e42b01b94d9 (diff)
downloadNetworkManager-12b9d30ae625000c578d6b4f4bcf8c3a119132dc.tar.gz
ifcfg-rh: add support to 802-3.[auto-negotiate,speed,duplex] properties
NOTE: changed the default value for auto-negotiate from TRUE to FALSE. Normalization enforces that no values for speed and duplex are there when autonegotiation is on. This is required as autoneg on with specific speed and duplex set means to ethtool to use autonegotiation but advertise that specific speed and duplex only. autoneg off, speed 0 and duplex NULL means to ignore link negotiation.
Diffstat (limited to 'src')
-rw-r--r--src/NetworkManager.ver-orig3
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c87
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c51
3 files changed, 126 insertions, 15 deletions
diff --git a/src/NetworkManager.ver-orig b/src/NetworkManager.ver-orig
index 08d5c6e4ec..e89ed95e0d 100644
--- a/src/NetworkManager.ver-orig
+++ b/src/NetworkManager.ver-orig
@@ -425,7 +425,9 @@ global:
nm_setting_vlan_get_type;
nm_setting_vlan_new;
nm_setting_wired_add_s390_option;
+ nm_setting_wired_get_auto_negotiate;
nm_setting_wired_get_cloned_mac_address;
+ nm_setting_wired_get_duplex;
nm_setting_wired_get_generate_mac_address_mask;
nm_setting_wired_get_mac_address;
nm_setting_wired_get_mac_address_blacklist;
@@ -435,6 +437,7 @@ global:
nm_setting_wired_get_s390_option;
nm_setting_wired_get_s390_option_by_key;
nm_setting_wired_get_s390_subchannels;
+ nm_setting_wired_get_speed;
nm_setting_wired_get_type;
nm_setting_wired_get_wake_on_lan;
nm_setting_wired_get_wake_on_lan_password;
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
index 0ce6f6c140..843bad1c62 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
@@ -3656,6 +3656,52 @@ wireless_connection_from_ifcfg (const char *file,
}
static void
+parse_ethtool_option_autoneg (const char *value, gboolean *out_autoneg)
+{
+ if (!value) {
+ PARSE_WARNING ("Auto-negotiation option missing");
+ return;
+ }
+
+ if (g_str_equal (value, "off"))
+ *out_autoneg = FALSE;
+ else if (g_str_equal (value, "on"))
+ *out_autoneg = TRUE;
+ else
+ PARSE_WARNING ("Auto-negotiation unknown value: %s", value);
+}
+
+static void
+parse_ethtool_option_speed (const char *value, guint32 *out_speed)
+{
+ if (!value) {
+ PARSE_WARNING ("Speed option missing");
+ return;
+ }
+
+ *out_speed = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, 0);
+ if (errno)
+ PARSE_WARNING ("Speed value '%s' is invalid", value);
+}
+
+static void
+parse_ethtool_option_duplex (const char *value, const char **out_duplex)
+{
+ if (!value) {
+ PARSE_WARNING ("Duplex option missing");
+ return;
+ }
+
+ if (g_str_equal (value, "half"))
+ *out_duplex = "half";
+ else if (g_str_equal (value, "full"))
+ *out_duplex = "full";
+ else
+ PARSE_WARNING ("Duplex unknown value: %s", value);
+
+}
+
+static void
parse_ethtool_option_wol (const char *value, NMSettingWiredWakeOnLan *out_flags)
{
NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE;
@@ -3715,10 +3761,16 @@ static void parse_ethtool_option_sopass (const char *value, char **out_password)
}
static void
-parse_ethtool_option (const char *value, NMSettingWiredWakeOnLan *out_flags, char **out_password)
+parse_ethtool_option (const char *value,
+ NMSettingWiredWakeOnLan *out_flags,
+ char **out_password,
+ gboolean *out_autoneg,
+ guint32 *out_speed,
+ const char **out_duplex)
{
gs_strfreev char **words = NULL;
const char **iter = NULL, *opt_val, *opt;
+
if (!value || !value[0])
return;
@@ -3740,7 +3792,13 @@ parse_ethtool_option (const char *value, NMSettingWiredWakeOnLan *out_flags, cha
opt_val = iter[0];
- if (g_str_equal (opt, "wol"))
+ if (g_str_equal (opt, "autoneg"))
+ parse_ethtool_option_autoneg (opt_val, out_autoneg);
+ else if (g_str_equal (opt, "speed"))
+ parse_ethtool_option_speed (opt_val, out_speed);
+ else if (g_str_equal (opt, "duplex"))
+ parse_ethtool_option_duplex (opt_val, out_duplex);
+ else if (g_str_equal (opt, "wol"))
parse_ethtool_option_wol (opt_val, out_flags);
else if (g_str_equal (opt, "sopass"))
parse_ethtool_option_sopass (opt_val, out_password);
@@ -3758,31 +3816,48 @@ static void
parse_ethtool_options (shvarFile *ifcfg, NMSettingWired *s_wired, const char *value)
{
NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT;
- gs_free char *wol_password = NULL;
- gboolean ignore_wol_password = FALSE;
+ gs_free char *wol_password = NULL, *wol_value = NULL;
+ gboolean ignore_wol_password = FALSE, autoneg = FALSE;
+ guint32 speed = 0;
+ const char *duplex = NULL;
if (value) {
gs_strfreev char **opts = NULL;
const char **iter;
- wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE;
+ /* WAKE_ON_LAN_IGNORE is inferred from a specified but empty ETHTOOL_OPTS */
+ if (!value[0])
+ wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE;
opts = g_strsplit_set (value, ";", 0);
for (iter = (const char **) opts; iter[0]; iter++) {
/* in case of repeated wol_passwords, parse_ethtool_option()
* will do the right thing and clear wol_password before resetting. */
- parse_ethtool_option (iter[0], &wol_flags, &wol_password);
+ parse_ethtool_option (iter[0], &wol_flags, &wol_password, &autoneg, &speed, &duplex);
}
}
+ /* ETHTOOL_WAKE_ON_LAN = ignore overrides WoL settings in ETHTOOL_OPTS */
+ wol_value = svGetValueString (ifcfg, "ETHTOOL_WAKE_ON_LAN");
+ if (wol_value) {
+ if (strcmp (wol_value, "ignore") == 0)
+ wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE;
+ else
+ PARSE_WARNING ("invalid ETHTOOL_WAKE_ON_LAN value '%s'", wol_value);
+ }
+
if ( wol_password
&& !NM_FLAGS_HAS (wol_flags, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) {
PARSE_WARNING ("Wake-on-LAN password not expected");
ignore_wol_password = TRUE;
}
+
g_object_set (s_wired,
NM_SETTING_WIRED_WAKE_ON_LAN, wol_flags,
NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, ignore_wol_password ? NULL : wol_password,
+ NM_SETTING_WIRED_AUTO_NEGOTIATE, autoneg,
+ NM_SETTING_WIRED_SPEED, autoneg ? 0 : speed,
+ NM_SETTING_WIRED_DUPLEX, autoneg ? NULL : duplex,
NULL);
}
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
index 1696e1ad43..22454fb347 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
@@ -1008,11 +1008,12 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
NMSettingWired *s_wired;
const char *device_mac, *cloned_mac;
char *tmp;
- const char *nettype, *portname, *ctcprot, *s390_key, *s390_val;
- guint32 mtu, num_opts, i;
+ const char *nettype, *portname, *ctcprot, *s390_key, *s390_val, *duplex;
+ guint32 mtu, num_opts, speed, i;
const char *const *s390_subchannels;
- GString *str;
+ GString *str = NULL;
const char * const *macaddr_blacklist;
+ gboolean auto_negotiate;
NMSettingWiredWakeOnLan wol;
const char *wol_password;
@@ -1101,14 +1102,44 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
g_string_free (str, TRUE);
}
+ /* Stuff ETHTOOL_OPT with required options */
+ str = NULL;
+ auto_negotiate = nm_setting_wired_get_auto_negotiate (s_wired);
+ /* autoneg off + speed 0 + duplex NULL, means we want NM
+ * to skip link configuration which is default. So write
+ * down link config only if we have auto-negotiate true or
+ * a valid value for one among speed and duplex.
+ */
+ if (auto_negotiate) {
+ str = g_string_sized_new (64);
+ g_string_printf (str, "autoneg on");
+ } else {
+ speed = nm_setting_wired_get_speed (s_wired);
+ duplex = nm_setting_wired_get_duplex (s_wired);
+ if (speed || duplex) {
+ str = g_string_sized_new (64);
+ g_string_printf (str, "autoneg off");
+ if (speed)
+ g_string_append_printf (str, " speed %u", speed);
+ if (duplex)
+ g_string_append_printf (str, " duplex %s", duplex);
+ }
+ }
+
wol = nm_setting_wired_get_wake_on_lan (s_wired);
wol_password = nm_setting_wired_get_wake_on_lan_password (s_wired);
+
if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE)
- svSetValue (ifcfg, "ETHTOOL_OPTS", "");
- else if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT)
- svUnsetValue (ifcfg, "ETHTOOL_OPTS");
- else {
- str = g_string_sized_new (30);
+ svSetValue (ifcfg, "ETHTOOL_WAKE_ON_LAN", "ignore");
+ else if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT) {
+ if (!str)
+ svUnsetValue (ifcfg, "ETHTOOL_OPTS");
+ } else {
+ if (!str)
+ str = g_string_sized_new (30);
+ else
+ g_string_append (str, " ");
+
g_string_append (str, "wol ");
if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_PHY))
@@ -1129,10 +1160,12 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
if (wol_password && NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC))
g_string_append_printf (str, "s sopass %s", wol_password);
-
+ }
+ if (str) {
svSetValueString (ifcfg, "ETHTOOL_OPTS", str->str);
g_string_free (str, TRUE);
}
+ /* End ETHTOOL_OPT stuffing */
svSetValueString (ifcfg, "TYPE", TYPE_ETHERNET);