diff options
author | Francesco Giudici <fgiudici@redhat.com> | 2018-06-12 12:57:05 +0200 |
---|---|---|
committer | Francesco Giudici <fgiudici@redhat.com> | 2018-06-15 14:19:50 +0200 |
commit | 356addb9e61a0a1f5929ba10cd4084b65cf9df1b (patch) | |
tree | c989bc620f728a5677ede9225b0e08a669b0ddf7 | |
parent | 45170bad5d977ed07b9b5f94073fa369187587f8 (diff) | |
download | NetworkManager-356addb9e61a0a1f5929ba10cd4084b65cf9df1b.tar.gz |
platform: allow to force the advertised auto-negotiation link value
This will only work for network devices supporting the BASE-T specification.
-rw-r--r-- | src/platform/nm-platform-utils.c | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index 114bf4b349..0d224443fa 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -384,6 +384,40 @@ nmp_utils_ethtool_get_link_settings (int ifindex, return TRUE; } + +#define ADVERTISED_INVALID 0 +#define BASET_ALL_MODES ( ADVERTISED_10baseT_Half \ + | ADVERTISED_10baseT_Full \ + | ADVERTISED_100baseT_Half \ + | ADVERTISED_100baseT_Full \ + | ADVERTISED_1000baseT_Half \ + | ADVERTISED_1000baseT_Full \ + | ADVERTISED_10000baseT_Full ) + +static inline guint32 +get_baset_mode (guint32 speed, NMPlatformLinkDuplexType duplex) +{ + if (duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN) + return ADVERTISED_INVALID; + + if (duplex == NM_PLATFORM_LINK_DUPLEX_HALF) { + switch (speed) { + case 10: return ADVERTISED_10baseT_Half; + case 100: return ADVERTISED_100baseT_Half; + case 1000: return ADVERTISED_1000baseT_Half; + default: return ADVERTISED_INVALID; + } + } else { + switch (speed) { + case 10: return ADVERTISED_10baseT_Full; + case 100: return ADVERTISED_100baseT_Full; + case 1000: return ADVERTISED_1000baseT_Full; + case 10000: return ADVERTISED_10000baseT_Full; + default: return ADVERTISED_INVALID; + } + } +} + gboolean nmp_utils_ethtool_set_link_settings (int ifindex, gboolean autoneg, @@ -395,6 +429,8 @@ nmp_utils_ethtool_set_link_settings (int ifindex, }; g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail ( (speed && duplex != NM_PLATFORM_LINK_DUPLEX_UNKNOWN) + || (!speed && duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN), FALSE); /* retrieve first current settings */ if (!ethtool_get (ifindex, &edata)) @@ -404,7 +440,31 @@ nmp_utils_ethtool_set_link_settings (int ifindex, edata.cmd = ETHTOOL_SSET; if (autoneg) { edata.autoneg = AUTONEG_ENABLE; - edata.advertising = edata.supported; + if (!speed) + edata.advertising = edata.supported; + else { + guint32 mode; + + mode = get_baset_mode (speed, duplex); + + if (!mode) { + nm_log_trace (LOGD_PLATFORM, + "ethtool[%d]: %uBASE-T %s duplex mode cannot be advertised", + ifindex, + speed, + nm_platform_link_duplex_type_to_string (duplex)); + return FALSE; + } + if (!(edata.supported & mode)) { + nm_log_trace (LOGD_PLATFORM, + "ethtool[%d]: device does not support %uBASE-T %s duplex mode", + ifindex, + speed, + nm_platform_link_duplex_type_to_string (duplex)); + return FALSE; + } + edata.advertising = (edata.supported & ~BASET_ALL_MODES) | mode; + } } else { edata.autoneg = AUTONEG_DISABLE; |