diff options
author | Francesco Giudici <fgiudici@redhat.com> | 2016-09-10 16:58:10 +0200 |
---|---|---|
committer | Francesco Giudici <fgiudici@redhat.com> | 2016-11-22 15:24:47 +0100 |
commit | 173819b73db3f76f97c021a5b25def6c6886a64e (patch) | |
tree | 13074880732464e590a34260b2e3db176b51bffa | |
parent | 61faa5080e47b75d3ca6d93a88afbdb49d2347f8 (diff) | |
download | NetworkManager-173819b73db3f76f97c021a5b25def6c6886a64e.tar.gz |
device/ethernet: check and apply link negotiation properties
This will allow to enforce link mode (autonegotiation, speed and duplex)
as specified in 802-3-ethernet properties.
-rw-r--r-- | src/devices/nm-device-ethernet.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index d01176b235..fb6467a23f 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -782,6 +782,97 @@ supplicant_interface_init (NMDeviceEthernet *self) return TRUE; } +static const char * +link_duplex_to_string (NMPlatformLinkDuplexType duplex) +{ + switch (duplex) { + case NM_PLATFORM_LINK_DUPLEX_FULL: + return "full"; + break; + case NM_PLATFORM_LINK_DUPLEX_HALF: + return "half"; + break; + default: + return "unknown"; + break; + } +} + +static NMPlatformLinkDuplexType +link_duplex_to_platform (const char *duplex) +{ + if (!duplex) + return NM_PLATFORM_LINK_DUPLEX_UNSET; + + if (nm_streq (duplex, "full")) + return NM_PLATFORM_LINK_DUPLEX_FULL; + + if (nm_streq (duplex, "half")) + return NM_PLATFORM_LINK_DUPLEX_HALF; + + return NM_PLATFORM_LINK_DUPLEX_UNKNOWN; +} + +static void +link_negotiation_set (NMDevice *device) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); + NMSettingWired *s_wired; + gboolean autoneg = TRUE, link_autoneg; + NMPlatformLinkDuplexType link_duplex, duplex = NM_PLATFORM_LINK_DUPLEX_UNSET; + guint32 speed = 0, link_speed; + + s_wired = (NMSettingWired *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRED); + if (s_wired) { + autoneg = nm_setting_wired_get_auto_negotiate (s_wired); + if (!autoneg) { + speed = nm_setting_wired_get_speed (s_wired); + duplex = link_duplex_to_platform (nm_setting_wired_get_duplex (s_wired)); + if (!speed && !duplex) { + _LOGD (LOGD_DEVICE, "set-link: ignore link negotiation"); + return; + } + } + } + + if (!nm_platform_ethtool_get_link_settings (NM_PLATFORM_GET, nm_device_get_iface (device), + &link_autoneg, &link_speed, &link_duplex)) { + _LOGW (LOGD_DEVICE, "set-link: unable to retrieve link negotiation"); + return; + } + + /* If link negotiation setting are already in place do nothing and return with success */ + if (autoneg != link_autoneg) + goto set_link; + + if (speed && (speed != link_speed)) + goto set_link; + + if (duplex && (duplex != link_duplex)) + goto set_link; + + _LOGW (LOGD_DEVICE, "set-link: link negotiation is already configured"); + return; + +set_link: + if (!nm_platform_ethtool_set_link_settings (NM_PLATFORM_GET, + nm_device_get_iface (device), + autoneg, + speed, + duplex)) { + _LOGW (LOGD_DEVICE, "set-link: failure to set link negotiation"); + return; + } + + if (autoneg) + _LOGD (LOGD_DEVICE, "set-link: configure autonegotiation"); + else { + _LOGD (LOGD_DEVICE, "set-link: configure static negotiation (%u Mbit - %s duplex)", + speed ?: link_speed, + duplex ? link_duplex_to_string (duplex) : link_duplex_to_string (link_duplex)); + } +} + static gboolean pppoe_reconnect_delay (gpointer user_data) { @@ -807,6 +898,8 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; + link_negotiation_set (dev); + if (!nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE)) return NM_ACT_STAGE_RETURN_FAILURE; |