about summary refs log tree commit diff
path: root/src/devices/nm-device-ethernet.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2020-06-28 18:58:14 +0200
committerMichael Biebl <biebl@debian.org>2020-06-28 18:58:14 +0200
commita54ac63bbf9b2c71026ac9028a8ffaf186cf3c82 (patch)
tree6a32883bd916c4096357b35298beff6db8bcd0b5 /src/devices/nm-device-ethernet.c
parent45e8e1149027529194982212c804c0468aa01d98 (diff)
New upstream version 1.25.90 upstream/1.25.90
Diffstat (limited to 'src/devices/nm-device-ethernet.c')
-rw-r--r--src/devices/nm-device-ethernet.c59
1 files changed, 58 insertions, 1 deletions
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index 7556bb27..9e7601f0 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -100,7 +100,15 @@ typedef struct _NMDeviceEthernetPrivate {
 	DcbWait       dcb_wait;
 	guint         dcb_timeout_id;
 
+	guint32       ethtool_prev_speed;
+
+	NMPlatformLinkDuplexType ethtool_prev_duplex:3;
+
 	bool          dcb_handle_carrier_changes:1;
+
+	bool          ethtool_prev_set:1;
+	bool          ethtool_prev_autoneg:1;
+
 } NMDeviceEthernetPrivate;
 
 NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceEthernet,
@@ -882,6 +890,7 @@ static void
 link_negotiation_set (NMDevice *device)
 {
 	NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device);
+	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
 	NMSettingWired *s_wired;
 	gboolean autoneg = TRUE;
 	gboolean link_autoneg;
@@ -925,7 +934,7 @@ link_negotiation_set (NMDevice *device)
 	    && !duplex)
 		_LOGD (LOGD_DEVICE, "set-link: configure auto-negotiation");
 	else {
-		_LOGD (LOGD_DEVICE, "set-link: configure %snegotiation (%u Mbit%s - %s duplex%s)",
+		_LOGD (LOGD_DEVICE, "set-link: configure %snegotiation (%u Mbit%s, %s duplex%s)",
 		       autoneg ? "auto-" : "static ",
 		       speed ?: link_speed,
 		       speed ? "" : "*",
@@ -935,6 +944,14 @@ link_negotiation_set (NMDevice *device)
 		       duplex ? "" : "*");
 	}
 
+	if (!priv->ethtool_prev_set) {
+		/* remember the values we had before setting it. */
+		priv->ethtool_prev_autoneg = link_autoneg;
+		priv->ethtool_prev_speed = link_speed;
+		priv->ethtool_prev_duplex = link_duplex;
+		priv->ethtool_prev_set = TRUE;
+	}
+
 	if (!nm_platform_ethtool_set_link_settings (nm_device_get_platform (device),
 	                                            nm_device_get_ifindex (device),
 	                                            autoneg,
@@ -964,6 +981,28 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 	NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device);
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
 
+	if (nm_device_sys_iface_state_is_external_or_assume (device)) {
+		if (   !priv->ethtool_prev_set
+		    && !nm_device_sys_iface_state_is_external (device)) {
+			NMSettingWired *s_wired;
+
+			/* During restart of NetworkManager service we forget the original auto
+			 * negotiation settings. When taking over a device, remember to reset
+			 * the "default" during deactivate. */
+			s_wired = nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRED);
+			if (   s_wired
+			    && (   nm_setting_wired_get_auto_negotiate (s_wired)
+			        || nm_setting_wired_get_speed (s_wired)
+			        || nm_setting_wired_get_duplex (s_wired))) {
+				priv->ethtool_prev_set = TRUE;
+				priv->ethtool_prev_autoneg = TRUE;
+				priv->ethtool_prev_speed = 0;
+				priv->ethtool_prev_duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN;
+			}
+		}
+		return NM_ACT_STAGE_RETURN_SUCCESS;
+	}
+
 	link_negotiation_set (device);
 
 	/* If we're re-activating a PPPoE connection a short while after
@@ -1525,6 +1564,23 @@ deactivate (NMDevice *device)
 	/* Set last PPPoE connection time */
 	if (nm_device_get_applied_setting (device, NM_TYPE_SETTING_PPPOE))
 		priv->last_pppoe_time = nm_utils_get_monotonic_timestamp_sec ();
+
+	if (priv->ethtool_prev_set) {
+		priv->ethtool_prev_set = FALSE;
+
+		_LOGD (LOGD_DEVICE, "set-link: reset %snegotiation (%u Mbit, %s duplex)",
+		       priv->ethtool_prev_autoneg ? "auto-" : "static ",
+		       priv->ethtool_prev_speed,
+		       nm_platform_link_duplex_type_to_string (priv->ethtool_prev_duplex));
+		if (!nm_platform_ethtool_set_link_settings (nm_device_get_platform (device),
+		                                            nm_device_get_ifindex (device),
+		                                            priv->ethtool_prev_autoneg,
+		                                            priv->ethtool_prev_speed,
+		                                            priv->ethtool_prev_duplex)) {
+			_LOGW (LOGD_DEVICE, "set-link: failure to reset link negotiation");
+			return;
+		}
+	}
 }
 
 static gboolean
@@ -1914,6 +1970,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
 	device_class->complete_connection = complete_connection;
 	device_class->new_default_connection = new_default_connection;
 
+	device_class->act_stage1_prepare_also_for_external_or_assume = TRUE;
 	device_class->act_stage1_prepare = act_stage1_prepare;
 	device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE;
 	device_class->act_stage2_config = act_stage2_config;