summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancesco Giudici <fgiudici@redhat.com>2018-06-12 12:57:05 +0200
committerFrancesco Giudici <fgiudici@redhat.com>2018-06-15 14:19:50 +0200
commit356addb9e61a0a1f5929ba10cd4084b65cf9df1b (patch)
treec989bc620f728a5677ede9225b0e08a669b0ddf7
parent45170bad5d977ed07b9b5f94073fa369187587f8 (diff)
downloadNetworkManager-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.c62
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;