diff options
author | Francesco Giudici <fgiudici@redhat.com> | 2016-09-14 17:48:13 +0200 |
---|---|---|
committer | Francesco Giudici <fgiudici@redhat.com> | 2016-11-22 15:24:47 +0100 |
commit | 12b9d30ae625000c578d6b4f4bcf8c3a119132dc (patch) | |
tree | ba9b27b777761c52ad75e96e7b44847ad2869fe0 | |
parent | de88a467757d619429f5b74c4d683e42b01b94d9 (diff) | |
download | NetworkManager-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.
-rw-r--r-- | libnm-core/nm-connection.c | 25 | ||||
-rw-r--r-- | libnm-core/nm-setting-wired.c | 51 | ||||
-rw-r--r-- | src/NetworkManager.ver-orig | 3 | ||||
-rw-r--r-- | src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 87 | ||||
-rw-r--r-- | src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 51 |
5 files changed, 195 insertions, 22 deletions
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index b7bca4f90f..e9b66dad2f 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -718,6 +718,30 @@ _normalize_connection_slave_type (NMConnection *self) } static gboolean +_normalize_ethernet_link_neg (NMConnection *self) +{ + NMSettingWired *s_wired = nm_connection_get_setting_wired (self); + + if (s_wired) { + gboolean autoneg = nm_setting_wired_get_auto_negotiate (s_wired); + guint speed = nm_setting_wired_get_speed (s_wired); + const char *duplex = nm_setting_wired_get_duplex (s_wired); + + if ((autoneg) && (speed || duplex)) { + speed = 0; + duplex = NULL; + g_object_set (s_wired, + NM_SETTING_WIRED_SPEED, speed, + NM_SETTING_WIRED_DUPLEX, duplex, + NULL); + return TRUE; + } + } + + return FALSE; +} + +static gboolean _normalize_ip_config (NMConnection *self, GHashTable *parameters) { NMSettingConnection *s_con = nm_connection_get_setting_connection (self); @@ -1207,6 +1231,7 @@ nm_connection_normalize (NMConnection *connection, was_modified |= _normalize_connection_uuid (connection); was_modified |= _normalize_connection_type (connection); was_modified |= _normalize_connection_slave_type (connection); + was_modified |= _normalize_ethernet_link_neg (connection); was_modified |= _normalize_ip_config (connection, parameters); was_modified |= _normalize_infiniband_mtu (connection, parameters); was_modified |= _normalize_bond_mode (connection, parameters); diff --git a/libnm-core/nm-setting-wired.c b/libnm-core/nm-setting-wired.c index b27643d9a1..04b0f5ebbe 100644 --- a/libnm-core/nm-setting-wired.c +++ b/libnm-core/nm-setting-wired.c @@ -759,6 +759,27 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + /* Normalizable errors */ + + if (priv->auto_negotiate) { + if (priv->duplex) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("when link autonegotiation is enabled no duplex value is accepted")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_DUPLEX); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + if (priv->speed) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("when link autonegotiation is enabled speed should be 0")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_SPEED); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + } + return TRUE; } @@ -779,6 +800,12 @@ compare_property (NMSetting *setting, return parent_class->compare_property (setting, other, prop_spec, flags); } +static GVariant * +_override_autoneg_get (NMSetting *setting, const char *property) +{ + return g_variant_new_boolean (nm_setting_wired_get_auto_negotiate ((NMSettingWired *) setting)); +} + /*****************************************************************************/ static void @@ -1001,8 +1028,9 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) **/ /* ---ifcfg-rh--- * property: speed - * variable: (none) - * description: The property is not saved by the plugin. + * variable: ETHTOOL_OPTS + * description: Fixed speed for the ethernet link. It is added as "speed" + * parameter in the ETHTOOL_OPTS variable. * ---end--- */ g_object_class_install_property @@ -1021,8 +1049,9 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) **/ /* ---ifcfg-rh--- * property: duplex - * variable: (none) - * description: The property is not saved by the plugin. + * variable: ETHTOOL_OPTS + * description: Fixed duplex mode for the ethernet link. It is added as + * "duplex" parameter in the ETHOOL_OPTS variable. * ---end--- */ g_object_class_install_property @@ -1041,17 +1070,25 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) **/ /* ---ifcfg-rh--- * property: auto-negotiate - * variable: (none) - * description: The property is not saved by the plugin. + * variable: ETHTOOL_OPTS + * description: Wether link speed and duplex autonegotiation is enabled. + * It is not saved only if disabled and no values are provided for the + * "speed" and "duplex" parameters (skips link configuration). * ---end--- */ g_object_class_install_property (object_class, PROP_AUTO_NEGOTIATE, g_param_spec_boolean (NM_SETTING_WIRED_AUTO_NEGOTIATE, "", "", - TRUE, + FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + _nm_setting_class_override_property (setting_class, + NM_SETTING_WIRED_AUTO_NEGOTIATE, + G_VARIANT_TYPE_BOOLEAN, + _override_autoneg_get, + NULL, + NULL); /** * NMSettingWired:mac-address: 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); |