mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-28 00:30:36 +01:00
WIP: support ethtool Forward Error Correction(fec)
Signed-off-by: Gris Ge <fge@redhat.com>
This commit is contained in:
parent
b699de9d4a
commit
78cbe53889
17 changed files with 205 additions and 1 deletions
|
|
@ -305,6 +305,7 @@ typedef struct {
|
|||
NMEthtoolPauseState *pause;
|
||||
NMEthtoolChannelsState *channels;
|
||||
NMEthtoolEEEState *eee;
|
||||
NMEthtoolFec fec;
|
||||
} EthtoolState;
|
||||
|
||||
typedef enum {
|
||||
|
|
@ -2450,6 +2451,25 @@ _ethtool_features_reset(NMDevice *self, NMPlatform *platform, EthtoolState *etht
|
|||
_LOGD(LOGD_DEVICE, "ethtool: offload features successfully reset");
|
||||
}
|
||||
|
||||
static inline _NMEthtoolFec
|
||||
_NM_ETHTOOL_FEC_CAST(NMEthtoolFec v)
|
||||
{
|
||||
return (_NMEthtoolFec) v;
|
||||
}
|
||||
|
||||
static void
|
||||
_ethtool_fec_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state)
|
||||
{
|
||||
gs_free NMEthtoolFeatureStates *features = NULL;
|
||||
|
||||
if (!nm_platform_ethtool_set_fec(platform,
|
||||
ethtool_state->ifindex,
|
||||
_NM_ETHTOOL_FEC_CAST(NM_ETHTOOL_FEC_AUTO)))
|
||||
_LOGW(LOGD_DEVICE, "ethtool: failure resetting FEC");
|
||||
else
|
||||
_LOGD(LOGD_DEVICE, "ethtool: FEC reset to auto");
|
||||
}
|
||||
|
||||
static void
|
||||
_ethtool_features_set(NMDevice *self,
|
||||
NMPlatform *platform,
|
||||
|
|
@ -2481,6 +2501,26 @@ _ethtool_features_set(NMDevice *self,
|
|||
ethtool_state->features = g_steal_pointer(&features);
|
||||
}
|
||||
|
||||
static void
|
||||
_ethtool_fec_set(NMDevice *self,
|
||||
NMPlatform *platform,
|
||||
EthtoolState *ethtool_state,
|
||||
NMSettingEthtool *s_ethtool)
|
||||
{
|
||||
NMEthtoolFec fec_mode = ethtool_state->fec;
|
||||
|
||||
if (fec_mode == NM_ETHTOOL_FEC_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nm_platform_ethtool_set_fec(platform,
|
||||
ethtool_state->ifindex,
|
||||
_NM_ETHTOOL_FEC_CAST(fec_mode)))
|
||||
_LOGW(LOGD_DEVICE, "ethtool: failure setting FEC %d", fec_mode);
|
||||
else
|
||||
_LOGD(LOGD_DEVICE, "ethtool: FEC %d successfully set", fec_mode);
|
||||
}
|
||||
|
||||
static void
|
||||
_ethtool_coalesce_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state)
|
||||
{
|
||||
|
|
@ -2962,6 +3002,7 @@ _ethtool_state_reset(NMDevice *self)
|
|||
_ethtool_pause_reset(self, platform, ethtool_state);
|
||||
_ethtool_channels_reset(self, platform, ethtool_state);
|
||||
_ethtool_eee_reset(self, platform, ethtool_state);
|
||||
_ethtool_fec_reset(self, platform, ethtool_state);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2998,6 +3039,7 @@ _ethtool_state_set(NMDevice *self)
|
|||
_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);
|
||||
_ethtool_fec_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->eee)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#ifndef __NM_LIBNM_BASE_H__
|
||||
#define __NM_LIBNM_BASE_H__
|
||||
|
||||
#include <linux/ethtool.h>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* this must be the same as NM_UTILS_HWADDR_LEN_MAX from libnm. */
|
||||
|
|
@ -135,7 +137,11 @@ typedef enum {
|
|||
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 = _NM_ETHTOOL_ID_FEC_FIRST,
|
||||
_NM_ETHTOOL_ID_FEC_LAST = NM_ETHTOOL_ID_FEC,
|
||||
|
||||
_NM_ETHTOOL_ID_LAST = _NM_ETHTOOL_ID_FEC_LAST,
|
||||
|
||||
_NM_ETHTOOL_ID_COALESCE_NUM =
|
||||
(_NM_ETHTOOL_ID_COALESCE_LAST - _NM_ETHTOOL_ID_COALESCE_FIRST + 1),
|
||||
|
|
@ -158,6 +164,7 @@ typedef enum {
|
|||
NM_ETHTOOL_TYPE_PAUSE,
|
||||
NM_ETHTOOL_TYPE_CHANNELS,
|
||||
NM_ETHTOOL_TYPE_EEE,
|
||||
NM_ETHTOOL_TYPE_FEC,
|
||||
} NMEthtoolType;
|
||||
|
||||
/****************************************************************************/
|
||||
|
|
@ -198,6 +205,22 @@ nm_ethtool_id_is_eee(NMEthtoolID id)
|
|||
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;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
// Mirrors libnm's NMEthtoolFec.
|
||||
_NM_ETHTOOL_FEC_NONE = ETHTOOL_FEC_NONE,
|
||||
_NM_ETHTOOL_FEC_AUTO = ETHTOOL_FEC_AUTO,
|
||||
_NM_ETHTOOL_FEC_OFF = ETHTOOL_FEC_OFF,
|
||||
_NM_ETHTOOL_FEC_RS = ETHTOOL_FEC_RS,
|
||||
_NM_ETHTOOL_FEC_BASER = ETHTOOL_FEC_BASER,
|
||||
_NM_ETHTOOL_FEC_LLRS = ETHTOOL_FEC_LLRS,
|
||||
} _NMEthtoolFec;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ const NMEthtoolData *const nm_ethtool_data[_NM_ETHTOOL_ID_NUM + 1] = {
|
|||
ETHT_DATA(CHANNELS_TX),
|
||||
ETHT_DATA(CHANNELS_OTHER),
|
||||
ETHT_DATA(CHANNELS_COMBINED),
|
||||
ETHT_DATA(FEC),
|
||||
[_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_VLAN_STAG_HW_INSERT,
|
||||
NM_ETHTOOL_ID_FEATURE_TXVLAN,
|
||||
NM_ETHTOOL_ID_FEC,
|
||||
NM_ETHTOOL_ID_PAUSE_AUTONEG,
|
||||
NM_ETHTOOL_ID_PAUSE_RX,
|
||||
NM_ETHTOOL_ID_PAUSE_TX,
|
||||
|
|
@ -305,6 +307,8 @@ nm_ethtool_id_to_type(NMEthtoolID id)
|
|||
return NM_ETHTOOL_TYPE_CHANNELS;
|
||||
if (nm_ethtool_id_is_eee(id))
|
||||
return NM_ETHTOOL_TYPE_EEE;
|
||||
if (nm_ethtool_id_is_fec(id))
|
||||
return NM_ETHTOOL_TYPE_FEC;
|
||||
|
||||
return NM_ETHTOOL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
|
@ -319,6 +323,7 @@ nm_ethtool_id_get_variant_type(NMEthtoolID ethtool_id)
|
|||
return G_VARIANT_TYPE_BOOLEAN;
|
||||
case NM_ETHTOOL_TYPE_CHANNELS:
|
||||
case NM_ETHTOOL_TYPE_COALESCE:
|
||||
case NM_ETHTOOL_TYPE_FEC:
|
||||
case NM_ETHTOOL_TYPE_RING:
|
||||
return G_VARIANT_TYPE_UINT32;
|
||||
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_COMBINED "channels-combined"
|
||||
|
||||
#define NM_ETHTOOL_OPTNAME_FEC "fec"
|
||||
|
||||
#define NM_ETHTOOL_OPTNAME_EEE_ENABLED "eee-enabled"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -1981,6 +1981,7 @@ global:
|
|||
|
||||
libnm_1_48_0 {
|
||||
global:
|
||||
nm_ethtool_fec_get_type;
|
||||
nm_setting_connection_down_on_poweroff_get_type;
|
||||
nm_setting_connection_get_down_on_poweroff;
|
||||
nm_setting_ip_config_get_dhcp_send_release;
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ G_BEGIN_DECLS
|
|||
#define NM_ETHTOOL_OPTNAME_CHANNELS_OTHER "channels-other"
|
||||
#define NM_ETHTOOL_OPTNAME_CHANNELS_COMBINED "channels-combined"
|
||||
|
||||
#define NM_ETHTOOL_OPTNAME_FEC "fec"
|
||||
|
||||
#define NM_ETHTOOL_OPTNAME_EEE_ENABLED "eee-enabled"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -1340,6 +1340,10 @@
|
|||
dbus-type="u"
|
||||
is-setting-option="1"
|
||||
/>
|
||||
<property name="fec"
|
||||
dbus-type="u"
|
||||
is-setting-option="1"
|
||||
/>
|
||||
</setting>
|
||||
<setting name="generic"
|
||||
gtype="NMSettingGeneric"
|
||||
|
|
|
|||
|
|
@ -121,6 +121,21 @@ nm_ethtool_optname_is_pause(const char *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.32
|
||||
*/
|
||||
gboolean
|
||||
nm_ethtool_optname_is_fec(const char *optname)
|
||||
{
|
||||
return optname && nm_ethtool_id_is_fec(nm_ethtool_id_get_by_name(optname));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,33 @@
|
|||
#endif
|
||||
|
||||
#include "nm-setting.h"
|
||||
#include <linux/ethtool.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* NMEthtoolFec:
|
||||
* @NM_ETHTOOL_FEC_NONE: Internal use only
|
||||
* @NM_ETHTOOL_FEC_AUTO: Select default/best FEC mode automatically
|
||||
* @NM_ETHTOOL_FEC_OFF: No FEC Mode
|
||||
* @NM_ETHTOOL_FEC_RS: Reed-Solomon FEC Mode
|
||||
* @NM_ETHTOOL_FEC_BASER: Base-R/Reed-Solomon FEC Mode
|
||||
* @NM_ETHTOOL_FEC_LLRS: Low Latency Reed Solomon FEC Mode
|
||||
*
|
||||
* #NMEthtoolFec describe ethtool Forward Error Correction(FEC) encoding modes.
|
||||
* FQDN.
|
||||
*
|
||||
* Since: 1.48
|
||||
*/
|
||||
typedef enum /*< flags >*/ {
|
||||
NM_ETHTOOL_FEC_NONE = ETHTOOL_FEC_NONE,
|
||||
NM_ETHTOOL_FEC_AUTO = ETHTOOL_FEC_AUTO,
|
||||
NM_ETHTOOL_FEC_OFF = ETHTOOL_FEC_OFF,
|
||||
NM_ETHTOOL_FEC_RS = ETHTOOL_FEC_RS,
|
||||
NM_ETHTOOL_FEC_BASER = ETHTOOL_FEC_BASER,
|
||||
NM_ETHTOOL_FEC_LLRS = ETHTOOL_FEC_LLRS,
|
||||
} NMEthtoolFec;
|
||||
|
||||
NM_AVAILABLE_IN_1_20
|
||||
gboolean nm_ethtool_optname_is_feature(const char *optname);
|
||||
|
||||
|
|
@ -32,6 +56,9 @@ gboolean nm_ethtool_optname_is_channels(const char *optname);
|
|||
NM_AVAILABLE_IN_1_46
|
||||
gboolean nm_ethtool_optname_is_eee(const char *optname);
|
||||
|
||||
NM_AVAILABLE_IN_1_48
|
||||
gboolean nm_ethtool_optname_is_fec(const char *optname);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_TYPE_SETTING_ETHTOOL (nm_setting_ethtool_get_type())
|
||||
|
|
|
|||
|
|
@ -1818,6 +1818,24 @@ nmp_utils_ethtool_set_wake_on_lan(int ifindex,
|
|||
return _ethtool_call_once(ifindex, &wol_info, sizeof(wol_info)) >= 0;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nmp_utils_ethtool_set_fec(int ifindex, const _NMEthtoolFec fec)
|
||||
{
|
||||
struct ethtool_fecparam fec_param = {
|
||||
.cmd = ETHTOOL_SFECPARAM,
|
||||
.fec = (uint32_t) fec,
|
||||
};
|
||||
|
||||
g_return_val_if_fail(ifindex > 0, FALSE);
|
||||
|
||||
if (fec == _NM_ETHTOOL_FEC_NONE)
|
||||
return TRUE;
|
||||
|
||||
nm_log_dbg(LOGD_PLATFORM, "ethtool[%d]: setting FEC options 0x%x", ifindex, fec);
|
||||
|
||||
return _ethtool_call_once(ifindex, &fec_param, sizeof(fec_param)) >= 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* mii
|
||||
*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ 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_fec(int ifindex, const _NMEthtoolFec fec);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean nmp_utils_mii_supports_carrier_detect(int ifindex);
|
||||
|
|
|
|||
|
|
@ -3569,6 +3569,16 @@ nm_platform_ethtool_set_features(
|
|||
return nmp_utils_ethtool_set_features(ifindex, features, requested, do_set);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_platform_ethtool_set_fec(NMPlatform *self, int ifindex, const _NMEthtoolFec fec)
|
||||
{
|
||||
_CHECK_SELF_NETNS(self, klass, netns, FALSE);
|
||||
|
||||
g_return_val_if_fail(ifindex > 0, FALSE);
|
||||
|
||||
return nmp_utils_ethtool_set_fec(ifindex, fec);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_platform_ethtool_get_link_coalesce(NMPlatform *self,
|
||||
int ifindex,
|
||||
|
|
|
|||
|
|
@ -2615,6 +2615,8 @@ gboolean nm_platform_ethtool_set_channels(NMPlatform *self,
|
|||
int ifindex,
|
||||
const NMEthtoolChannelsState *channels);
|
||||
|
||||
gboolean nm_platform_ethtool_set_fec(NMPlatform *self, int ifindex, const _NMEthtoolFec fec);
|
||||
|
||||
gboolean
|
||||
nm_platform_ethtool_get_link_pause(NMPlatform *self, int ifindex, NMEthtoolPauseState *pause);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#define __NMP_FWD_H__
|
||||
|
||||
#include "libnm-base/nm-base.h"
|
||||
#include <linux/ethtool.h>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -4459,6 +4459,8 @@ _get_fcn_ethtool(ARGS_GET_FCN)
|
|||
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
||||
s = gettext(s);
|
||||
return s;
|
||||
// NM_ETHTOOL_TYPE_FEC is not using `_pt_ethtool`, hence unreachable here
|
||||
case NM_ETHTOOL_TYPE_FEC:
|
||||
case NM_ETHTOOL_TYPE_UNKNOWN:
|
||||
nm_assert_not_reached();
|
||||
}
|
||||
|
|
@ -4512,6 +4514,8 @@ _set_fcn_ethtool(ARGS_SET_FCN)
|
|||
|
||||
nm_setting_option_set_boolean(setting, nm_ethtool_data[ethtool_id]->optname, !!t);
|
||||
return TRUE;
|
||||
// NM_ETHTOOL_TYPE_FEC is not using `_pt_ethtool`, hence unreachable here
|
||||
case NM_ETHTOOL_TYPE_FEC:
|
||||
case NM_ETHTOOL_TYPE_UNKNOWN:
|
||||
nm_assert_not_reached();
|
||||
}
|
||||
|
|
@ -5988,6 +5992,42 @@ static const NMMetaPropertyInfo *const property_infos_ETHTOOL[] = {
|
|||
PROPERTY_INFO_ETHTOOL (CHANNELS_TX),
|
||||
PROPERTY_INFO_ETHTOOL (CHANNELS_OTHER),
|
||||
PROPERTY_INFO_ETHTOOL (CHANNELS_COMBINED),
|
||||
// PROPERTY_INFO_WITH_DESC (NM_ETHTOOL_OPTNAME_FEC,
|
||||
PROPERTY_INFO(NM_ETHTOOL_OPTNAME_FEC, "TODO doc",
|
||||
.property_type = &_pt_gobject_enum,
|
||||
.property_typ_data = DEFINE_PROPERTY_TYP_DATA
|
||||
(
|
||||
PROPERTY_TYP_DATA_SUBTYPE
|
||||
(gobject_enum,
|
||||
.get_gtype = nm_ethtool_fec_get_type,
|
||||
.value_infos = ENUM_VALUE_INFOS
|
||||
(
|
||||
{
|
||||
.value = NM_ETHTOOL_FEC_AUTO,
|
||||
.nick = "auto",
|
||||
},
|
||||
{
|
||||
.value = NM_ETHTOOL_FEC_OFF,
|
||||
.nick = "off",
|
||||
},
|
||||
{
|
||||
.value = NM_ETHTOOL_FEC_RS,
|
||||
.nick = "rs",
|
||||
},
|
||||
{
|
||||
.value = NM_ETHTOOL_FEC_BASER,
|
||||
.nick = "baser",
|
||||
},
|
||||
{
|
||||
.value = NM_ETHTOOL_FEC_LLRS,
|
||||
.nick = "llrs",
|
||||
},
|
||||
),
|
||||
),
|
||||
.typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT
|
||||
| NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT,
|
||||
),
|
||||
),
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -122,6 +122,9 @@ get_ethtool_format(const NMMetaPropertyInfo *prop_info)
|
|||
case NM_ETHTOOL_TYPE_PAUSE:
|
||||
case NM_ETHTOOL_TYPE_EEE:
|
||||
return g_strdup("ternary");
|
||||
// NM_ETHTOOL_TYPE_FEC is not using NM_META_PROPERTY_TYPE_FORMAT_ETHTOOL,
|
||||
// hence unreachable.
|
||||
case NM_ETHTOOL_TYPE_FEC:
|
||||
case NM_ETHTOOL_TYPE_UNKNOWN:
|
||||
nm_assert_not_reached();
|
||||
};
|
||||
|
|
@ -328,6 +331,9 @@ append_ethtool_valid_values(const NMMetaPropertyInfo *prop_info, GPtrArray *vali
|
|||
case NM_ETHTOOL_TYPE_EEE:
|
||||
append_vals(valid_values, "on", "off", "ignore");
|
||||
break;
|
||||
case NM_ETHTOOL_TYPE_FEC:
|
||||
append_enum_valid_values(prop_info, valid_values);
|
||||
break;
|
||||
case NM_ETHTOOL_TYPE_UNKNOWN:
|
||||
nm_assert_not_reached();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1078,6 +1078,10 @@
|
|||
<property name="channels-combined"
|
||||
format="integer"
|
||||
values="0 - 4294967295" />
|
||||
<property name="fec"
|
||||
format="flags (NMEthtoolFec)"
|
||||
nmcli-description="The Forward Error Correction(FEC) encoding modes to set. Not all devices support all options. May be any combination of "auto" (0x2), "off" (0x4), "rs" (0x8), "baser" (0x10), "llrs" (0x20)"
|
||||
values="auto(0x2), off(0x4), rs(0x8), baser(0x10), llrs(0x20)"/>
|
||||
</setting>
|
||||
<setting name="generic" >
|
||||
<property name="device-handler"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue