summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÍñigo Huguet <inigohuguet@hotmail.com>2023-10-18 06:54:00 +0000
committerÍñigo Huguet <inigohuguet@hotmail.com>2023-10-18 06:54:00 +0000
commit2d956f4d51da2d524cd85164de5e9bf0e65de903 (patch)
tree9c415d1572cbb7578f009c955015d5f5c2d68d7f
parent123ca26770306b8fd3fbfd47c3c43a40f7a36cfb (diff)
parent6c41cb3a582d8281b4cf42fda5c27e763dddf85c (diff)
merge: branch 'bg/ethtool-channels'
Add ethtool channels support https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1754
-rw-r--r--src/core/devices/nm-device.c120
-rw-r--r--src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c13
-rw-r--r--src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c5
-rw-r--r--src/libnm-base/nm-base.h20
-rw-r--r--src/libnm-base/nm-ethtool-base.c26
-rw-r--r--src/libnm-base/nm-ethtool-utils-base.h5
-rw-r--r--src/libnm-client-impl/libnm.ver1
-rw-r--r--src/libnm-client-public/nm-ethtool-utils.h5
-rw-r--r--src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in16
-rw-r--r--src/libnm-core-impl/nm-setting-ethtool.c16
-rw-r--r--src/libnm-core-public/nm-setting-ethtool.h3
-rw-r--r--src/libnm-platform/nm-platform-utils.c63
-rw-r--r--src/libnm-platform/nm-platform-utils.h4
-rw-r--r--src/libnm-platform/nm-platform.c25
-rw-r--r--src/libnm-platform/nm-platform.h8
-rw-r--r--src/libnm-platform/nmp-base.h11
-rw-r--r--src/libnmc-setting/nm-meta-setting-desc.c73
-rw-r--r--src/nmcli/gen-metadata-nm-settings-nmcli.c25
-rw-r--r--src/nmcli/gen-metadata-nm-settings-nmcli.xml.in12
19 files changed, 396 insertions, 55 deletions
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 2f7b4f81b8..0ab7d8c922 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -303,6 +303,7 @@ typedef struct {
NMEthtoolCoalesceState *coalesce;
NMEthtoolRingState *ring;
NMEthtoolPauseState *pause;
+ NMEthtoolChannelsState *channels;
} EthtoolState;
typedef enum {
@@ -2385,6 +2386,8 @@ _ethtool_features_reset(NMDevice *self, NMPlatform *platform, EthtoolState *etht
gs_free NMEthtoolFeatureStates *features = NULL;
features = g_steal_pointer(&ethtool_state->features);
+ if (!features)
+ return;
if (!nm_platform_ethtool_set_features(platform,
ethtool_state->ifindex,
@@ -2404,8 +2407,7 @@ _ethtool_features_set(NMDevice *self,
{
gs_free NMEthtoolFeatureStates *features = NULL;
- if (ethtool_state->features)
- _ethtool_features_reset(self, platform, ethtool_state);
+ _ethtool_features_reset(self, platform, ethtool_state);
if (nm_setting_ethtool_init_features(s_ethtool, ethtool_state->requested) == 0)
return;
@@ -2603,6 +2605,104 @@ _ethtool_ring_set(NMDevice *self,
}
static void
+_ethtool_channels_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state)
+{
+ gs_free NMEthtoolChannelsState *channels = NULL;
+
+ nm_assert(NM_IS_DEVICE(self));
+ nm_assert(NM_IS_PLATFORM(platform));
+ nm_assert(ethtool_state);
+
+ channels = g_steal_pointer(&ethtool_state->channels);
+ if (!channels)
+ return;
+
+ if (!nm_platform_ethtool_set_channels(platform, ethtool_state->ifindex, channels))
+ _LOGW(LOGD_DEVICE, "ethtool: failure resetting one or more channels settings");
+ else
+ _LOGD(LOGD_DEVICE, "ethtool: channels settings successfully reset");
+}
+
+static void
+_ethtool_channels_set(NMDevice *self,
+ NMPlatform *platform,
+ EthtoolState *ethtool_state,
+ NMSettingEthtool *s_ethtool)
+{
+ NMEthtoolChannelsState channels_old;
+ NMEthtoolChannelsState channels_new;
+ GHashTable *hash;
+ GHashTableIter iter;
+ const char *name;
+ GVariant *variant;
+ gboolean has_old = FALSE;
+
+ 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->channels);
+
+ 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_channels(ethtool_id))
+ continue;
+
+ nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32));
+
+ if (!has_old) {
+ if (!nm_platform_ethtool_get_link_channels(platform,
+ ethtool_state->ifindex,
+ &channels_old)) {
+ _LOGW(LOGD_DEVICE,
+ "ethtool: failure setting channels options (cannot read existing setting)");
+ return;
+ }
+ has_old = TRUE;
+ channels_new = channels_old;
+ }
+
+ u32 = g_variant_get_uint32(variant);
+
+ switch (ethtool_id) {
+ case NM_ETHTOOL_ID_CHANNELS_RX:
+ channels_new.rx = u32;
+ break;
+ case NM_ETHTOOL_ID_CHANNELS_TX:
+ channels_new.tx = u32;
+ break;
+ case NM_ETHTOOL_ID_CHANNELS_OTHER:
+ channels_new.other = u32;
+ break;
+ case NM_ETHTOOL_ID_CHANNELS_COMBINED:
+ channels_new.combined = u32;
+ break;
+ default:
+ nm_assert_not_reached();
+ }
+ }
+
+ if (!has_old)
+ return;
+
+ ethtool_state->channels = nm_memdup(&channels_old, sizeof(channels_old));
+
+ if (!nm_platform_ethtool_set_channels(platform, ethtool_state->ifindex, &channels_new)) {
+ _LOGW(LOGD_DEVICE, "ethtool: failure setting channels settings");
+ return;
+ }
+
+ _LOGD(LOGD_DEVICE, "ethtool: channels settings successfully set");
+}
+
+static void
_ethtool_pause_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state)
{
gs_free NMEthtoolPauseState *pause = NULL;
@@ -2719,14 +2819,11 @@ _ethtool_state_reset(NMDevice *self)
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);
- if (ethtool_state->ring)
- _ethtool_ring_reset(self, platform, ethtool_state);
- if (ethtool_state->pause)
- _ethtool_pause_reset(self, platform, ethtool_state);
+ _ethtool_features_reset(self, platform, ethtool_state);
+ _ethtool_coalesce_reset(self, platform, ethtool_state);
+ _ethtool_ring_reset(self, platform, ethtool_state);
+ _ethtool_pause_reset(self, platform, ethtool_state);
+ _ethtool_channels_reset(self, platform, ethtool_state);
}
static void
@@ -2761,9 +2858,10 @@ _ethtool_state_set(NMDevice *self)
_ethtool_coalesce_set(self, platform, ethtool_state, s_ethtool);
_ethtool_ring_set(self, platform, ethtool_state, s_ethtool);
_ethtool_pause_set(self, platform, ethtool_state, s_ethtool);
+ _ethtool_channels_set(self, platform, ethtool_state, s_ethtool);
if (ethtool_state->features || ethtool_state->coalesce || ethtool_state->ring
- || ethtool_state->pause)
+ || ethtool_state->pause || ethtool_state->channels)
priv->ethtool_state = g_steal_pointer(&ethtool_state);
}
diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
index 08deaf5abd..516f2fd890 100644
--- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
+++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
@@ -1346,6 +1346,7 @@ write_ethtool_setting(NMConnection *connection, shvarFile *ifcfg, GError **error
guint32 u32;
gboolean b;
gboolean any_option = FALSE;
+ char prop_name[300];
s_con = nm_connection_get_setting_connection(connection);
if (s_con) {
@@ -1426,6 +1427,18 @@ write_ethtool_setting(NMConnection *connection, shvarFile *ifcfg, GError **error
any_option = TRUE;
}
+ is_first = TRUE;
+ for (ethtool_id = _NM_ETHTOOL_ID_CHANNELS_FIRST; ethtool_id <= _NM_ETHTOOL_ID_CHANNELS_LAST;
+ ethtool_id++) {
+ if (nm_setting_option_get_uint32(NM_SETTING(s_ethtool),
+ nm_ethtool_data[ethtool_id]->optname,
+ &u32)) {
+ nm_sprintf_buf(prop_name, "ethtool.%s", nm_ethtool_data[ethtool_id]->optname);
+ set_error_unsupported(error, connection, prop_name, FALSE);
+ return FALSE;
+ }
+ }
+
if (!any_option) {
/* Write an empty dummy "-A" option without arguments. This is to
* ensure that the reader will create an (all default) NMSettingEthtool.
diff --git a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
index 8c1e9d9490..ccfc6ff394 100644
--- a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -3623,6 +3623,11 @@ test_roundtrip_ethtool(void)
optname = nm_ethtool_data[ethtool_id]->optname;
vtype = nm_ethtool_id_get_variant_type(ethtool_id);
+ if (nm_ethtool_optname_is_channels(optname)) {
+ /* Not supported */
+ continue;
+ }
+
if (NM_IN_SET(ethtool_id,
NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX,
NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX)) {
diff --git a/src/libnm-base/nm-base.h b/src/libnm-base/nm-base.h
index 54d5e9e904..88acbcc5b2 100644
--- a/src/libnm-base/nm-base.h
+++ b/src/libnm-base/nm-base.h
@@ -124,14 +124,23 @@ typedef enum {
NM_ETHTOOL_ID_RING_TX,
_NM_ETHTOOL_ID_RING_LAST = NM_ETHTOOL_ID_RING_TX,
- _NM_ETHTOOL_ID_LAST = _NM_ETHTOOL_ID_RING_LAST,
+ _NM_ETHTOOL_ID_CHANNELS_FIRST = _NM_ETHTOOL_ID_RING_LAST + 1,
+ NM_ETHTOOL_ID_CHANNELS_RX = _NM_ETHTOOL_ID_CHANNELS_FIRST,
+ NM_ETHTOOL_ID_CHANNELS_TX,
+ NM_ETHTOOL_ID_CHANNELS_OTHER,
+ NM_ETHTOOL_ID_CHANNELS_COMBINED,
+ _NM_ETHTOOL_ID_CHANNELS_LAST = NM_ETHTOOL_ID_CHANNELS_COMBINED,
+
+ _NM_ETHTOOL_ID_LAST = _NM_ETHTOOL_ID_CHANNELS_LAST,
_NM_ETHTOOL_ID_COALESCE_NUM =
(_NM_ETHTOOL_ID_COALESCE_LAST - _NM_ETHTOOL_ID_COALESCE_FIRST + 1),
_NM_ETHTOOL_ID_FEATURE_NUM = (_NM_ETHTOOL_ID_FEATURE_LAST - _NM_ETHTOOL_ID_FEATURE_FIRST + 1),
_NM_ETHTOOL_ID_RING_NUM = (_NM_ETHTOOL_ID_RING_LAST - _NM_ETHTOOL_ID_RING_FIRST + 1),
_NM_ETHTOOL_ID_PAUSE_NUM = (_NM_ETHTOOL_ID_PAUSE_LAST - _NM_ETHTOOL_ID_PAUSE_FIRST + 1),
- _NM_ETHTOOL_ID_NUM = (_NM_ETHTOOL_ID_LAST - _NM_ETHTOOL_ID_FIRST + 1),
+ _NM_ETHTOOL_ID_CHANNELS_NUM =
+ (_NM_ETHTOOL_ID_CHANNELS_LAST - _NM_ETHTOOL_ID_CHANNELS_FIRST + 1),
+ _NM_ETHTOOL_ID_NUM = (_NM_ETHTOOL_ID_LAST - _NM_ETHTOOL_ID_FIRST + 1),
} NMEthtoolID;
#define _NM_ETHTOOL_ID_FEATURE_AS_IDX(ethtool_id) ((ethtool_id) -_NM_ETHTOOL_ID_FEATURE_FIRST)
@@ -143,6 +152,7 @@ typedef enum {
NM_ETHTOOL_TYPE_FEATURE,
NM_ETHTOOL_TYPE_RING,
NM_ETHTOOL_TYPE_PAUSE,
+ NM_ETHTOOL_TYPE_CHANNELS,
} NMEthtoolType;
/****************************************************************************/
@@ -171,6 +181,12 @@ nm_ethtool_id_is_pause(NMEthtoolID id)
return id >= _NM_ETHTOOL_ID_PAUSE_FIRST && id <= _NM_ETHTOOL_ID_PAUSE_LAST;
}
+static inline gboolean
+nm_ethtool_id_is_channels(NMEthtoolID id)
+{
+ return id >= _NM_ETHTOOL_ID_CHANNELS_FIRST && id <= _NM_ETHTOOL_ID_CHANNELS_LAST;
+}
+
/*****************************************************************************/
typedef enum {
diff --git a/src/libnm-base/nm-ethtool-base.c b/src/libnm-base/nm-ethtool-base.c
index c31cff6f53..25b12cda32 100644
--- a/src/libnm-base/nm-ethtool-base.c
+++ b/src/libnm-base/nm-ethtool-base.c
@@ -106,11 +106,19 @@ const NMEthtoolData *const nm_ethtool_data[_NM_ETHTOOL_ID_NUM + 1] = {
ETHT_DATA(RING_RX_JUMBO),
ETHT_DATA(RING_RX_MINI),
ETHT_DATA(RING_TX),
+ ETHT_DATA(CHANNELS_RX),
+ ETHT_DATA(CHANNELS_TX),
+ ETHT_DATA(CHANNELS_OTHER),
+ ETHT_DATA(CHANNELS_COMBINED),
[_NM_ETHTOOL_ID_NUM] = NULL,
};
static const guint8 _by_name[_NM_ETHTOOL_ID_NUM] = {
/* sorted by optname. */
+ NM_ETHTOOL_ID_CHANNELS_COMBINED,
+ NM_ETHTOOL_ID_CHANNELS_OTHER,
+ NM_ETHTOOL_ID_CHANNELS_RX,
+ NM_ETHTOOL_ID_CHANNELS_TX,
NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX,
NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX,
NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH,
@@ -291,6 +299,8 @@ nm_ethtool_id_to_type(NMEthtoolID id)
return NM_ETHTOOL_TYPE_RING;
if (nm_ethtool_id_is_pause(id))
return NM_ETHTOOL_TYPE_PAUSE;
+ if (nm_ethtool_id_is_channels(id))
+ return NM_ETHTOOL_TYPE_CHANNELS;
return NM_ETHTOOL_TYPE_UNKNOWN;
}
@@ -298,11 +308,17 @@ nm_ethtool_id_to_type(NMEthtoolID id)
const GVariantType *
nm_ethtool_id_get_variant_type(NMEthtoolID ethtool_id)
{
- if (nm_ethtool_id_is_feature(ethtool_id) || nm_ethtool_id_is_pause(ethtool_id))
+ switch (nm_ethtool_id_to_type(ethtool_id)) {
+ case NM_ETHTOOL_TYPE_FEATURE:
+ case NM_ETHTOOL_TYPE_PAUSE:
return G_VARIANT_TYPE_BOOLEAN;
-
- if (nm_ethtool_id_is_coalesce(ethtool_id) || nm_ethtool_id_is_ring(ethtool_id))
+ case NM_ETHTOOL_TYPE_CHANNELS:
+ case NM_ETHTOOL_TYPE_COALESCE:
+ case NM_ETHTOOL_TYPE_RING:
return G_VARIANT_TYPE_UINT32;
-
- return NULL;
+ case NM_ETHTOOL_TYPE_UNKNOWN:
+ nm_assert(ethtool_id == NM_ETHTOOL_ID_UNKNOWN);
+ return NULL;
+ }
+ return nm_assert_unreachable_val(NULL);
}
diff --git a/src/libnm-base/nm-ethtool-utils-base.h b/src/libnm-base/nm-ethtool-utils-base.h
index fa9c30715d..80c640df39 100644
--- a/src/libnm-base/nm-ethtool-utils-base.h
+++ b/src/libnm-base/nm-ethtool-utils-base.h
@@ -104,6 +104,11 @@ G_BEGIN_DECLS
#define NM_ETHTOOL_OPTNAME_PAUSE_RX "pause-rx"
#define NM_ETHTOOL_OPTNAME_PAUSE_TX "pause-tx"
+#define NM_ETHTOOL_OPTNAME_CHANNELS_RX "channels-rx"
+#define NM_ETHTOOL_OPTNAME_CHANNELS_TX "channels-tx"
+#define NM_ETHTOOL_OPTNAME_CHANNELS_OTHER "channels-other"
+#define NM_ETHTOOL_OPTNAME_CHANNELS_COMBINED "channels-combined"
+
/*****************************************************************************/
G_END_DECLS
diff --git a/src/libnm-client-impl/libnm.ver b/src/libnm-client-impl/libnm.ver
index acbfb4a6e6..aeb51d3c26 100644
--- a/src/libnm-client-impl/libnm.ver
+++ b/src/libnm-client-impl/libnm.ver
@@ -1947,4 +1947,5 @@ global:
libnm_1_46_0 {
global:
nm_access_point_get_bandwidth;
+ nm_ethtool_optname_is_channels;
} libnm_1_44_0;
diff --git a/src/libnm-client-public/nm-ethtool-utils.h b/src/libnm-client-public/nm-ethtool-utils.h
index fa9c30715d..80c640df39 100644
--- a/src/libnm-client-public/nm-ethtool-utils.h
+++ b/src/libnm-client-public/nm-ethtool-utils.h
@@ -104,6 +104,11 @@ G_BEGIN_DECLS
#define NM_ETHTOOL_OPTNAME_PAUSE_RX "pause-rx"
#define NM_ETHTOOL_OPTNAME_PAUSE_TX "pause-tx"
+#define NM_ETHTOOL_OPTNAME_CHANNELS_RX "channels-rx"
+#define NM_ETHTOOL_OPTNAME_CHANNELS_TX "channels-tx"
+#define NM_ETHTOOL_OPTNAME_CHANNELS_OTHER "channels-other"
+#define NM_ETHTOOL_OPTNAME_CHANNELS_COMBINED "channels-combined"
+
/*****************************************************************************/
G_END_DECLS
diff --git a/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in b/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in
index 4e17a45baa..d84c6c6e3d 100644
--- a/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in
+++ b/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in
@@ -1292,6 +1292,22 @@
dbus-type="u"
is-setting-option="1"
/>
+ <property name="channels-rx"
+ dbus-type="u"
+ is-setting-option="1"
+ />
+ <property name="channels-tx"
+ dbus-type="u"
+ is-setting-option="1"
+ />
+ <property name="channels-other"
+ dbus-type="u"
+ is-setting-option="1"
+ />
+ <property name="channels-combined"
+ dbus-type="u"
+ is-setting-option="1"
+ />
</setting>
<setting name="generic"
gtype="NMSettingGeneric"
diff --git a/src/libnm-core-impl/nm-setting-ethtool.c b/src/libnm-core-impl/nm-setting-ethtool.c
index ab1ed0e2b6..138e86c02e 100644
--- a/src/libnm-core-impl/nm-setting-ethtool.c
+++ b/src/libnm-core-impl/nm-setting-ethtool.c
@@ -76,6 +76,22 @@ nm_ethtool_optname_is_ring(const char *optname)
}
/**
+ * nm_ethtool_optname_is_channels:
+ * @optname: (nullable): the option name to check
+ *
+ * Checks whether @optname is a valid option name for a channels setting.
+ *
+ * Returns: %TRUE, if @optname is valid
+ *
+ * Since: 1.46
+ */
+gboolean
+nm_ethtool_optname_is_channels(const char *optname)
+{
+ return optname && nm_ethtool_id_is_channels(nm_ethtool_id_get_by_name(optname));
+}
+
+/**
* nm_ethtool_optname_is_pause:
* @optname: (nullable): the option name to check
*
diff --git a/src/libnm-core-public/nm-setting-ethtool.h b/src/libnm-core-public/nm-setting-ethtool.h
index 698dcebe27..47db2573b7 100644
--- a/src/libnm-core-public/nm-setting-ethtool.h
+++ b/src/libnm-core-public/nm-setting-ethtool.h
@@ -26,6 +26,9 @@ gboolean nm_ethtool_optname_is_ring(const char *optname);
NM_AVAILABLE_IN_1_32
gboolean nm_ethtool_optname_is_pause(const char *optname);
+NM_AVAILABLE_IN_1_46
+gboolean nm_ethtool_optname_is_channels(const char *optname);
+
/*****************************************************************************/
#define NM_TYPE_SETTING_ETHTOOL (nm_setting_ethtool_get_type())
diff --git a/src/libnm-platform/nm-platform-utils.c b/src/libnm-platform/nm-platform-utils.c
index 08d82fe87a..32c4732d3d 100644
--- a/src/libnm-platform/nm-platform-utils.c
+++ b/src/libnm-platform/nm-platform-utils.c
@@ -1068,6 +1068,69 @@ nmp_utils_ethtool_set_ring(int ifindex, const NMEthtoolRingState *ring)
}
gboolean
+nmp_utils_ethtool_get_channels(int ifindex, NMEthtoolChannelsState *channels)
+{
+ struct ethtool_channels eth_data;
+
+ g_return_val_if_fail(ifindex > 0, FALSE);
+ g_return_val_if_fail(channels, FALSE);
+
+ eth_data.cmd = ETHTOOL_GCHANNELS;
+
+ if (_ethtool_call_once(ifindex, &eth_data, sizeof(eth_data)) < 0) {
+ nm_log_trace(LOGD_PLATFORM,
+ "ethtool[%d]: %s: failure getting channels settings",
+ ifindex,
+ "get-channels");
+ return FALSE;
+ }
+
+ *channels = (NMEthtoolChannelsState){
+ .rx = eth_data.rx_count,
+ .tx = eth_data.tx_count,
+ .other = eth_data.other_count,
+ .combined = eth_data.combined_count,
+ };
+
+ nm_log_trace(LOGD_PLATFORM,
+ "ethtool[%d]: %s: retrieved kernel channels settings",
+ ifindex,
+ "get-channels");
+ return TRUE;
+}
+
+gboolean
+nmp_utils_ethtool_set_channels(int ifindex, const NMEthtoolChannelsState *channels)
+{
+ struct ethtool_channels eth_data;
+
+ g_return_val_if_fail(ifindex > 0, FALSE);
+ g_return_val_if_fail(channels, FALSE);
+
+ eth_data = (struct ethtool_channels){
+ .cmd = ETHTOOL_SCHANNELS,
+ .rx_count = channels->rx,
+ .tx_count = channels->tx,
+ .other_count = channels->other,
+ .combined_count = channels->combined,
+ };
+
+ if (_ethtool_call_once(ifindex, &eth_data, sizeof(eth_data)) < 0) {
+ nm_log_trace(LOGD_PLATFORM,
+ "ethtool[%d]: %s: failure setting channels settings",
+ ifindex,
+ "set-channels");
+ return FALSE;
+ }
+
+ nm_log_trace(LOGD_PLATFORM,
+ "ethtool[%d]: %s: set kernel channels settings",
+ ifindex,
+ "set-channels");
+ return TRUE;
+}
+
+gboolean
nmp_utils_ethtool_get_pause(int ifindex, NMEthtoolPauseState *pause)
{
struct ethtool_pauseparam eth_data;
diff --git a/src/libnm-platform/nm-platform-utils.h b/src/libnm-platform/nm-platform-utils.h
index 14b09a793e..815d165431 100644
--- a/src/libnm-platform/nm-platform-utils.h
+++ b/src/libnm-platform/nm-platform-utils.h
@@ -54,6 +54,10 @@ gboolean nmp_utils_ethtool_get_ring(int ifindex, NMEthtoolRingState *ring);
gboolean nmp_utils_ethtool_set_ring(int ifindex, const NMEthtoolRingState *ring);
+gboolean nmp_utils_ethtool_get_channels(int ifindex, NMEthtoolChannelsState *channels);
+
+gboolean nmp_utils_ethtool_set_channels(int ifindex, const NMEthtoolChannelsState *channels);
+
gboolean nmp_utils_ethtool_get_pause(int ifindex, NMEthtoolPauseState *pause);
gboolean nmp_utils_ethtool_set_pause(int ifindex, const NMEthtoolPauseState *pause);
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 7bd9de4121..1b513d34be 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -3581,6 +3581,31 @@ nm_platform_ethtool_set_ring(NMPlatform *self, int ifindex, const NMEthtoolRingS
}
gboolean
+nm_platform_ethtool_get_link_channels(NMPlatform *self,
+ int ifindex,
+ NMEthtoolChannelsState *channels)
+{
+ _CHECK_SELF_NETNS(self, klass, netns, FALSE);
+
+ g_return_val_if_fail(ifindex > 0, FALSE);
+ g_return_val_if_fail(channels, FALSE);
+
+ return nmp_utils_ethtool_get_channels(ifindex, channels);
+}
+
+gboolean
+nm_platform_ethtool_set_channels(NMPlatform *self,
+ int ifindex,
+ const NMEthtoolChannelsState *channels)
+{
+ _CHECK_SELF_NETNS(self, klass, netns, FALSE);
+
+ g_return_val_if_fail(ifindex > 0, FALSE);
+
+ return nmp_utils_ethtool_set_channels(ifindex, channels);
+}
+
+gboolean
nm_platform_ethtool_get_link_pause(NMPlatform *self, int ifindex, NMEthtoolPauseState *pause)
{
_CHECK_SELF_NETNS(self, klass, netns, FALSE);
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
index 6ad0d15bd0..bc5bc5e8b4 100644
--- a/src/libnm-platform/nm-platform.h
+++ b/src/libnm-platform/nm-platform.h
@@ -2567,6 +2567,14 @@ gboolean nm_platform_ethtool_get_link_ring(NMPlatform *self, int ifindex, NMEtht
gboolean
nm_platform_ethtool_set_ring(NMPlatform *self, int ifindex, const NMEthtoolRingState *ring);
+gboolean nm_platform_ethtool_get_link_channels(NMPlatform *self,
+ int ifindex,
+ NMEthtoolChannelsState *channels);
+
+gboolean nm_platform_ethtool_set_channels(NMPlatform *self,
+ int ifindex,
+ const NMEthtoolChannelsState *channels);
+
gboolean
nm_platform_ethtool_get_link_pause(NMPlatform *self, int ifindex, NMEthtoolPauseState *pause);
diff --git a/src/libnm-platform/nmp-base.h b/src/libnm-platform/nmp-base.h
index ffe5936300..eeaad024a0 100644
--- a/src/libnm-platform/nmp-base.h
+++ b/src/libnm-platform/nmp-base.h
@@ -93,16 +93,12 @@ typedef struct {
const NMEthtoolFeatureState states_list[];
} NMEthtoolFeatureStates;
-/*****************************************************************************/
-
typedef struct {
guint32
s[_NM_ETHTOOL_ID_COALESCE_NUM /* indexed by (NMEthtoolID - _NM_ETHTOOL_ID_COALESCE_FIRST) */
];
} NMEthtoolCoalesceState;
-/*****************************************************************************/
-
typedef struct {
guint32 rx_pending;
guint32 rx_mini_pending;
@@ -116,6 +112,13 @@ typedef struct {
bool tx : 1;
} NMEthtoolPauseState;
+typedef struct {
+ guint32 rx;
+ guint32 tx;
+ guint32 other;
+ guint32 combined;
+} NMEthtoolChannelsState;
+
/*****************************************************************************/
typedef struct _NMPNetns NMPNetns;
diff --git a/src/libnmc-setting/nm-meta-setting-desc.c b/src/libnmc-setting/nm-meta-setting-desc.c
index 4a6626d039..18bd407768 100644
--- a/src/libnmc-setting/nm-meta-setting-desc.c
+++ b/src/libnmc-setting/nm-meta-setting-desc.c
@@ -4421,26 +4421,32 @@ _get_fcn_ethtool(ARGS_GET_FCN)
RETURN_UNSUPPORTED_GET_TYPE();
- if (nm_ethtool_id_is_coalesce(ethtool_id) || nm_ethtool_id_is_ring(ethtool_id)) {
+ switch (nm_ethtool_id_to_type(ethtool_id)) {
+ case NM_ETHTOOL_TYPE_CHANNELS:
+ case NM_ETHTOOL_TYPE_COALESCE:
+ case NM_ETHTOOL_TYPE_RING:
if (!nm_setting_option_get_uint32(setting, nm_ethtool_data[ethtool_id]->optname, &u32)) {
NM_SET_OUT(out_is_default, TRUE);
return NULL;
}
RETURN_STR_TO_FREE(nm_strdup_int(u32));
- }
-
- nm_assert(nm_ethtool_id_is_feature(ethtool_id) || nm_ethtool_id_is_pause(ethtool_id));
+ case NM_ETHTOOL_TYPE_FEATURE:
+ case NM_ETHTOOL_TYPE_PAUSE:
+ if (!nm_setting_option_get_boolean(setting, nm_ethtool_data[ethtool_id]->optname, &b)) {
+ NM_SET_OUT(out_is_default, TRUE);
+ return NULL;
+ }
- if (!nm_setting_option_get_boolean(setting, nm_ethtool_data[ethtool_id]->optname, &b)) {
- NM_SET_OUT(out_is_default, TRUE);
- return NULL;
+ s = b ? N_("on") : N_("off");
+ if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
+ s = gettext(s);
+ return s;
+ case NM_ETHTOOL_TYPE_UNKNOWN:
+ nm_assert_not_reached();
}
- s = b ? N_("on") : N_("off");
- if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
- s = gettext(s);
- return s;
+ return NULL;
}
static gboolean
@@ -4453,7 +4459,10 @@ _set_fcn_ethtool(ARGS_SET_FCN)
if (_SET_FCN_DO_RESET_DEFAULT(property_info, modifier, value))
goto do_unset;
- if (nm_ethtool_id_is_coalesce(ethtool_id) || nm_ethtool_id_is_ring(ethtool_id)) {
+ switch (nm_ethtool_id_to_type(ethtool_id)) {
+ case NM_ETHTOOL_TYPE_CHANNELS:
+ case NM_ETHTOOL_TYPE_COALESCE:
+ case NM_ETHTOOL_TYPE_RING:
i64 = _nm_utils_ascii_str_to_int64(value, 10, 0, G_MAXUINT32, -1);
if (i64 == -1) {
nm_utils_error_set(
@@ -4468,25 +4477,27 @@ _set_fcn_ethtool(ARGS_SET_FCN)
nm_setting_option_set_uint32(setting, nm_ethtool_data[ethtool_id]->optname, i64);
return TRUE;
- }
-
- nm_assert(nm_ethtool_id_is_feature(ethtool_id) || nm_ethtool_id_is_pause(ethtool_id));
+ case NM_ETHTOOL_TYPE_FEATURE:
+ case NM_ETHTOOL_TYPE_PAUSE:
+ if (!nmc_string_to_ternary_full(value,
+ NMC_STRING_TO_TERNARY_FLAGS_IGNORE_FOR_DEFAULT,
+ &t,
+ NULL)) {
+ nm_utils_error_set(error,
+ NM_UTILS_ERROR_INVALID_ARGUMENT,
+ _("'%s' is not valid; use 'on', 'off', or 'ignore'"),
+ value);
+ return FALSE;
+ }
+ if (t == NM_TERNARY_DEFAULT)
+ goto do_unset;
- if (!nmc_string_to_ternary_full(value,
- NMC_STRING_TO_TERNARY_FLAGS_IGNORE_FOR_DEFAULT,
- &t,
- NULL)) {
- nm_utils_error_set(error,
- NM_UTILS_ERROR_INVALID_ARGUMENT,
- _("'%s' is not valid; use 'on', 'off', or 'ignore'"),
- value);
- return FALSE;
+ nm_setting_option_set_boolean(setting, nm_ethtool_data[ethtool_id]->optname, !!t);
+ return TRUE;
+ case NM_ETHTOOL_TYPE_UNKNOWN:
+ nm_assert_not_reached();
}
- if (t == NM_TERNARY_DEFAULT)
- goto do_unset;
-
- nm_setting_option_set_boolean(setting, nm_ethtool_data[ethtool_id]->optname, !!t);
- return TRUE;
+ return FALSE;
do_unset:
nm_setting_option_set(setting, nm_ethtool_data[ethtool_id]->optname, NULL);
@@ -5919,6 +5930,10 @@ static const NMMetaPropertyInfo *const property_infos_ETHTOOL[] = {
PROPERTY_INFO_ETHTOOL (RING_RX_JUMBO),
PROPERTY_INFO_ETHTOOL (RING_RX_MINI),
PROPERTY_INFO_ETHTOOL (RING_TX),
+ PROPERTY_INFO_ETHTOOL (CHANNELS_RX),
+ PROPERTY_INFO_ETHTOOL (CHANNELS_TX),
+ PROPERTY_INFO_ETHTOOL (CHANNELS_OTHER),
+ PROPERTY_INFO_ETHTOOL (CHANNELS_COMBINED),
NULL,
};
diff --git a/src/nmcli/gen-metadata-nm-settings-nmcli.c b/src/nmcli/gen-metadata-nm-settings-nmcli.c
index f29c91805c..f8dc303628 100644
--- a/src/nmcli/gen-metadata-nm-settings-nmcli.c
+++ b/src/nmcli/gen-metadata-nm-settings-nmcli.c
@@ -111,10 +111,18 @@ get_ethtool_format(const NMMetaPropertyInfo *prop_info)
ethtool_id = prop_info->property_typ_data->subtype.ethtool.ethtool_id;
- if (nm_ethtool_id_is_coalesce(ethtool_id) || nm_ethtool_id_is_ring(ethtool_id))
+ switch (nm_ethtool_id_to_type(ethtool_id)) {
+ case NM_ETHTOOL_TYPE_CHANNELS:
+ case NM_ETHTOOL_TYPE_COALESCE:
+ case NM_ETHTOOL_TYPE_RING:
return g_strdup("integer");
- else if (nm_ethtool_id_is_feature(ethtool_id) || nm_ethtool_id_is_pause(ethtool_id))
+ case NM_ETHTOOL_TYPE_FEATURE:
+ case NM_ETHTOOL_TYPE_PAUSE:
return g_strdup("ternary");
+ case NM_ETHTOOL_TYPE_UNKNOWN:
+ nm_assert_not_reached();
+ };
+
return NULL;
}
@@ -301,10 +309,19 @@ append_ethtool_valid_values(const NMMetaPropertyInfo *prop_info, GPtrArray *vali
ethtool_id = prop_info->property_typ_data->subtype.ethtool.ethtool_id;
- if (nm_ethtool_id_is_coalesce(ethtool_id) || nm_ethtool_id_is_ring(ethtool_id))
+ switch (nm_ethtool_id_to_type(ethtool_id)) {
+ case NM_ETHTOOL_TYPE_CHANNELS:
+ case NM_ETHTOOL_TYPE_COALESCE:
+ case NM_ETHTOOL_TYPE_RING:
g_ptr_array_add(valid_values, g_strdup_printf("0 - %u", G_MAXUINT32));
- else if (nm_ethtool_id_is_feature(ethtool_id) || nm_ethtool_id_is_pause(ethtool_id))
+ break;
+ case NM_ETHTOOL_TYPE_FEATURE:
+ case NM_ETHTOOL_TYPE_PAUSE:
append_vals(valid_values, "on", "off", "ignore");
+ break;
+ case NM_ETHTOOL_TYPE_UNKNOWN:
+ nm_assert_not_reached();
+ }
}
static void
diff --git a/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in b/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
index e61897e9d9..82304a409a 100644
--- a/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
+++ b/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
@@ -1040,6 +1040,18 @@
<property name="ring-tx"
format="integer"
values="0 - 4294967295" />
+ <property name="channels-rx"
+ format="integer"
+ values="0 - 4294967295" />
+ <property name="channels-tx"
+ format="integer"
+ values="0 - 4294967295" />
+ <property name="channels-other"
+ format="integer"
+ values="0 - 4294967295" />
+ <property name="channels-combined"
+ format="integer"
+ values="0 - 4294967295" />
</setting>
<setting name="generic" >
</setting>