summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Cardace <acardace@redhat.com>2020-05-07 17:13:46 +0200
committerAntonio Cardace <acardace@redhat.com>2020-05-13 10:15:23 +0200
commite2be41cbbefc2b58d4ced977c89d54898bd82374 (patch)
tree1249aa6d314d757cbd4e3704cdde6657ba7112f8
parentd8f551cf4a443c980f0f2ee15097cd58c43b2165 (diff)
downloadNetworkManager-ac/ethtool_opts.tar.gz
nm-device: apply ethtool coalesce settings when activating a connectionac/ethtool_opts
nm-device now applies ethtool coalesce settings during stage 2 "device config" of the connection activation. Coalesce settings will be then restored (according to what the state was before the connection got activated on the device) when the connection is deactivated during the device cleanup. One thing to be noted is that unset coalesce settings (in the profile) will not be touched at all by NetworkManager so that if the NIC driver sets some default values these will be preserved unless specifically overridden by the connection profile. https://bugzilla.redhat.com/show_bug.cgi?id=1614700
-rw-r--r--src/devices/nm-device.c227
1 files changed, 186 insertions, 41 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index fb926c945d..de72b1d15a 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -185,6 +185,7 @@ typedef struct {
int ifindex;
NMEthtoolFeatureStates *features;
NMTernary requested[_NM_ETHTOOL_ID_FEATURE_NUM];
+ NMEthtoolCoalesceStates *coalesce;
} EthtoolState;
/*****************************************************************************/
@@ -812,64 +813,47 @@ NM_UTILS_LOOKUP_STR_DEFINE (mtu_source_to_str, NMDeviceMtuSource,
/*****************************************************************************/
static void
-_ethtool_state_reset (NMDevice *self)
+_ethtool_features_reset (NMDevice *self,
+ NMPlatform *platform,
+ EthtoolState *ethtool_state)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ gs_free NMEthtoolFeatureStates *features;
- if (priv->ethtool_state) {
- gs_free NMEthtoolFeatureStates *features = priv->ethtool_state->features;
- gs_free EthtoolState *ethtool_state = g_steal_pointer (&priv->ethtool_state);
+ features = g_steal_pointer (&ethtool_state->features);
- if (!nm_platform_ethtool_set_features (nm_device_get_platform (self),
- ethtool_state->ifindex,
- features,
- ethtool_state->requested,
- FALSE))
- _LOGW (LOGD_DEVICE, "ethtool: failure resetting one or more offload features");
- else
- _LOGD (LOGD_DEVICE, "ethtool: offload features successfully reset");
- }
+ if (!nm_platform_ethtool_set_features (platform,
+ ethtool_state->ifindex,
+ features,
+ ethtool_state->requested,
+ FALSE))
+ _LOGW (LOGD_DEVICE, "ethtool: failure resetting one or more offload features");
+ else
+ _LOGD (LOGD_DEVICE, "ethtool: offload features successfully reset");
}
static void
-_ethtool_state_set (NMDevice *self)
+_ethtool_features_set (NMDevice *self,
+ NMPlatform *platform,
+ EthtoolState *ethtool_state,
+ NMSettingEthtool *s_ethtool)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
- int ifindex;
- NMConnection *connection;
- NMSettingEthtool *s_ethtool;
- NMPlatform *platform;
- gs_free EthtoolState *ethtool_state = NULL;
gs_free NMEthtoolFeatureStates *features = NULL;
- _ethtool_state_reset (self);
-
- connection = nm_device_get_applied_connection (self);
- if (!connection)
- return;
-
- ifindex = nm_device_get_ip_ifindex (self);
- if (ifindex <= 0)
- return;
+ if (ethtool_state->features)
+ _ethtool_features_reset (self, platform, ethtool_state);
- s_ethtool = NM_SETTING_ETHTOOL (nm_connection_get_setting (connection, NM_TYPE_SETTING_ETHTOOL));
- if (!s_ethtool)
- return;
-
- ethtool_state = g_new (EthtoolState, 1);
if (nm_setting_ethtool_init_features (s_ethtool, ethtool_state->requested) == 0)
return;
- platform = nm_device_get_platform (self);
-
- features = nm_platform_ethtool_get_link_features (platform, ifindex);
+ features = nm_platform_ethtool_get_link_features (platform,
+ ethtool_state->ifindex);
if (!features) {
_LOGW (LOGD_DEVICE, "ethtool: failure setting offload features (cannot read features)");
return;
}
if (!nm_platform_ethtool_set_features (platform,
- ifindex,
+ ethtool_state->ifindex,
features,
ethtool_state->requested,
TRUE))
@@ -877,9 +861,170 @@ _ethtool_state_set (NMDevice *self)
else
_LOGD (LOGD_DEVICE, "ethtool: offload features successfully set");
- ethtool_state->ifindex = ifindex;
ethtool_state->features = g_steal_pointer (&features);
- priv->ethtool_state = g_steal_pointer (&ethtool_state);
+}
+
+static gboolean
+_ethtool_init_coalesce (NMDevice *self,
+ NMPlatform *platform,
+ NMSettingEthtool *s_ethtool,
+ NMEthtoolCoalesceStates *coalesce)
+{
+ GHashTable *hash;
+ GHashTableIter iter;
+ const char *name;
+ GVariant *variant;
+ gsize n_coalesce_set = 0;
+
+ nm_assert (self);
+ nm_assert (platform);
+ nm_assert (coalesce);
+ nm_assert (NM_IS_SETTING_ETHTOOL (s_ethtool));
+
+ hash = _nm_setting_gendata_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_platform_ethtool_init_coalesce (platform,
+ coalesce,
+ name,
+ g_variant_get_uint32(variant))) {
+ _LOGW (LOGD_DEVICE, "ethtool: invalid coalesce setting %s", name);
+ return FALSE;
+ }
+ ++n_coalesce_set;
+
+ }
+
+ return (!!n_coalesce_set);
+}
+
+
+
+static void
+_ethtool_coalesce_reset (NMDevice *self,
+ NMPlatform *platform,
+ EthtoolState *ethtool_state)
+{
+ gs_free NMEthtoolCoalesceStates *coalesce = NULL;
+
+ nm_assert (NM_IS_DEVICE (self));
+ nm_assert (NM_IS_PLATFORM (platform));
+ nm_assert (ethtool_state);
+
+ coalesce = g_steal_pointer (&ethtool_state->coalesce);
+
+ if (!nm_platform_ethtool_set_coalesce (platform,
+ ethtool_state->ifindex,
+ coalesce,
+ FALSE))
+ _LOGW (LOGD_DEVICE, "ethtool: failure resetting one or more coalesce settings");
+ else
+ _LOGD (LOGD_DEVICE, "ethtool: coalesce settings successfully reset");
+}
+
+static void
+_ethtool_coalesce_set (NMDevice *self,
+ NMPlatform *platform,
+ EthtoolState *ethtool_state,
+ NMSettingEthtool *s_ethtool)
+{
+ gs_free NMEthtoolCoalesceStates *coalesce = NULL;
+
+ nm_assert (ethtool_state);
+ nm_assert (NM_IS_DEVICE (self));
+ nm_assert (NM_IS_PLATFORM (platform));
+ nm_assert (NM_IS_SETTING_ETHTOOL (s_ethtool));
+
+ coalesce = nm_platform_ethtool_get_link_coalesce (platform,
+ ethtool_state->ifindex);
+
+ if (!coalesce) {
+ _LOGW (LOGD_DEVICE, "ethtool: failure getting coalesce settings (cannot read)");
+ return;
+ }
+
+ if (!_ethtool_init_coalesce (self,
+ platform,
+ s_ethtool,
+ coalesce))
+ return;
+
+ if (!nm_platform_ethtool_set_coalesce (platform,
+ ethtool_state->ifindex,
+ coalesce,
+ TRUE)) {
+ _LOGW (LOGD_DEVICE, "ethtool: failure setting coalesce settings");
+ return;
+ }
+ _LOGD (LOGD_DEVICE, "ethtool: coalesce settings successfully set");
+
+ ethtool_state->coalesce = g_steal_pointer (&coalesce);
+}
+
+static void
+_ethtool_state_reset (NMDevice *self)
+{
+ NMPlatform *platform = nm_device_get_platform (self);
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ gs_free EthtoolState *ethtool_state = g_steal_pointer (&priv->ethtool_state);
+
+ if (!ethtool_state)
+ return;
+
+ if (ethtool_state->features)
+ _ethtool_features_reset (self, platform, ethtool_state);
+ if (ethtool_state->coalesce)
+ _ethtool_coalesce_reset (self, platform, ethtool_state);
+}
+
+
+
+static void
+_ethtool_state_set (NMDevice *self)
+{
+ int ifindex;
+ NMPlatform *platform;
+ NMConnection *connection;
+ NMSettingEthtool *s_ethtool;
+ gs_free EthtoolState *ethtool_state = NULL;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+
+ ifindex = nm_device_get_ip_ifindex (self);
+ if (ifindex <= 0)
+ return;
+
+ platform = nm_device_get_platform (self);
+ nm_assert (platform);
+
+ connection = nm_device_get_applied_connection (self);
+ if (!connection)
+ return;
+
+ s_ethtool = NM_SETTING_ETHTOOL (nm_connection_get_setting (connection, NM_TYPE_SETTING_ETHTOOL));
+ if (!s_ethtool)
+ return;
+
+ ethtool_state = g_new0 (EthtoolState, 1);
+ ethtool_state->ifindex = ifindex;
+
+ _ethtool_features_set (self,
+ platform,
+ ethtool_state,
+ s_ethtool);
+ _ethtool_coalesce_set (self,
+ platform,
+ ethtool_state,
+ s_ethtool);
+
+ if ( ethtool_state->features
+ || ethtool_state->coalesce)
+ priv->ethtool_state = g_steal_pointer (&ethtool_state);
}
/*****************************************************************************/