Thomas Haller 2020-05-29 12:49:14 +02:00
commit 31516a47bd
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
4 changed files with 108 additions and 98 deletions

View file

@ -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;

View file

@ -950,50 +950,6 @@ _ethtool_coalesce_set (NMDevice *self,
_LOGD (LOGD_DEVICE, "ethtool: coalesce settings successfully set");
}
static gboolean
_ethtool_init_ring (NMDevice *self,
NMPlatform *platform,
NMSettingEthtool *s_ethtool,
NMEthtoolRingState *ring)
{
GHashTable *hash;
GHashTableIter iter;
const char *name;
GVariant *variant;
gsize n_ring_set = 0;
nm_assert (self);
nm_assert (platform);
nm_assert (ring);
nm_assert (NM_IS_SETTING_ETHTOOL (s_ethtool));
hash = _nm_setting_option_hash (NM_SETTING (s_ethtool), FALSE);
if (!hash)
return FALSE;
g_hash_table_iter_init (&iter, hash);
while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) {
if (!g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32))
continue;
if (!nm_ethtool_optname_is_ring (name))
continue;
if (!nm_platform_ethtool_init_ring (platform,
ring,
name,
g_variant_get_uint32(variant))) {
_LOGW (LOGD_DEVICE, "ethtool: invalid ring setting %s", name);
return FALSE;
}
++n_ring_set;
}
return !!n_ring_set;
}
static void
_ethtool_ring_reset (NMDevice *self,
NMPlatform *platform,
@ -1025,25 +981,64 @@ _ethtool_ring_set (NMDevice *self,
{
NMEthtoolRingState ring_old;
NMEthtoolRingState ring_new;
GHashTable *hash;
GHashTableIter iter;
const char *name;
GVariant *variant;
gboolean has_old = FALSE;
nm_assert (ethtool_state);
nm_assert (NM_IS_DEVICE (self));
nm_assert (NM_IS_PLATFORM (platform));
nm_assert (NM_IS_SETTING_ETHTOOL (s_ethtool));
nm_assert (ethtool_state);
nm_assert (!ethtool_state->ring);
if (!nm_platform_ethtool_get_link_ring (platform,
ethtool_state->ifindex,
&ring_old)) {
_LOGW (LOGD_DEVICE, "ethtool: failure getting ring settings (cannot read)");
hash = _nm_setting_option_hash (NM_SETTING (s_ethtool), FALSE);
if (!hash)
return;
g_hash_table_iter_init (&iter, hash);
while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) {
NMEthtoolID ethtool_id = nm_ethtool_id_get_by_name (name);
guint32 u32;
if (!nm_ethtool_id_is_ring (ethtool_id))
continue;
nm_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32));
if (!has_old) {
if (!nm_platform_ethtool_get_link_ring (platform,
ethtool_state->ifindex,
&ring_old)) {
_LOGW (LOGD_DEVICE, "ethtool: failure setting ring options (cannot read existing setting)");
return;
}
has_old = TRUE;
ring_new = ring_old;
}
u32 = g_variant_get_uint32 (variant);
switch (ethtool_id) {
case NM_ETHTOOL_ID_RING_RX:
ring_new.rx_pending = u32;
break;
case NM_ETHTOOL_ID_RING_RX_JUMBO:
ring_new.rx_jumbo_pending = u32;
break;
case NM_ETHTOOL_ID_RING_RX_MINI:
ring_new.rx_mini_pending = u32;
break;
case NM_ETHTOOL_ID_RING_TX:
ring_new.tx_pending = u32;
break;
default:
nm_assert_not_reached ();
}
}
ring_new = ring_old;
if (!_ethtool_init_ring (self,
platform,
s_ethtool,
&ring_new))
if (!has_old)
return;
ethtool_state->ring = nm_memdup (&ring_old, sizeof (ring_old));
@ -1076,8 +1071,6 @@ _ethtool_state_reset (NMDevice *self)
_ethtool_ring_reset (self, platform, ethtool_state);
}
static void
_ethtool_state_set (NMDevice *self)
{

View file

@ -3252,41 +3252,6 @@ nm_platform_ethtool_get_link_ring (NMPlatform *self,
return nmp_utils_ethtool_get_ring (ifindex, ring);
}
gboolean
nm_platform_ethtool_init_ring (NMPlatform *self,
NMEthtoolRingState *ring,
const char *option_name,
guint32 value)
{
NMEthtoolID ethtool_id;
g_return_val_if_fail (ring, FALSE);
g_return_val_if_fail (option_name, FALSE);
ethtool_id = nm_ethtool_id_get_by_name (option_name);
g_return_val_if_fail (nm_ethtool_id_is_ring (ethtool_id), FALSE);
switch (ethtool_id) {
case NM_ETHTOOL_ID_RING_RX:
ring->rx_pending = value;
break;
case NM_ETHTOOL_ID_RING_RX_JUMBO:
ring->rx_jumbo_pending = value;
break;
case NM_ETHTOOL_ID_RING_RX_MINI:
ring->rx_mini_pending = value;
break;
case NM_ETHTOOL_ID_RING_TX:
ring->tx_pending = value;
break;
default:
g_return_val_if_reached (FALSE);
}
return TRUE;
}
gboolean
nm_platform_ethtool_set_ring (NMPlatform *self,
int ifindex,

View file

@ -1975,11 +1975,6 @@ gboolean nm_platform_ethtool_get_link_ring (NMPlatform *self,
int ifindex,
NMEthtoolRingState *ring);
gboolean nm_platform_ethtool_init_ring (NMPlatform *self,
NMEthtoolRingState *ring,
const char *option_name,
guint32 value);
gboolean nm_platform_ethtool_set_ring (NMPlatform *self,
int ifindex,
const NMEthtoolRingState *ring);