diff options
author | Johannes Zink <j.zink@pengutronix.de> | 2023-10-25 16:52:47 +0200 |
---|---|---|
committer | Johannes Zink <j.zink@pengutronix.de> | 2023-11-03 15:41:21 +0000 |
commit | 3165d9a2deeaa2d0cd5fcb827ee32ec36818078e (patch) | |
tree | 54764963dc7753ff0163d3d5ff8a5d7ae7e3162b | |
parent | 384241851265b91abf32d3d6d24c013454f3c4c3 (diff) |
ethtool: introduce EEE support
Some Applications require to explicitly enable or disable EEE.
Therefore introduce EEE (Energy Efficient Ethernet) support with:
* ethtool.eee on/off
Unit test case included.
Signed-off-by: Johannes Zink <j.zink@pengutronix.de>
20 files changed, 318 insertions, 3 deletions
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 8031bd5dd4..d0cb5990d4 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -305,6 +305,7 @@ typedef struct { NMEthtoolRingState *ring; NMEthtoolPauseState *pause; NMEthtoolChannelsState *channels; + NMEthtoolEEEState *eee; } EthtoolState; typedef enum { @@ -2723,6 +2724,25 @@ _ethtool_pause_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool } static void +_ethtool_eee_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state) +{ + gs_free NMEthtoolEEEState *eee = NULL; + + nm_assert(NM_IS_DEVICE(self)); + nm_assert(NM_IS_PLATFORM(platform)); + nm_assert(ethtool_state); + + eee = g_steal_pointer(ðtool_state->eee); + if (!eee) + return; + + if (!nm_platform_ethtool_set_eee(platform, ethtool_state->ifindex, eee)) + _LOGW(LOGD_DEVICE, "ethtool: failure resetting eee settings"); + else + _LOGD(LOGD_DEVICE, "ethtool: eee settings successfully reset"); +} + +static void _ethtool_pause_set(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state, @@ -2811,6 +2831,73 @@ _ethtool_pause_set(NMDevice *self, } static void +_ethtool_eee_set(NMDevice *self, + NMPlatform *platform, + EthtoolState *ethtool_state, + NMSettingEthtool *s_ethtool) +{ + NMEthtoolEEEState eee_old; + NMEthtoolEEEState eee_new; + GHashTable *hash; + GHashTableIter iter; + const char *name; + GVariant *variant; + gboolean has_old = FALSE; + NMTernary eee = NM_TERNARY_DEFAULT; + + 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->eee); + + 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); + + if (!nm_ethtool_id_is_eee(ethtool_id)) + continue; + + nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)); + + if (!has_old) { + if (!nm_platform_ethtool_get_link_eee(platform, ethtool_state->ifindex, &eee_old)) { + _LOGW(LOGD_DEVICE, + "ethtool: failure setting eee options (cannot read " + "existing setting)"); + return; + } + has_old = TRUE; + } + + if (ethtool_id == NM_ETHTOOL_ID_EEE_ENABLED) + eee = g_variant_get_boolean(variant); + else + nm_assert_not_reached(); + } + + if (!has_old) + return; + + eee_new = eee_old; + if (eee != NM_TERNARY_DEFAULT) + eee_new.enabled = !!eee; + + ethtool_state->eee = nm_memdup(&eee_old, sizeof(eee_old)); + + if (!nm_platform_ethtool_set_eee(platform, ethtool_state->ifindex, &eee_new)) { + _LOGW(LOGD_DEVICE, "ethtool: failure setting eee settings"); + return; + } + + _LOGD(LOGD_DEVICE, "ethtool: eee settings successfully set"); +} + +static void _ethtool_state_reset(NMDevice *self) { NMPlatform *platform = nm_device_get_platform(self); @@ -2825,6 +2912,7 @@ _ethtool_state_reset(NMDevice *self) _ethtool_ring_reset(self, platform, ethtool_state); _ethtool_pause_reset(self, platform, ethtool_state); _ethtool_channels_reset(self, platform, ethtool_state); + _ethtool_eee_reset(self, platform, ethtool_state); } static void @@ -2860,9 +2948,10 @@ _ethtool_state_set(NMDevice *self) _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); + _ethtool_eee_set(self, platform, ethtool_state, s_ethtool); if (ethtool_state->features || ethtool_state->coalesce || ethtool_state->ring - || ethtool_state->pause || ethtool_state->channels) + || ethtool_state->pause || ethtool_state->channels || ethtool_state->eee) priv->ethtool_state = g_steal_pointer(ðtool_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 516f2fd890..fae336b703 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 @@ -1439,6 +1439,18 @@ write_ethtool_setting(NMConnection *connection, shvarFile *ifcfg, GError **error } } + is_first = TRUE; + for (ethtool_id = _NM_ETHTOOL_ID_EEE_FIRST; ethtool_id <= _NM_ETHTOOL_ID_EEE_LAST; + ethtool_id++) { + if (nm_setting_option_get_boolean(NM_SETTING(s_ethtool), + nm_ethtool_data[ethtool_id]->optname, + &b)) { + 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 ccfc6ff394..d4374eb5e6 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,7 +3623,7 @@ 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)) { + if (nm_ethtool_optname_is_channels(optname) || nm_ethtool_optname_is_eee(optname)) { /* Not supported */ continue; } diff --git a/src/libnm-base/nm-base.h b/src/libnm-base/nm-base.h index 88acbcc5b2..34944408ca 100644 --- a/src/libnm-base/nm-base.h +++ b/src/libnm-base/nm-base.h @@ -117,7 +117,11 @@ typedef enum { NM_ETHTOOL_ID_PAUSE_TX, _NM_ETHTOOL_ID_PAUSE_LAST = NM_ETHTOOL_ID_PAUSE_TX, - _NM_ETHTOOL_ID_RING_FIRST = _NM_ETHTOOL_ID_PAUSE_LAST + 1, + _NM_ETHTOOL_ID_EEE_FIRST = _NM_ETHTOOL_ID_PAUSE_LAST + 1, + NM_ETHTOOL_ID_EEE_ENABLED = _NM_ETHTOOL_ID_EEE_FIRST, + _NM_ETHTOOL_ID_EEE_LAST = NM_ETHTOOL_ID_EEE_ENABLED, + + _NM_ETHTOOL_ID_RING_FIRST = _NM_ETHTOOL_ID_EEE_LAST + 1, NM_ETHTOOL_ID_RING_RX = _NM_ETHTOOL_ID_RING_FIRST, NM_ETHTOOL_ID_RING_RX_JUMBO, NM_ETHTOOL_ID_RING_RX_MINI, @@ -153,6 +157,7 @@ typedef enum { NM_ETHTOOL_TYPE_RING, NM_ETHTOOL_TYPE_PAUSE, NM_ETHTOOL_TYPE_CHANNELS, + NM_ETHTOOL_TYPE_EEE, } NMEthtoolType; /****************************************************************************/ @@ -187,6 +192,12 @@ nm_ethtool_id_is_channels(NMEthtoolID id) return id >= _NM_ETHTOOL_ID_CHANNELS_FIRST && id <= _NM_ETHTOOL_ID_CHANNELS_LAST; } +static inline gboolean +nm_ethtool_id_is_eee(NMEthtoolID id) +{ + return id >= _NM_ETHTOOL_ID_EEE_FIRST && id <= _NM_ETHTOOL_ID_EEE_LAST; +} + /*****************************************************************************/ typedef enum { diff --git a/src/libnm-base/nm-ethtool-base.c b/src/libnm-base/nm-ethtool-base.c index 25b12cda32..a02b901869 100644 --- a/src/libnm-base/nm-ethtool-base.c +++ b/src/libnm-base/nm-ethtool-base.c @@ -41,6 +41,7 @@ const NMEthtoolData *const nm_ethtool_data[_NM_ETHTOOL_ID_NUM + 1] = { ETHT_DATA(COALESCE_TX_USECS_HIGH), ETHT_DATA(COALESCE_TX_USECS_IRQ), ETHT_DATA(COALESCE_TX_USECS_LOW), + ETHT_DATA(EEE_ENABLED), ETHT_DATA(FEATURE_ESP_HW_OFFLOAD), ETHT_DATA(FEATURE_ESP_TX_CSUM_HW_OFFLOAD), ETHT_DATA(FEATURE_FCOE_MTU), @@ -141,6 +142,7 @@ static const guint8 _by_name[_NM_ETHTOOL_ID_NUM] = { NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH, NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ, NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW, + NM_ETHTOOL_ID_EEE_ENABLED, NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD, NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD, NM_ETHTOOL_ID_FEATURE_FCOE_MTU, @@ -301,6 +303,8 @@ nm_ethtool_id_to_type(NMEthtoolID id) return NM_ETHTOOL_TYPE_PAUSE; if (nm_ethtool_id_is_channels(id)) return NM_ETHTOOL_TYPE_CHANNELS; + if (nm_ethtool_id_is_eee(id)) + return NM_ETHTOOL_TYPE_EEE; return NM_ETHTOOL_TYPE_UNKNOWN; } @@ -311,6 +315,7 @@ nm_ethtool_id_get_variant_type(NMEthtoolID ethtool_id) switch (nm_ethtool_id_to_type(ethtool_id)) { case NM_ETHTOOL_TYPE_FEATURE: case NM_ETHTOOL_TYPE_PAUSE: + case NM_ETHTOOL_TYPE_EEE: return G_VARIANT_TYPE_BOOLEAN; case NM_ETHTOOL_TYPE_CHANNELS: case NM_ETHTOOL_TYPE_COALESCE: diff --git a/src/libnm-base/nm-ethtool-utils-base.h b/src/libnm-base/nm-ethtool-utils-base.h index 80c640df39..6b7a5937bc 100644 --- a/src/libnm-base/nm-ethtool-utils-base.h +++ b/src/libnm-base/nm-ethtool-utils-base.h @@ -109,6 +109,7 @@ G_BEGIN_DECLS #define NM_ETHTOOL_OPTNAME_CHANNELS_OTHER "channels-other" #define NM_ETHTOOL_OPTNAME_CHANNELS_COMBINED "channels-combined" +#define NM_ETHTOOL_OPTNAME_EEE_ENABLED "eee" /*****************************************************************************/ G_END_DECLS diff --git a/src/libnm-client-impl/libnm.ver b/src/libnm-client-impl/libnm.ver index aeb51d3c26..a92f8991ad 100644 --- a/src/libnm-client-impl/libnm.ver +++ b/src/libnm-client-impl/libnm.ver @@ -1948,4 +1948,5 @@ libnm_1_46_0 { global: nm_access_point_get_bandwidth; nm_ethtool_optname_is_channels; + nm_ethtool_optname_is_eee; } 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 80c640df39..6b7a5937bc 100644 --- a/src/libnm-client-public/nm-ethtool-utils.h +++ b/src/libnm-client-public/nm-ethtool-utils.h @@ -109,6 +109,7 @@ G_BEGIN_DECLS #define NM_ETHTOOL_OPTNAME_CHANNELS_OTHER "channels-other" #define NM_ETHTOOL_OPTNAME_CHANNELS_COMBINED "channels-combined" +#define NM_ETHTOOL_OPTNAME_EEE_ENABLED "eee" /*****************************************************************************/ 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 d84c6c6e3d..78394a0432 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 @@ -1276,6 +1276,10 @@ dbus-type="b" is-setting-option="1" /> + <property name="eee" + dbus-type="b" + is-setting-option="1" + /> <property name="ring-rx" dbus-type="u" is-setting-option="1" diff --git a/src/libnm-core-impl/nm-setting-ethtool.c b/src/libnm-core-impl/nm-setting-ethtool.c index 138e86c02e..06c9c12b0d 100644 --- a/src/libnm-core-impl/nm-setting-ethtool.c +++ b/src/libnm-core-impl/nm-setting-ethtool.c @@ -92,6 +92,21 @@ nm_ethtool_optname_is_channels(const char *optname) } /** + * nm_ethtool_optname_is_eee: + * @optname: (nullable): the option name to check + * + * Checks whether @optname is a valid option name for an eee setting. + * + * Returns: %TRUE, if @optname is valid + * + * Since: 1.46 + */ +gboolean +nm_ethtool_optname_is_eee(const char *optname) +{ + return optname && nm_ethtool_id_is_eee(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-impl/tests/test-setting.c b/src/libnm-core-impl/tests/test-setting.c index b30758ffab..1a8910d8d3 100644 --- a/src/libnm-core-impl/tests/test-setting.c +++ b/src/libnm-core-impl/tests/test-setting.c @@ -2303,6 +2303,79 @@ test_ethtool_pause(void) g_assert_true(out_value); } +static void +test_ethtool_eee(void) +{ + gs_unref_object NMConnection *con = NULL; + gs_unref_object NMConnection *con2 = NULL; + gs_unref_object NMConnection *con3 = NULL; + gs_unref_variant GVariant *variant = NULL; + gs_free_error GError *error = NULL; + nm_auto_unref_keyfile GKeyFile *keyfile = NULL; + NMSettingConnection *s_con; + NMSettingEthtool *s_ethtool; + NMSettingEthtool *s_ethtool2; + NMSettingEthtool *s_ethtool3; + gboolean out_value; + + con = + nmtst_create_minimal_connection("ethtool-eee", NULL, NM_SETTING_WIRED_SETTING_NAME, &s_con); + s_ethtool = NM_SETTING_ETHTOOL(nm_setting_ethtool_new()); + nm_connection_add_setting(con, NM_SETTING(s_ethtool)); + + nm_setting_option_set_boolean(NM_SETTING(s_ethtool), NM_ETHTOOL_OPTNAME_EEE_ENABLED, FALSE); + + g_assert_true(nm_setting_option_get_boolean(NM_SETTING(s_ethtool), + NM_ETHTOOL_OPTNAME_EEE_ENABLED, + &out_value)); + g_assert_true(!out_value); + + nmtst_connection_normalize(con); + + variant = nm_connection_to_dbus(con, NM_CONNECTION_SERIALIZE_ALL); + + con2 = nm_simple_connection_new_from_dbus(variant, &error); + nmtst_assert_success(con2, error); + + s_ethtool2 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con2, NM_TYPE_SETTING_ETHTOOL)); + + g_assert_true(nm_setting_option_get_boolean(NM_SETTING(s_ethtool2), + NM_ETHTOOL_OPTNAME_EEE_ENABLED, + &out_value)); + g_assert_true(!out_value); + + nmtst_assert_connection_verifies_without_normalization(con2); + + nmtst_assert_connection_equals(con, FALSE, con2, FALSE); + + con2 = nm_simple_connection_new_from_dbus(variant, &error); + nmtst_assert_success(con2, error); + + keyfile = nm_keyfile_write(con, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error); + nmtst_assert_success(keyfile, error); + + con3 = nm_keyfile_read(keyfile, + "/ignored/current/working/directory/for/loading/relative/paths", + NM_KEYFILE_HANDLER_FLAGS_NONE, + NULL, + NULL, + &error); + nmtst_assert_success(con3, error); + + nm_keyfile_read_ensure_id(con3, "unused-because-already-has-id"); + nm_keyfile_read_ensure_uuid(con3, "unused-because-already-has-uuid"); + + nmtst_connection_normalize(con3); + + nmtst_assert_connection_equals(con, FALSE, con3, FALSE); + + s_ethtool3 = NM_SETTING_ETHTOOL(nm_connection_get_setting(con3, NM_TYPE_SETTING_ETHTOOL)); + + g_assert_true(nm_setting_option_get_boolean(NM_SETTING(s_ethtool3), + NM_ETHTOOL_OPTNAME_EEE_ENABLED, + &out_value)); + g_assert_true(!out_value); +} /*****************************************************************************/ static void @@ -5326,6 +5399,7 @@ main(int argc, char **argv) g_test_add_func("/libnm/settings/ethtool/coalesce", test_ethtool_coalesce); g_test_add_func("/libnm/settings/ethtool/ring", test_ethtool_ring); g_test_add_func("/libnm/settings/ethtool/pause", test_ethtool_pause); + g_test_add_func("/libnm/settings/ethtool/eee", test_ethtool_eee); g_test_add_func("/libnm/settings/6lowpan/1", test_6lowpan_1); diff --git a/src/libnm-core-public/nm-setting-ethtool.h b/src/libnm-core-public/nm-setting-ethtool.h index 47db2573b7..fe1fbc0e39 100644 --- a/src/libnm-core-public/nm-setting-ethtool.h +++ b/src/libnm-core-public/nm-setting-ethtool.h @@ -29,6 +29,9 @@ gboolean nm_ethtool_optname_is_pause(const char *optname); NM_AVAILABLE_IN_1_46 gboolean nm_ethtool_optname_is_channels(const char *optname); +NM_AVAILABLE_IN_1_46 +gboolean nm_ethtool_optname_is_eee(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 bba822a7b3..fc68fbb148 100644 --- a/src/libnm-platform/nm-platform-utils.c +++ b/src/libnm-platform/nm-platform-utils.c @@ -1162,6 +1162,35 @@ nmp_utils_ethtool_get_pause(int ifindex, NMEthtoolPauseState *pause) } gboolean +nmp_utils_ethtool_get_eee(int ifindex, NMEthtoolEEEState *eee) +{ + struct ethtool_eee eth_data; + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(eee, FALSE); + + eth_data.cmd = ETHTOOL_GEEE; + if (_ethtool_call_handle(&shandle, ð_data, sizeof(struct ethtool_eee)) != 0) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: failure getting eee settings", + ifindex, + "get-eee"); + return FALSE; + } + + *eee = (NMEthtoolEEEState){ + .enabled = eth_data.eee_enabled == 1, + }; + + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: retrieved kernel eee settings", + ifindex, + "get-eee"); + return TRUE; +} + +gboolean nmp_utils_ethtool_set_pause(int ifindex, const NMEthtoolPauseState *pause) { struct ethtool_pauseparam eth_data; @@ -1188,6 +1217,36 @@ nmp_utils_ethtool_set_pause(int ifindex, const NMEthtoolPauseState *pause) return TRUE; } +gboolean +nmp_utils_ethtool_set_eee(int ifindex, const NMEthtoolEEEState *eee) +{ + struct ethtool_eee eth_data; + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(eee, FALSE); + + eth_data.cmd = ETHTOOL_GEEE; + if (_ethtool_call_handle(&shandle, ð_data, sizeof(struct ethtool_eee)) != 0) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: failure getting eee settings", + ifindex, + "get-eee"); + return FALSE; + } + + eth_data.cmd = ETHTOOL_SEEE, eth_data.eee_enabled = eee->enabled ? 1 : 0; + + if (_ethtool_call_handle(&shandle, ð_data, sizeof(struct ethtool_eee)) != 0) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: failure setting eee settings", + ifindex, + "set-eee"); + return FALSE; + } + nm_log_trace(LOGD_PLATFORM, "ethtool[%d]: %s: set kernel eee settings", ifindex, "set-eee"); + return TRUE; +} /*****************************************************************************/ gboolean diff --git a/src/libnm-platform/nm-platform-utils.h b/src/libnm-platform/nm-platform-utils.h index 815d165431..18fc615557 100644 --- a/src/libnm-platform/nm-platform-utils.h +++ b/src/libnm-platform/nm-platform-utils.h @@ -62,6 +62,10 @@ gboolean nmp_utils_ethtool_get_pause(int ifindex, NMEthtoolPauseState *pause); gboolean nmp_utils_ethtool_set_pause(int ifindex, const NMEthtoolPauseState *pause); +gboolean nmp_utils_ethtool_get_eee(int ifindex, NMEthtoolEEEState *eee); + +gboolean nmp_utils_ethtool_set_eee(int ifindex, const NMEthtoolEEEState *eee); + /*****************************************************************************/ gboolean nmp_utils_mii_supports_carrier_detect(int ifindex); diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index d5acec98f5..68d41daa98 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -3629,6 +3629,17 @@ nm_platform_ethtool_get_link_pause(NMPlatform *self, int ifindex, NMEthtoolPause } gboolean +nm_platform_ethtool_get_link_eee(NMPlatform *self, int ifindex, NMEthtoolEEEState *eee) +{ + _CHECK_SELF_NETNS(self, klass, netns, FALSE); + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(eee, FALSE); + + return nmp_utils_ethtool_get_eee(ifindex, eee); +} + +gboolean nm_platform_ethtool_set_pause(NMPlatform *self, int ifindex, const NMEthtoolPauseState *pause) { _CHECK_SELF_NETNS(self, klass, netns, FALSE); @@ -3638,6 +3649,15 @@ nm_platform_ethtool_set_pause(NMPlatform *self, int ifindex, const NMEthtoolPaus return nmp_utils_ethtool_set_pause(ifindex, pause); } +gboolean +nm_platform_ethtool_set_eee(NMPlatform *self, int ifindex, const NMEthtoolEEEState *eee) +{ + _CHECK_SELF_NETNS(self, klass, netns, FALSE); + + g_return_val_if_fail(ifindex > 0, FALSE); + + return nmp_utils_ethtool_set_eee(ifindex, eee); +} /*****************************************************************************/ const NMDedupMultiHeadEntry * diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index 81d2b9d6fe..557b4190a8 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -2578,9 +2578,13 @@ gboolean nm_platform_ethtool_set_channels(NMPlatform *self, gboolean nm_platform_ethtool_get_link_pause(NMPlatform *self, int ifindex, NMEthtoolPauseState *pause); +gboolean nm_platform_ethtool_get_link_eee(NMPlatform *self, int ifindex, NMEthtoolEEEState *eee); + gboolean nm_platform_ethtool_set_pause(NMPlatform *self, int ifindex, const NMEthtoolPauseState *pause); +gboolean nm_platform_ethtool_set_eee(NMPlatform *self, int ifindex, const NMEthtoolEEEState *eee); + void nm_platform_ip4_dev_route_blacklist_set(NMPlatform *self, int ifindex, GPtrArray *ip4_dev_route_blacklist); diff --git a/src/libnm-platform/nmp-base.h b/src/libnm-platform/nmp-base.h index eeaad024a0..578efa51b3 100644 --- a/src/libnm-platform/nmp-base.h +++ b/src/libnm-platform/nmp-base.h @@ -119,6 +119,10 @@ typedef struct { guint32 combined; } NMEthtoolChannelsState; +typedef struct { + bool enabled : 1; +} NMEthtoolEEEState; + /*****************************************************************************/ 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 18bd407768..2e9593f81e 100644 --- a/src/libnmc-setting/nm-meta-setting-desc.c +++ b/src/libnmc-setting/nm-meta-setting-desc.c @@ -4433,6 +4433,7 @@ _get_fcn_ethtool(ARGS_GET_FCN) RETURN_STR_TO_FREE(nm_strdup_int(u32)); case NM_ETHTOOL_TYPE_FEATURE: case NM_ETHTOOL_TYPE_PAUSE: + case NM_ETHTOOL_TYPE_EEE: if (!nm_setting_option_get_boolean(setting, nm_ethtool_data[ethtool_id]->optname, &b)) { NM_SET_OUT(out_is_default, TRUE); return NULL; @@ -4479,6 +4480,7 @@ _set_fcn_ethtool(ARGS_SET_FCN) return TRUE; case NM_ETHTOOL_TYPE_FEATURE: case NM_ETHTOOL_TYPE_PAUSE: + case NM_ETHTOOL_TYPE_EEE: if (!nmc_string_to_ternary_full(value, NMC_STRING_TO_TERNARY_FLAGS_IGNORE_FOR_DEFAULT, &t, @@ -5926,6 +5928,7 @@ static const NMMetaPropertyInfo *const property_infos_ETHTOOL[] = { DEFINE_PROPERTY_TYP_DATA_SUBTYPE (ethtool, .ethtool_id = NM_ETHTOOL_ID_PAUSE_TX) ), + PROPERTY_INFO_ETHTOOL (EEE_ENABLED), PROPERTY_INFO_ETHTOOL (RING_RX), PROPERTY_INFO_ETHTOOL (RING_RX_JUMBO), PROPERTY_INFO_ETHTOOL (RING_RX_MINI), diff --git a/src/nmcli/gen-metadata-nm-settings-nmcli.c b/src/nmcli/gen-metadata-nm-settings-nmcli.c index 2def909565..a7f7bb681b 100644 --- a/src/nmcli/gen-metadata-nm-settings-nmcli.c +++ b/src/nmcli/gen-metadata-nm-settings-nmcli.c @@ -118,6 +118,7 @@ get_ethtool_format(const NMMetaPropertyInfo *prop_info) return g_strdup("integer"); case NM_ETHTOOL_TYPE_FEATURE: case NM_ETHTOOL_TYPE_PAUSE: + case NM_ETHTOOL_TYPE_EEE: return g_strdup("ternary"); case NM_ETHTOOL_TYPE_UNKNOWN: nm_assert_not_reached(); @@ -317,6 +318,7 @@ append_ethtool_valid_values(const NMMetaPropertyInfo *prop_info, GPtrArray *vali break; case NM_ETHTOOL_TYPE_FEATURE: case NM_ETHTOOL_TYPE_PAUSE: + case NM_ETHTOOL_TYPE_EEE: append_vals(valid_values, "on", "off", "ignore"); break; case NM_ETHTOOL_TYPE_UNKNOWN: diff --git a/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in b/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in index 82304a409a..7297a2852f 100644 --- a/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in +++ b/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in @@ -1028,6 +1028,9 @@ nmcli-description="Whether TX pause should be enabled. Only valid when automatic negotiation is disabled" format="ternary" values="on, off, ignore" /> + <property name="eee" + format="ternary" + values="on, off, ignore" /> <property name="ring-rx" format="integer" values="0 - 4294967295" /> |