ethtool: support Forward Error Correction(fec)
Introducing support of ethtool FEC mode: D-BUS API: `fec-mode: uint32_t`. Keyfile: ``` [ethtool] fec-mode=<uint32_t> ``` nmcli: `ethtool.fec-mode` allowing values are any combination of: * auto * off * rs * baser * llrs Unit test cases included. Resolves: https://issues.redhat.com/browse/RHEL-24055 Signed-off-by: Gris Ge <fge@redhat.com>
This commit is contained in:
1
NEWS
1
NEWS
@@ -23,6 +23,7 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
|
|||||||
ipv4.routed-dns and ipv6.routed-dns properties; when enabled, each
|
ipv4.routed-dns and ipv6.routed-dns properties; when enabled, each
|
||||||
name server is reached only via the device that specifies it.
|
name server is reached only via the device that specifies it.
|
||||||
* Support OCI in nm-cloud-setup
|
* Support OCI in nm-cloud-setup
|
||||||
|
* Added support for ethtool FEC mode
|
||||||
|
|
||||||
=============================================
|
=============================================
|
||||||
NetworkManager-1.50
|
NetworkManager-1.50
|
||||||
|
@@ -315,6 +315,7 @@ typedef struct {
|
|||||||
NMEthtoolPauseState *pause;
|
NMEthtoolPauseState *pause;
|
||||||
NMEthtoolChannelsState *channels;
|
NMEthtoolChannelsState *channels;
|
||||||
NMEthtoolEEEState *eee;
|
NMEthtoolEEEState *eee;
|
||||||
|
uint32_t fec_mode;
|
||||||
} EthtoolState;
|
} EthtoolState;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -2681,6 +2682,19 @@ _ethtool_features_reset(NMDevice *self, NMPlatform *platform, EthtoolState *etht
|
|||||||
_LOGD(LOGD_DEVICE, "ethtool: offload features successfully reset");
|
_LOGD(LOGD_DEVICE, "ethtool: offload features successfully reset");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ethtool_fec_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state)
|
||||||
|
{
|
||||||
|
if (ethtool_state->fec_mode) {
|
||||||
|
if (!nm_platform_ethtool_set_fec_mode(platform,
|
||||||
|
ethtool_state->ifindex,
|
||||||
|
ethtool_state->fec_mode))
|
||||||
|
_LOGW(LOGD_DEVICE, "ethtool: failure resetting FEC");
|
||||||
|
else
|
||||||
|
_LOGD(LOGD_DEVICE, "ethtool: FEC successfully reset");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_ethtool_features_set(NMDevice *self,
|
_ethtool_features_set(NMDevice *self,
|
||||||
NMPlatform *platform,
|
NMPlatform *platform,
|
||||||
@@ -2712,6 +2726,55 @@ _ethtool_features_set(NMDevice *self,
|
|||||||
ethtool_state->features = g_steal_pointer(&features);
|
ethtool_state->features = g_steal_pointer(&features);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ethtool_fec_set(NMDevice *self,
|
||||||
|
NMPlatform *platform,
|
||||||
|
EthtoolState *ethtool_state,
|
||||||
|
NMSettingEthtool *s_ethtool)
|
||||||
|
{
|
||||||
|
uint32_t old_fec_mode;
|
||||||
|
uint32_t fec_mode = NM_SETTING_ETHTOOL_FEC_MODE_NONE;
|
||||||
|
GHashTable *hash;
|
||||||
|
GHashTableIter iter;
|
||||||
|
const char *name;
|
||||||
|
GVariant *variant;
|
||||||
|
|
||||||
|
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->fec_mode);
|
||||||
|
|
||||||
|
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_fec(ethtool_id))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32));
|
||||||
|
fec_mode = g_variant_get_uint32(variant);
|
||||||
|
}
|
||||||
|
|
||||||
|
nm_platform_ethtool_get_fec_mode(platform, ethtool_state->ifindex, &old_fec_mode);
|
||||||
|
|
||||||
|
/* The NM_SETTING_ETHTOOL_FEC_MODE_NONE is query only value, hence do nothing. */
|
||||||
|
if (!fec_mode || fec_mode == NM_SETTING_ETHTOOL_FEC_MODE_NONE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nm_platform_ethtool_set_fec_mode(platform, ethtool_state->ifindex, fec_mode))
|
||||||
|
_LOGW(LOGD_DEVICE, "ethtool: failure setting FEC %d", fec_mode);
|
||||||
|
else {
|
||||||
|
_LOGD(LOGD_DEVICE, "ethtool: FEC %d successfully set", fec_mode);
|
||||||
|
ethtool_state->fec_mode = old_fec_mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_ethtool_coalesce_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state)
|
_ethtool_coalesce_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state)
|
||||||
{
|
{
|
||||||
@@ -3193,6 +3256,7 @@ _ethtool_state_reset(NMDevice *self)
|
|||||||
_ethtool_pause_reset(self, platform, ethtool_state);
|
_ethtool_pause_reset(self, platform, ethtool_state);
|
||||||
_ethtool_channels_reset(self, platform, ethtool_state);
|
_ethtool_channels_reset(self, platform, ethtool_state);
|
||||||
_ethtool_eee_reset(self, platform, ethtool_state);
|
_ethtool_eee_reset(self, platform, ethtool_state);
|
||||||
|
_ethtool_fec_reset(self, platform, ethtool_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -3229,9 +3293,11 @@ _ethtool_state_set(NMDevice *self)
|
|||||||
_ethtool_pause_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_channels_set(self, platform, ethtool_state, s_ethtool);
|
||||||
_ethtool_eee_set(self, platform, ethtool_state, s_ethtool);
|
_ethtool_eee_set(self, platform, ethtool_state, s_ethtool);
|
||||||
|
_ethtool_fec_set(self, platform, ethtool_state, s_ethtool);
|
||||||
|
|
||||||
if (ethtool_state->features || ethtool_state->coalesce || ethtool_state->ring
|
if (ethtool_state->features || ethtool_state->coalesce || ethtool_state->ring
|
||||||
|| ethtool_state->pause || ethtool_state->channels || ethtool_state->eee)
|
|| ethtool_state->pause || ethtool_state->channels || ethtool_state->eee
|
||||||
|
|| ethtool_state->fec_mode != 0)
|
||||||
priv->ethtool_state = g_steal_pointer(ðtool_state);
|
priv->ethtool_state = g_steal_pointer(ðtool_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1454,6 +1454,15 @@ write_ethtool_setting(NMConnection *connection, shvarFile *ifcfg, GError **error
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ethtool_id == NM_ETHTOOL_ID_FEC_MODE) {
|
||||||
|
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) {
|
if (!any_option) {
|
||||||
/* Write an empty dummy "-A" option without arguments. This is to
|
/* Write an empty dummy "-A" option without arguments. This is to
|
||||||
|
@@ -3623,7 +3623,8 @@ test_roundtrip_ethtool(void)
|
|||||||
optname = nm_ethtool_data[ethtool_id]->optname;
|
optname = nm_ethtool_data[ethtool_id]->optname;
|
||||||
vtype = nm_ethtool_id_get_variant_type(ethtool_id);
|
vtype = nm_ethtool_id_get_variant_type(ethtool_id);
|
||||||
|
|
||||||
if (nm_ethtool_optname_is_channels(optname) || nm_ethtool_optname_is_eee(optname)) {
|
if (nm_ethtool_optname_is_channels(optname) || nm_ethtool_optname_is_eee(optname)
|
||||||
|
|| nm_ethtool_optname_is_fec(optname)) {
|
||||||
/* Not supported */
|
/* Not supported */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@@ -135,7 +135,11 @@ typedef enum {
|
|||||||
NM_ETHTOOL_ID_CHANNELS_COMBINED,
|
NM_ETHTOOL_ID_CHANNELS_COMBINED,
|
||||||
_NM_ETHTOOL_ID_CHANNELS_LAST = 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_FEC_FIRST = _NM_ETHTOOL_ID_CHANNELS_LAST + 1,
|
||||||
|
NM_ETHTOOL_ID_FEC_MODE = _NM_ETHTOOL_ID_FEC_FIRST,
|
||||||
|
_NM_ETHTOOL_ID_FEC_LAST = NM_ETHTOOL_ID_FEC_MODE,
|
||||||
|
|
||||||
|
_NM_ETHTOOL_ID_LAST = _NM_ETHTOOL_ID_FEC_LAST,
|
||||||
|
|
||||||
_NM_ETHTOOL_ID_COALESCE_NUM =
|
_NM_ETHTOOL_ID_COALESCE_NUM =
|
||||||
(_NM_ETHTOOL_ID_COALESCE_LAST - _NM_ETHTOOL_ID_COALESCE_FIRST + 1),
|
(_NM_ETHTOOL_ID_COALESCE_LAST - _NM_ETHTOOL_ID_COALESCE_FIRST + 1),
|
||||||
@@ -158,6 +162,7 @@ typedef enum {
|
|||||||
NM_ETHTOOL_TYPE_PAUSE,
|
NM_ETHTOOL_TYPE_PAUSE,
|
||||||
NM_ETHTOOL_TYPE_CHANNELS,
|
NM_ETHTOOL_TYPE_CHANNELS,
|
||||||
NM_ETHTOOL_TYPE_EEE,
|
NM_ETHTOOL_TYPE_EEE,
|
||||||
|
NM_ETHTOOL_TYPE_FEC,
|
||||||
} NMEthtoolType;
|
} NMEthtoolType;
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
@@ -198,6 +203,12 @@ nm_ethtool_id_is_eee(NMEthtoolID id)
|
|||||||
return id >= _NM_ETHTOOL_ID_EEE_FIRST && id <= _NM_ETHTOOL_ID_EEE_LAST;
|
return id >= _NM_ETHTOOL_ID_EEE_FIRST && id <= _NM_ETHTOOL_ID_EEE_LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline gboolean
|
||||||
|
nm_ethtool_id_is_fec(NMEthtoolID id)
|
||||||
|
{
|
||||||
|
return id >= _NM_ETHTOOL_ID_FEC_FIRST && id <= _NM_ETHTOOL_ID_FEC_LAST;
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@@ -111,6 +111,7 @@ const NMEthtoolData *const nm_ethtool_data[_NM_ETHTOOL_ID_NUM + 1] = {
|
|||||||
ETHT_DATA(CHANNELS_TX),
|
ETHT_DATA(CHANNELS_TX),
|
||||||
ETHT_DATA(CHANNELS_OTHER),
|
ETHT_DATA(CHANNELS_OTHER),
|
||||||
ETHT_DATA(CHANNELS_COMBINED),
|
ETHT_DATA(CHANNELS_COMBINED),
|
||||||
|
ETHT_DATA(FEC_MODE),
|
||||||
[_NM_ETHTOOL_ID_NUM] = NULL,
|
[_NM_ETHTOOL_ID_NUM] = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -201,6 +202,7 @@ static const guint8 _by_name[_NM_ETHTOOL_ID_NUM] = {
|
|||||||
NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION,
|
NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION,
|
||||||
NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT,
|
NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT,
|
||||||
NM_ETHTOOL_ID_FEATURE_TXVLAN,
|
NM_ETHTOOL_ID_FEATURE_TXVLAN,
|
||||||
|
NM_ETHTOOL_ID_FEC_MODE,
|
||||||
NM_ETHTOOL_ID_PAUSE_AUTONEG,
|
NM_ETHTOOL_ID_PAUSE_AUTONEG,
|
||||||
NM_ETHTOOL_ID_PAUSE_RX,
|
NM_ETHTOOL_ID_PAUSE_RX,
|
||||||
NM_ETHTOOL_ID_PAUSE_TX,
|
NM_ETHTOOL_ID_PAUSE_TX,
|
||||||
@@ -305,6 +307,8 @@ nm_ethtool_id_to_type(NMEthtoolID id)
|
|||||||
return NM_ETHTOOL_TYPE_CHANNELS;
|
return NM_ETHTOOL_TYPE_CHANNELS;
|
||||||
if (nm_ethtool_id_is_eee(id))
|
if (nm_ethtool_id_is_eee(id))
|
||||||
return NM_ETHTOOL_TYPE_EEE;
|
return NM_ETHTOOL_TYPE_EEE;
|
||||||
|
if (nm_ethtool_id_is_fec(id))
|
||||||
|
return NM_ETHTOOL_TYPE_FEC;
|
||||||
|
|
||||||
return NM_ETHTOOL_TYPE_UNKNOWN;
|
return NM_ETHTOOL_TYPE_UNKNOWN;
|
||||||
}
|
}
|
||||||
@@ -319,6 +323,7 @@ nm_ethtool_id_get_variant_type(NMEthtoolID ethtool_id)
|
|||||||
return G_VARIANT_TYPE_BOOLEAN;
|
return G_VARIANT_TYPE_BOOLEAN;
|
||||||
case NM_ETHTOOL_TYPE_CHANNELS:
|
case NM_ETHTOOL_TYPE_CHANNELS:
|
||||||
case NM_ETHTOOL_TYPE_COALESCE:
|
case NM_ETHTOOL_TYPE_COALESCE:
|
||||||
|
case NM_ETHTOOL_TYPE_FEC:
|
||||||
case NM_ETHTOOL_TYPE_RING:
|
case NM_ETHTOOL_TYPE_RING:
|
||||||
return G_VARIANT_TYPE_UINT32;
|
return G_VARIANT_TYPE_UINT32;
|
||||||
case NM_ETHTOOL_TYPE_UNKNOWN:
|
case NM_ETHTOOL_TYPE_UNKNOWN:
|
||||||
|
@@ -109,6 +109,8 @@ G_BEGIN_DECLS
|
|||||||
#define NM_ETHTOOL_OPTNAME_CHANNELS_OTHER "channels-other"
|
#define NM_ETHTOOL_OPTNAME_CHANNELS_OTHER "channels-other"
|
||||||
#define NM_ETHTOOL_OPTNAME_CHANNELS_COMBINED "channels-combined"
|
#define NM_ETHTOOL_OPTNAME_CHANNELS_COMBINED "channels-combined"
|
||||||
|
|
||||||
|
#define NM_ETHTOOL_OPTNAME_FEC_MODE "fec-mode"
|
||||||
|
|
||||||
#define NM_ETHTOOL_OPTNAME_EEE_ENABLED "eee-enabled"
|
#define NM_ETHTOOL_OPTNAME_EEE_ENABLED "eee-enabled"
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@@ -2043,4 +2043,6 @@ global:
|
|||||||
nm_setting_connection_clear_ip_ping_addresses;
|
nm_setting_connection_clear_ip_ping_addresses;
|
||||||
nm_setting_connection_remove_ip_ping_address_by_value;
|
nm_setting_connection_remove_ip_ping_address_by_value;
|
||||||
nm_setting_connection_get_ip_ping_addresses_require_all;
|
nm_setting_connection_get_ip_ping_addresses_require_all;
|
||||||
|
nm_setting_ethtool_fec_mode_get_type;
|
||||||
|
nm_ethtool_optname_is_fec;
|
||||||
} libnm_1_50_0;
|
} libnm_1_50_0;
|
||||||
|
@@ -109,6 +109,8 @@ G_BEGIN_DECLS
|
|||||||
#define NM_ETHTOOL_OPTNAME_CHANNELS_OTHER "channels-other"
|
#define NM_ETHTOOL_OPTNAME_CHANNELS_OTHER "channels-other"
|
||||||
#define NM_ETHTOOL_OPTNAME_CHANNELS_COMBINED "channels-combined"
|
#define NM_ETHTOOL_OPTNAME_CHANNELS_COMBINED "channels-combined"
|
||||||
|
|
||||||
|
#define NM_ETHTOOL_OPTNAME_FEC_MODE "fec-mode"
|
||||||
|
|
||||||
#define NM_ETHTOOL_OPTNAME_EEE_ENABLED "eee-enabled"
|
#define NM_ETHTOOL_OPTNAME_EEE_ENABLED "eee-enabled"
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@@ -1361,6 +1361,10 @@
|
|||||||
dbus-type="u"
|
dbus-type="u"
|
||||||
is-setting-option="1"
|
is-setting-option="1"
|
||||||
/>
|
/>
|
||||||
|
<property name="fec-mode"
|
||||||
|
dbus-type="u"
|
||||||
|
is-setting-option="1"
|
||||||
|
/>
|
||||||
</setting>
|
</setting>
|
||||||
<setting name="generic"
|
<setting name="generic"
|
||||||
gtype="NMSettingGeneric"
|
gtype="NMSettingGeneric"
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#include "nm-setting-private.h"
|
#include "nm-setting-private.h"
|
||||||
#include "libnm-base/nm-ethtool-base.h"
|
#include "libnm-base/nm-ethtool-base.h"
|
||||||
#include "libnm-base/nm-ethtool-utils-base.h"
|
#include "libnm-base/nm-ethtool-utils-base.h"
|
||||||
|
#include "libnm-glib-aux/nm-enum-utils.h"
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
@@ -121,6 +122,21 @@ nm_ethtool_optname_is_pause(const char *optname)
|
|||||||
{
|
{
|
||||||
return optname && nm_ethtool_id_is_pause(nm_ethtool_id_get_by_name(optname));
|
return optname && nm_ethtool_id_is_pause(nm_ethtool_id_get_by_name(optname));
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* nm_ethtool_optname_is_fec:
|
||||||
|
* @optname: (nullable): the option name to check
|
||||||
|
*
|
||||||
|
* Checks whether @optname is a valid option name for a fec setting.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE, if @optname is valid
|
||||||
|
*
|
||||||
|
* Since: 1.52
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
nm_ethtool_optname_is_fec(const char *optname)
|
||||||
|
{
|
||||||
|
return optname && nm_ethtool_id_is_fec(nm_ethtool_id_get_by_name(optname));
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
@@ -309,6 +325,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
|
|||||||
NMTernary pause_autoneg = NM_TERNARY_DEFAULT;
|
NMTernary pause_autoneg = NM_TERNARY_DEFAULT;
|
||||||
NMTernary pause_tx = NM_TERNARY_DEFAULT;
|
NMTernary pause_tx = NM_TERNARY_DEFAULT;
|
||||||
NMTernary pause_rx = NM_TERNARY_DEFAULT;
|
NMTernary pause_rx = NM_TERNARY_DEFAULT;
|
||||||
|
guint32 fec_mode = 0;
|
||||||
|
|
||||||
len = _nm_setting_option_get_all(setting, &optnames, &variants);
|
len = _nm_setting_option_get_all(setting, &optnames, &variants);
|
||||||
|
|
||||||
@@ -356,6 +373,8 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
|
|||||||
pause_rx = g_variant_get_boolean(variant);
|
pause_rx = g_variant_get_boolean(variant);
|
||||||
else if (NM_IN_SET(ethtool_id, NM_ETHTOOL_ID_PAUSE_TX))
|
else if (NM_IN_SET(ethtool_id, NM_ETHTOOL_ID_PAUSE_TX))
|
||||||
pause_tx = g_variant_get_boolean(variant);
|
pause_tx = g_variant_get_boolean(variant);
|
||||||
|
else if (NM_IN_SET(ethtool_id, NM_ETHTOOL_ID_FEC_MODE))
|
||||||
|
fec_mode = g_variant_get_uint32(variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pause_rx != NM_TERNARY_DEFAULT || pause_tx != NM_TERNARY_DEFAULT) {
|
if (pause_rx != NM_TERNARY_DEFAULT || pause_tx != NM_TERNARY_DEFAULT) {
|
||||||
@@ -372,6 +391,32 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fec_mode == NM_SETTING_ETHTOOL_FEC_MODE_NONE
|
||||||
|
|| fec_mode >= (_NM_SETTING_ETHTOOL_FEC_MODE_LAST << 1)) {
|
||||||
|
gs_free const char *cur_fec_mode = NULL;
|
||||||
|
gs_free const char **valid_all = NULL;
|
||||||
|
gs_free const char *valid_str = NULL;
|
||||||
|
|
||||||
|
cur_fec_mode = _nm_utils_enum_to_str_full(nm_setting_ethtool_fec_mode_get_type(),
|
||||||
|
(int) (fec_mode & INT_MAX),
|
||||||
|
", ",
|
||||||
|
NULL);
|
||||||
|
valid_all = nm_utils_enum_get_values(nm_setting_ethtool_fec_mode_get_type(), 0, G_MAXUINT);
|
||||||
|
valid_str = g_strjoinv(",", (char **) valid_all);
|
||||||
|
|
||||||
|
g_set_error(error,
|
||||||
|
NM_CONNECTION_ERROR,
|
||||||
|
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||||
|
_("'%s' is not valid FEC modes, valid modes are combinations of %s"),
|
||||||
|
cur_fec_mode,
|
||||||
|
valid_str);
|
||||||
|
g_prefix_error(error,
|
||||||
|
"%s.%s: ",
|
||||||
|
NM_SETTING_ETHTOOL_SETTING_NAME,
|
||||||
|
NM_ETHTOOL_OPTNAME_FEC_MODE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2383,6 +2383,85 @@ test_ethtool_eee(void)
|
|||||||
}
|
}
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_ethtool_fec(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;
|
||||||
|
guint32 out_value;
|
||||||
|
guint32 expected_fec_mode =
|
||||||
|
NM_SETTING_ETHTOOL_FEC_MODE_AUTO | NM_SETTING_ETHTOOL_FEC_MODE_BASER;
|
||||||
|
|
||||||
|
con =
|
||||||
|
nmtst_create_minimal_connection("ethtool-fec", 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_uint32(NM_SETTING(s_ethtool),
|
||||||
|
NM_ETHTOOL_OPTNAME_FEC_MODE,
|
||||||
|
expected_fec_mode);
|
||||||
|
|
||||||
|
g_assert_true(nm_setting_option_get_uint32(NM_SETTING(s_ethtool),
|
||||||
|
NM_ETHTOOL_OPTNAME_FEC_MODE,
|
||||||
|
&out_value));
|
||||||
|
g_assert_true(out_value == expected_fec_mode);
|
||||||
|
|
||||||
|
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_uint32(NM_SETTING(s_ethtool2),
|
||||||
|
NM_ETHTOOL_OPTNAME_FEC_MODE,
|
||||||
|
&out_value));
|
||||||
|
g_assert_true(out_value == expected_fec_mode);
|
||||||
|
|
||||||
|
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_uint32(NM_SETTING(s_ethtool3),
|
||||||
|
NM_ETHTOOL_OPTNAME_FEC_MODE,
|
||||||
|
&out_value));
|
||||||
|
g_assert_true(out_value == expected_fec_mode);
|
||||||
|
}
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_sriov_vf(void)
|
test_sriov_vf(void)
|
||||||
{
|
{
|
||||||
@@ -5486,6 +5565,7 @@ main(int argc, char **argv)
|
|||||||
g_test_add_func("/libnm/settings/ethtool/ring", test_ethtool_ring);
|
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/pause", test_ethtool_pause);
|
||||||
g_test_add_func("/libnm/settings/ethtool/eee", test_ethtool_eee);
|
g_test_add_func("/libnm/settings/ethtool/eee", test_ethtool_eee);
|
||||||
|
g_test_add_func("/libnm/settings/ethtool/fec", test_ethtool_fec);
|
||||||
|
|
||||||
g_test_add_func("/libnm/settings/6lowpan/1", test_6lowpan_1);
|
g_test_add_func("/libnm/settings/6lowpan/1", test_6lowpan_1);
|
||||||
|
|
||||||
|
@@ -32,6 +32,9 @@ gboolean nm_ethtool_optname_is_channels(const char *optname);
|
|||||||
NM_AVAILABLE_IN_1_46
|
NM_AVAILABLE_IN_1_46
|
||||||
gboolean nm_ethtool_optname_is_eee(const char *optname);
|
gboolean nm_ethtool_optname_is_eee(const char *optname);
|
||||||
|
|
||||||
|
NM_AVAILABLE_IN_1_52
|
||||||
|
gboolean nm_ethtool_optname_is_fec(const char *optname);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
#define NM_TYPE_SETTING_ETHTOOL (nm_setting_ethtool_get_type())
|
#define NM_TYPE_SETTING_ETHTOOL (nm_setting_ethtool_get_type())
|
||||||
@@ -74,6 +77,30 @@ NM_AVAILABLE_IN_1_14
|
|||||||
NM_DEPRECATED_IN_1_26
|
NM_DEPRECATED_IN_1_26
|
||||||
void nm_setting_ethtool_clear_features(NMSettingEthtool *setting);
|
void nm_setting_ethtool_clear_features(NMSettingEthtool *setting);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NMSettingEthtoolFecMode:
|
||||||
|
* @NM_SETTING_ETHTOOL_FEC_MODE_NONE: FEC mode configuration is not supported.
|
||||||
|
* @NM_SETTING_ETHTOOL_FEC_MODE_AUTO: Select default/best FEC mode automatically.
|
||||||
|
* @NM_SETTING_ETHTOOL_FEC_MODE_OFF: No FEC mode.
|
||||||
|
* @NM_SETTING_ETHTOOL_FEC_MODE_RS: Reed-Solomon FEC Mode.
|
||||||
|
* @NM_SETTING_ETHTOOL_FEC_MODE_BASER: Base-R/Reed-Solomon FEC Mode.
|
||||||
|
* @NM_SETTING_ETHTOOL_FEC_MODE_LLRS: Low Latency Reed Solomon FEC Mode.
|
||||||
|
*
|
||||||
|
* These flags modify the ethtool FEC(Forward Error Correction) mode.
|
||||||
|
*
|
||||||
|
* Since: 1.52
|
||||||
|
**/
|
||||||
|
typedef enum { /*< flags >*/
|
||||||
|
NM_SETTING_ETHTOOL_FEC_MODE_NONE = 1 << 0, /*< skip >*/
|
||||||
|
NM_SETTING_ETHTOOL_FEC_MODE_AUTO = 1 << 1,
|
||||||
|
NM_SETTING_ETHTOOL_FEC_MODE_OFF = 1 << 2,
|
||||||
|
NM_SETTING_ETHTOOL_FEC_MODE_RS = 1 << 3,
|
||||||
|
NM_SETTING_ETHTOOL_FEC_MODE_BASER = 1 << 4,
|
||||||
|
NM_SETTING_ETHTOOL_FEC_MODE_LLRS = 1 << 5,
|
||||||
|
/* New constant should align with linux/ethtool.h ETHTOOL_FEC_XXX */
|
||||||
|
_NM_SETTING_ETHTOOL_FEC_MODE_LAST = NM_SETTING_ETHTOOL_FEC_MODE_LLRS, /*< skip >*/
|
||||||
|
} NMSettingEthtoolFecMode;
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __NM_SETTING_ETHTOOL_H__ */
|
#endif /* __NM_SETTING_ETHTOOL_H__ */
|
||||||
|
@@ -1820,6 +1820,46 @@ nmp_utils_ethtool_set_wake_on_lan(int ifindex,
|
|||||||
return _ethtool_call_once(ifindex, &wol_info, sizeof(wol_info)) >= 0;
|
return _ethtool_call_once(ifindex, &wol_info, sizeof(wol_info)) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nmp_utils_ethtool_get_fec_mode(int ifindex, uint32_t *fec_mode)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
struct ethtool_fecparam fec_param = {
|
||||||
|
.cmd = ETHTOOL_GFECPARAM,
|
||||||
|
.fec = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
g_return_val_if_fail(ifindex > 0, FALSE);
|
||||||
|
|
||||||
|
if (_ethtool_call_once(ifindex, &fec_param, sizeof(fec_param)) >= 0) {
|
||||||
|
nm_log_dbg(LOGD_PLATFORM, "ethtool[%d]: get FEC options 0x%x", ifindex, fec_param.fec);
|
||||||
|
*fec_mode = fec_param.fec;
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
r = -NM_ERRNO_NATIVE(errno);
|
||||||
|
nm_log_dbg(LOGD_PLATFORM,
|
||||||
|
"ethtool[%d]: ETHTOOL_GFECPARAM failure get fec mode: (%s)",
|
||||||
|
ifindex,
|
||||||
|
nm_strerror_native(-r));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nmp_utils_ethtool_set_fec_mode(int ifindex, uint32_t fec_mode)
|
||||||
|
{
|
||||||
|
struct ethtool_fecparam fec_param = {
|
||||||
|
.cmd = ETHTOOL_SFECPARAM,
|
||||||
|
.fec = fec_mode,
|
||||||
|
};
|
||||||
|
|
||||||
|
g_return_val_if_fail(ifindex > 0, FALSE);
|
||||||
|
|
||||||
|
nm_log_dbg(LOGD_PLATFORM, "ethtool[%d]: setting FEC options 0x%x", ifindex, fec_mode);
|
||||||
|
|
||||||
|
return _ethtool_call_once(ifindex, &fec_param, sizeof(fec_param)) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* mii
|
* mii
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
@@ -66,6 +66,10 @@ gboolean nmp_utils_ethtool_get_eee(int ifindex, NMEthtoolEEEState *eee);
|
|||||||
|
|
||||||
gboolean nmp_utils_ethtool_set_eee(int ifindex, const NMEthtoolEEEState *eee);
|
gboolean nmp_utils_ethtool_set_eee(int ifindex, const NMEthtoolEEEState *eee);
|
||||||
|
|
||||||
|
gboolean nmp_utils_ethtool_get_fec_mode(int ifindex, uint32_t *fec_mode);
|
||||||
|
|
||||||
|
gboolean nmp_utils_ethtool_set_fec_mode(int ifindex, uint32_t fec_mode);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
gboolean nmp_utils_mii_supports_carrier_detect(int ifindex);
|
gboolean nmp_utils_mii_supports_carrier_detect(int ifindex);
|
||||||
|
@@ -3617,6 +3617,26 @@ nm_platform_ethtool_set_features(
|
|||||||
return nmp_utils_ethtool_set_features(ifindex, features, requested, do_set);
|
return nmp_utils_ethtool_set_features(ifindex, features, requested, do_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_platform_ethtool_get_fec_mode(NMPlatform *self, int ifindex, uint32_t *fec_mode)
|
||||||
|
{
|
||||||
|
_CHECK_SELF_NETNS(self, klass, netns, FALSE);
|
||||||
|
|
||||||
|
g_return_val_if_fail(ifindex > 0, FALSE);
|
||||||
|
|
||||||
|
return nmp_utils_ethtool_get_fec_mode(ifindex, fec_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_platform_ethtool_set_fec_mode(NMPlatform *self, int ifindex, uint32_t fec_mode)
|
||||||
|
{
|
||||||
|
_CHECK_SELF_NETNS(self, klass, netns, FALSE);
|
||||||
|
|
||||||
|
g_return_val_if_fail(ifindex > 0, FALSE);
|
||||||
|
|
||||||
|
return nmp_utils_ethtool_set_fec_mode(ifindex, fec_mode);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nm_platform_ethtool_get_link_coalesce(NMPlatform *self,
|
nm_platform_ethtool_get_link_coalesce(NMPlatform *self,
|
||||||
int ifindex,
|
int ifindex,
|
||||||
|
@@ -2652,6 +2652,10 @@ gboolean nm_platform_ethtool_set_channels(NMPlatform *self,
|
|||||||
int ifindex,
|
int ifindex,
|
||||||
const NMEthtoolChannelsState *channels);
|
const NMEthtoolChannelsState *channels);
|
||||||
|
|
||||||
|
gboolean nm_platform_ethtool_get_fec_mode(NMPlatform *self, int ifindex, uint32_t *fec_mode);
|
||||||
|
|
||||||
|
gboolean nm_platform_ethtool_set_fec_mode(NMPlatform *self, int ifindex, uint32_t fec_mode);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nm_platform_ethtool_get_link_pause(NMPlatform *self, int ifindex, NMEthtoolPauseState *pause);
|
nm_platform_ethtool_get_link_pause(NMPlatform *self, int ifindex, NMEthtoolPauseState *pause);
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <linux/if_ether.h>
|
#include <linux/if_ether.h>
|
||||||
#include <linux/if_infiniband.h>
|
#include <linux/if_infiniband.h>
|
||||||
|
#include <linux/ethtool.h>
|
||||||
|
|
||||||
#include "libnm-core-aux-intern/nm-common-macros.h"
|
#include "libnm-core-aux-intern/nm-common-macros.h"
|
||||||
#include "libnm-glib-aux/nm-enum-utils.h"
|
#include "libnm-glib-aux/nm-enum-utils.h"
|
||||||
@@ -4459,6 +4460,21 @@ _get_fcn_ethtool(ARGS_GET_FCN)
|
|||||||
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
||||||
s = gettext(s);
|
s = gettext(s);
|
||||||
return s;
|
return s;
|
||||||
|
case NM_ETHTOOL_TYPE_FEC:
|
||||||
|
if (!nm_setting_option_get_uint32(setting, nm_ethtool_data[ethtool_id]->optname, &u32)) {
|
||||||
|
NM_SET_OUT(out_is_default, TRUE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
s = _nm_utils_enum_to_str_full(nm_setting_ethtool_fec_mode_get_type(),
|
||||||
|
(int) (u32 & INT_MAX),
|
||||||
|
", ",
|
||||||
|
NULL);
|
||||||
|
if (s == NULL) {
|
||||||
|
NM_SET_OUT(out_is_default, TRUE);
|
||||||
|
}
|
||||||
|
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
||||||
|
s = gettext(s);
|
||||||
|
return s;
|
||||||
case NM_ETHTOOL_TYPE_UNKNOWN:
|
case NM_ETHTOOL_TYPE_UNKNOWN:
|
||||||
nm_assert_not_reached();
|
nm_assert_not_reached();
|
||||||
}
|
}
|
||||||
@@ -4472,6 +4488,8 @@ _set_fcn_ethtool(ARGS_SET_FCN)
|
|||||||
NMEthtoolID ethtool_id = property_info->property_typ_data->subtype.ethtool.ethtool_id;
|
NMEthtoolID ethtool_id = property_info->property_typ_data->subtype.ethtool.ethtool_id;
|
||||||
gint64 i64;
|
gint64 i64;
|
||||||
NMTernary t;
|
NMTernary t;
|
||||||
|
int fec_mode = 0;
|
||||||
|
gs_free char *invalid_fec_mode = NULL;
|
||||||
|
|
||||||
if (_SET_FCN_DO_RESET_DEFAULT(property_info, modifier, value))
|
if (_SET_FCN_DO_RESET_DEFAULT(property_info, modifier, value))
|
||||||
goto do_unset;
|
goto do_unset;
|
||||||
@@ -4512,6 +4530,30 @@ _set_fcn_ethtool(ARGS_SET_FCN)
|
|||||||
|
|
||||||
nm_setting_option_set_boolean(setting, nm_ethtool_data[ethtool_id]->optname, !!t);
|
nm_setting_option_set_boolean(setting, nm_ethtool_data[ethtool_id]->optname, !!t);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
case NM_ETHTOOL_TYPE_FEC:
|
||||||
|
if (_nm_utils_enum_from_str_full(nm_setting_ethtool_fec_mode_get_type(),
|
||||||
|
value,
|
||||||
|
&fec_mode,
|
||||||
|
&invalid_fec_mode,
|
||||||
|
NULL)) {
|
||||||
|
nm_setting_option_set_uint32(setting,
|
||||||
|
NM_ETHTOOL_OPTNAME_FEC_MODE,
|
||||||
|
(uint32_t) (fec_mode & UINT32_MAX));
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
gs_free const char **valid_all = NULL;
|
||||||
|
gs_free const char *valid_str = NULL;
|
||||||
|
|
||||||
|
valid_all =
|
||||||
|
nm_utils_enum_get_values(nm_setting_ethtool_fec_mode_get_type(), 0, G_MAXUINT);
|
||||||
|
valid_str = g_strjoinv(",", (char **) valid_all);
|
||||||
|
nm_utils_error_set(error,
|
||||||
|
NM_UTILS_ERROR_INVALID_ARGUMENT,
|
||||||
|
_("'%s' is not valid FEC modes, valid modes are combinations of %s"),
|
||||||
|
invalid_fec_mode,
|
||||||
|
valid_str);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
case NM_ETHTOOL_TYPE_UNKNOWN:
|
case NM_ETHTOOL_TYPE_UNKNOWN:
|
||||||
nm_assert_not_reached();
|
nm_assert_not_reached();
|
||||||
}
|
}
|
||||||
@@ -5989,6 +6031,15 @@ static const NMMetaPropertyInfo *const property_infos_ETHTOOL[] = {
|
|||||||
PROPERTY_INFO_ETHTOOL (CHANNELS_TX),
|
PROPERTY_INFO_ETHTOOL (CHANNELS_TX),
|
||||||
PROPERTY_INFO_ETHTOOL (CHANNELS_OTHER),
|
PROPERTY_INFO_ETHTOOL (CHANNELS_OTHER),
|
||||||
PROPERTY_INFO_ETHTOOL (CHANNELS_COMBINED),
|
PROPERTY_INFO_ETHTOOL (CHANNELS_COMBINED),
|
||||||
|
PROPERTY_INFO (NM_ETHTOOL_OPTNAME_FEC_MODE,
|
||||||
|
"The Forward Error Correction(FEC) encoding modes to set. "
|
||||||
|
"Not all devices support all options. "
|
||||||
|
"May be any combination of auto, off, rs, baser, llrs.",
|
||||||
|
.property_type = &_pt_ethtool,
|
||||||
|
.property_typ_data =
|
||||||
|
DEFINE_PROPERTY_TYP_DATA_SUBTYPE
|
||||||
|
(ethtool, .ethtool_id = NM_ETHTOOL_ID_FEC_MODE)
|
||||||
|
),
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -124,6 +124,8 @@ get_ethtool_format(const NMMetaPropertyInfo *prop_info)
|
|||||||
case NM_ETHTOOL_TYPE_PAUSE:
|
case NM_ETHTOOL_TYPE_PAUSE:
|
||||||
case NM_ETHTOOL_TYPE_EEE:
|
case NM_ETHTOOL_TYPE_EEE:
|
||||||
return g_strdup("ternary");
|
return g_strdup("ternary");
|
||||||
|
case NM_ETHTOOL_TYPE_FEC:
|
||||||
|
return g_strdup("flags (NMSettingEthtoolFecMode)");
|
||||||
case NM_ETHTOOL_TYPE_UNKNOWN:
|
case NM_ETHTOOL_TYPE_UNKNOWN:
|
||||||
nm_assert_not_reached();
|
nm_assert_not_reached();
|
||||||
};
|
};
|
||||||
@@ -334,6 +336,13 @@ append_ethtool_valid_values(const NMMetaPropertyInfo *prop_info, GPtrArray *vali
|
|||||||
case NM_ETHTOOL_TYPE_EEE:
|
case NM_ETHTOOL_TYPE_EEE:
|
||||||
append_vals(valid_values, "on", "off", "ignore");
|
append_vals(valid_values, "on", "off", "ignore");
|
||||||
break;
|
break;
|
||||||
|
case NM_ETHTOOL_TYPE_FEC:
|
||||||
|
_append_enum_valid_values(NM_TYPE_SETTING_ETHTOOL_FEC_MODE,
|
||||||
|
0,
|
||||||
|
G_MAXUINT,
|
||||||
|
NULL,
|
||||||
|
valid_values);
|
||||||
|
break;
|
||||||
case NM_ETHTOOL_TYPE_UNKNOWN:
|
case NM_ETHTOOL_TYPE_UNKNOWN:
|
||||||
nm_assert_not_reached();
|
nm_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
@@ -1096,6 +1096,10 @@
|
|||||||
<property name="channels-combined"
|
<property name="channels-combined"
|
||||||
format="integer"
|
format="integer"
|
||||||
values="0 - 4294967295" />
|
values="0 - 4294967295" />
|
||||||
|
<property name="fec-mode"
|
||||||
|
nmcli-description="The Forward Error Correction(FEC) encoding modes to set. Not all devices support all options. May be any combination of auto, off, rs, baser, llrs."
|
||||||
|
format="flags (NMSettingEthtoolFecMode)"
|
||||||
|
values="auto (0x2), off (0x4), rs (0x8), baser (0x10), llrs (0x20)" />
|
||||||
</setting>
|
</setting>
|
||||||
<setting name="generic" >
|
<setting name="generic" >
|
||||||
<property name="device-handler"
|
<property name="device-handler"
|
||||||
|
Reference in New Issue
Block a user