From 3165d9a2deeaa2d0cd5fcb827ee32ec36818078e Mon Sep 17 00:00:00 2001 From: Johannes Zink Date: Wed, 25 Oct 2023 16:52:47 +0200 Subject: 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 --- src/core/devices/nm-device.c | 91 +++++++++++++++++++++- .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 12 +++ .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 2 +- src/libnm-base/nm-base.h | 13 +++- src/libnm-base/nm-ethtool-base.c | 5 ++ src/libnm-base/nm-ethtool-utils-base.h | 1 + src/libnm-client-impl/libnm.ver | 1 + src/libnm-client-public/nm-ethtool-utils.h | 1 + .../gen-metadata-nm-settings-libnm-core.xml.in | 4 + src/libnm-core-impl/nm-setting-ethtool.c | 15 ++++ src/libnm-core-impl/tests/test-setting.c | 74 ++++++++++++++++++ src/libnm-core-public/nm-setting-ethtool.h | 3 + src/libnm-platform/nm-platform-utils.c | 59 ++++++++++++++ src/libnm-platform/nm-platform-utils.h | 4 + src/libnm-platform/nm-platform.c | 20 +++++ src/libnm-platform/nm-platform.h | 4 + src/libnm-platform/nmp-base.h | 4 + src/libnmc-setting/nm-meta-setting-desc.c | 3 + src/nmcli/gen-metadata-nm-settings-nmcli.c | 2 + src/nmcli/gen-metadata-nm-settings-nmcli.xml.in | 3 + 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 { @@ -2722,6 +2723,25 @@ _ethtool_pause_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool _LOGD(LOGD_DEVICE, "ethtool: pause settings successfully reset"); } +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, @@ -2810,6 +2830,73 @@ _ethtool_pause_set(NMDevice *self, _LOGD(LOGD_DEVICE, "ethtool: pause settings successfully set"); } +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) { @@ -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" /> + 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) { @@ -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 @@ -3628,6 +3628,17 @@ nm_platform_ethtool_get_link_pause(NMPlatform *self, int ifindex, NMEthtoolPause return nmp_utils_ethtool_get_pause(ifindex, pause); } +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) { @@ -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" /> + -- cgit v1.2.3