mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-20 11:20:29 +01:00
ethtool: merge branch 'ac/ethtool_opts'
Add support for ethtool coalesce options https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/496
This commit is contained in:
commit
79f254850c
20 changed files with 1128 additions and 113 deletions
|
|
@ -4097,61 +4097,104 @@ _gobject_enum_pre_set_notify_fcn_wireless_security_wep_key_type (const NMMetaPro
|
|||
static gconstpointer
|
||||
_get_fcn_ethtool (ARGS_GET_FCN)
|
||||
{
|
||||
const char *s;
|
||||
NMTernary val;
|
||||
char *return_str;
|
||||
guint32 u32;
|
||||
NMEthtoolID ethtool_id = property_info->property_typ_data->subtype.ethtool.ethtool_id;
|
||||
|
||||
RETURN_UNSUPPORTED_GET_TYPE ();
|
||||
|
||||
val = nm_setting_ethtool_get_feature (NM_SETTING_ETHTOOL (setting),
|
||||
nm_ethtool_data[ethtool_id]->optname);
|
||||
if (nm_ethtool_id_is_coalesce (ethtool_id)) {
|
||||
if (!nm_setting_ethtool_get_coalesce (NM_SETTING_ETHTOOL (setting),
|
||||
nm_ethtool_data[ethtool_id]->optname,
|
||||
&u32)) {
|
||||
NM_SET_OUT (out_is_default, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (val == NM_TERNARY_TRUE)
|
||||
s = N_("on");
|
||||
else if (val == NM_TERNARY_FALSE)
|
||||
s = N_("off");
|
||||
else {
|
||||
s = NULL;
|
||||
NM_SET_OUT (out_is_default, TRUE);
|
||||
return_str = g_strdup_printf ("%"G_GUINT32_FORMAT, u32);
|
||||
RETURN_STR_TO_FREE (return_str);
|
||||
} else if (nm_ethtool_id_is_feature (ethtool_id)) {
|
||||
const char *s;
|
||||
NMTernary val;
|
||||
|
||||
val = nm_setting_ethtool_get_feature (NM_SETTING_ETHTOOL (setting),
|
||||
nm_ethtool_data[ethtool_id]->optname);
|
||||
|
||||
if (val == NM_TERNARY_TRUE)
|
||||
s = N_("on");
|
||||
else if (val == NM_TERNARY_FALSE)
|
||||
s = N_("off");
|
||||
else {
|
||||
s = NULL;
|
||||
NM_SET_OUT (out_is_default, TRUE);
|
||||
}
|
||||
|
||||
if (s && get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
||||
s = gettext (s);
|
||||
return s;
|
||||
}
|
||||
|
||||
if (s && get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
||||
s = gettext (s);
|
||||
return s;
|
||||
nm_assert_not_reached();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_set_fcn_ethtool (ARGS_SET_FCN)
|
||||
{
|
||||
gs_free char *value_to_free = NULL;
|
||||
NMTernary val;
|
||||
gint64 i64;
|
||||
NMEthtoolID ethtool_id = property_info->property_typ_data->subtype.ethtool.ethtool_id;
|
||||
|
||||
if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) {
|
||||
val = NM_TERNARY_DEFAULT;
|
||||
goto set;
|
||||
if (nm_ethtool_id_is_coalesce (ethtool_id)) {
|
||||
i64 = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, -1);
|
||||
|
||||
if (i64 == -1) {
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
|
||||
_("'%s' is out of range [%"G_GUINT32_FORMAT", %"G_GUINT32_FORMAT"]"),
|
||||
value, 0, G_MAXUINT32);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
nm_setting_ethtool_set_coalesce (NM_SETTING_ETHTOOL (setting),
|
||||
nm_ethtool_data[ethtool_id]->optname,
|
||||
(guint32) i64);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
value = nm_strstrip_avoid_copy_a (300, value, &value_to_free);
|
||||
if (nm_ethtool_id_is_feature (ethtool_id)) {
|
||||
gs_free char *value_to_free = NULL;
|
||||
NMTernary val;
|
||||
|
||||
if (NM_IN_STRSET (value, "1", "yes", "true", "on"))
|
||||
val = NM_TERNARY_TRUE;
|
||||
else if (NM_IN_STRSET (value, "0", "no", "false", "off"))
|
||||
val = NM_TERNARY_FALSE;
|
||||
else if (NM_IN_STRSET (value, "", "ignore", "default"))
|
||||
val = NM_TERNARY_DEFAULT;
|
||||
else {
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
|
||||
_("'%s' is not valid; use 'on', 'off', or 'ignore'"),
|
||||
value);
|
||||
return FALSE;
|
||||
}
|
||||
if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) {
|
||||
val = NM_TERNARY_DEFAULT;
|
||||
goto set;
|
||||
}
|
||||
|
||||
value = nm_strstrip_avoid_copy_a (300, value, &value_to_free);
|
||||
|
||||
if (NM_IN_STRSET (value, "1", "yes", "true", "on"))
|
||||
val = NM_TERNARY_TRUE;
|
||||
else if (NM_IN_STRSET (value, "0", "no", "false", "off"))
|
||||
val = NM_TERNARY_FALSE;
|
||||
else if (NM_IN_STRSET (value, "", "ignore", "default"))
|
||||
val = NM_TERNARY_DEFAULT;
|
||||
else {
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT,
|
||||
_("'%s' is not valid; use 'on', 'off', or 'ignore'"),
|
||||
value);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
set:
|
||||
nm_setting_ethtool_set_feature (NM_SETTING_ETHTOOL (setting),
|
||||
nm_setting_ethtool_set_feature (NM_SETTING_ETHTOOL (setting),
|
||||
nm_ethtool_data[ethtool_id]->optname,
|
||||
val);
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
nm_assert_not_reached();
|
||||
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_SETTING_MISSING,
|
||||
_("ethtool property not supported"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static const char *const*
|
||||
|
|
@ -4170,10 +4213,14 @@ _complete_fcn_ethtool (ARGS_COMPLETE_FCN)
|
|||
"ignore",
|
||||
NULL,
|
||||
};
|
||||
NMEthtoolID ethtool_id = property_info->property_typ_data->subtype.ethtool.ethtool_id;
|
||||
|
||||
if (!text || !text[0])
|
||||
return &v[7];
|
||||
return v;
|
||||
if (nm_ethtool_id_is_feature (ethtool_id)) {
|
||||
if (!text || !text[0])
|
||||
return &v[7];
|
||||
return v;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -5431,6 +5478,28 @@ static const NMMetaPropertyInfo *const property_infos_ETHTOOL[] = {
|
|||
PROPERTY_INFO_ETHTOOL (FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION),
|
||||
PROPERTY_INFO_ETHTOOL (FEATURE_TX_UDP_TNL_SEGMENTATION),
|
||||
PROPERTY_INFO_ETHTOOL (FEATURE_TX_VLAN_STAG_HW_INSERT),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_ADAPTIVE_RX),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_ADAPTIVE_TX),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_PKT_RATE_HIGH),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_PKT_RATE_LOW),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_RX_FRAMES),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_RX_FRAMES_IRQ),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_RX_FRAMES_HIGH),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_RX_FRAMES_LOW),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_RX_USECS),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_RX_USECS_IRQ),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_RX_USECS_HIGH),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_RX_USECS_LOW),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_SAMPLE_INTERVAL),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_STATS_BLOCK_USECS),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_TX_FRAMES),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_TX_FRAMES_IRQ),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_TX_FRAMES_HIGH),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_TX_FRAMES_LOW),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_TX_USECS),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_TX_USECS_IRQ),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_TX_USECS_HIGH),
|
||||
PROPERTY_INFO_ETHTOOL (COALESCE_TX_USECS_LOW),
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,22 @@ nm_ethtool_optname_is_feature (const char *optname)
|
|||
return optname && nm_ethtool_id_is_feature (nm_ethtool_id_get_by_name (optname));
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_ethtool_optname_is_coalesce:
|
||||
* @optname: (allow-none): the option name to check
|
||||
*
|
||||
* Checks whether @optname is a valid option name for a coalesce setting.
|
||||
*
|
||||
* %Returns: %TRUE, if @optname is valid
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
gboolean
|
||||
nm_ethtool_optname_is_coalesce (const char *optname)
|
||||
{
|
||||
return optname && nm_ethtool_id_is_coalesce (nm_ethtool_id_get_by_name (optname));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
|
|
@ -239,6 +255,143 @@ nm_setting_ethtool_init_features (NMSettingEthtool *setting,
|
|||
return n_req;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_ethtool_get_coalesce:
|
||||
* @setting: the #NMSettingEthtool
|
||||
* @optname: option name of the coalescing setting to get
|
||||
* @out_value (out) (allow-none): value of the coalescing setting
|
||||
*
|
||||
* Gets the value of coalescing setting.
|
||||
*
|
||||
* Note that @optname must be a valid name for a setting, according to
|
||||
* nm_ethtool_optname_is_coalesce().
|
||||
*
|
||||
*
|
||||
* Returns: %TRUE and places the coalesce setting value in @out_value or %FALSE if unset.
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
gboolean
|
||||
nm_setting_ethtool_get_coalesce (NMSettingEthtool *setting,
|
||||
const char *optname,
|
||||
guint32 *out_value)
|
||||
{
|
||||
GVariant *v;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING_ETHTOOL (setting), FALSE);
|
||||
g_return_val_if_fail (nm_ethtool_optname_is_coalesce (optname), FALSE);
|
||||
|
||||
v = nm_setting_gendata_get (NM_SETTING (setting), optname);
|
||||
if ( v
|
||||
&& g_variant_is_of_type (v, G_VARIANT_TYPE_UINT32)) {
|
||||
NM_SET_OUT (out_value, g_variant_get_uint32 (v));
|
||||
return TRUE;
|
||||
}
|
||||
NM_SET_OUT (out_value, 0);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_ethtool_set_coalesce:
|
||||
* @setting: the #NMSettingEthtool
|
||||
* @optname: option name of the coalesce setting
|
||||
* @value: the new value to set.
|
||||
*
|
||||
* Sets a coalesce setting.
|
||||
*
|
||||
* Note that @optname must be a valid name for a coalesce setting, according to
|
||||
* nm_ethtool_optname_is_coalesce().
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
void
|
||||
nm_setting_ethtool_set_coalesce (NMSettingEthtool *setting,
|
||||
const char *optname,
|
||||
guint32 value)
|
||||
{
|
||||
GHashTable *ht;
|
||||
NMEthtoolID ethtool_id;
|
||||
|
||||
g_return_if_fail (NM_IS_SETTING_ETHTOOL (setting));
|
||||
|
||||
ethtool_id = nm_ethtool_id_get_by_name (optname);
|
||||
|
||||
g_return_if_fail (nm_ethtool_id_is_coalesce (ethtool_id));
|
||||
|
||||
ht = _nm_setting_gendata_hash (NM_SETTING (setting),
|
||||
TRUE);
|
||||
|
||||
if (NM_IN_SET (ethtool_id,
|
||||
NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX,
|
||||
NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX))
|
||||
value = !!value;
|
||||
|
||||
g_hash_table_insert (ht,
|
||||
g_strdup (optname),
|
||||
g_variant_ref_sink (g_variant_new_uint32 (value)));
|
||||
_notify_attributes (setting);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_ethtool_clear_coalesce:
|
||||
* @setting: the #NMSettingEthtool
|
||||
* @optname: option name of the coalesce setting
|
||||
*
|
||||
* Clear a coalesce setting
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
void
|
||||
nm_setting_ethtool_clear_coalesce (NMSettingEthtool *setting,
|
||||
const char *optname)
|
||||
{
|
||||
GHashTable *hash;
|
||||
|
||||
g_return_if_fail (NM_IS_SETTING_ETHTOOL (setting));
|
||||
g_return_if_fail (nm_str_not_empty (optname));
|
||||
|
||||
hash = _nm_setting_gendata_hash (NM_SETTING (setting), FALSE);
|
||||
if (!hash)
|
||||
return;
|
||||
|
||||
if (g_hash_table_remove (hash, optname))
|
||||
_notify_attributes (setting);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_ethtool_clear_coalesce_all:
|
||||
* @setting: the #NMSettingEthtool
|
||||
*
|
||||
* Clears all coalesce settings
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
void
|
||||
nm_setting_ethtool_clear_coalesce_all (NMSettingEthtool *setting)
|
||||
{
|
||||
GHashTable *hash;
|
||||
GHashTableIter iter;
|
||||
const char *name;
|
||||
gboolean changed = FALSE;
|
||||
|
||||
g_return_if_fail (NM_IS_SETTING_ETHTOOL (setting));
|
||||
|
||||
hash = _nm_setting_gendata_hash (NM_SETTING (setting), FALSE);
|
||||
if (!hash)
|
||||
return;
|
||||
|
||||
g_hash_table_iter_init (&iter, hash);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &name, NULL)) {
|
||||
if (nm_ethtool_optname_is_coalesce (name)) {
|
||||
g_hash_table_iter_remove (&iter);
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
_notify_attributes (setting);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
|
|
@ -284,19 +437,29 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
|
|||
|
||||
g_hash_table_iter_init (&iter, hash);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &optname, (gpointer *) &variant)) {
|
||||
if (!nm_ethtool_optname_is_feature (optname)) {
|
||||
if (nm_ethtool_optname_is_feature (optname)) {
|
||||
if (!g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN)) {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("offload feature has invalid variant type"));
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname);
|
||||
return FALSE;
|
||||
}
|
||||
} else if (nm_ethtool_optname_is_coalesce (optname)) {
|
||||
if (!g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32)) {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("coalesce setting has invalid variant type"));
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname);
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("unsupported offload feature"));
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname);
|
||||
return FALSE;
|
||||
}
|
||||
if (!g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN)) {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("offload feature has invalid variant type"));
|
||||
_("unsupported ethtool setting"));
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -316,6 +479,9 @@ get_variant_type (const NMSettInfoSetting *sett_info,
|
|||
if (nm_ethtool_optname_is_feature (name))
|
||||
return G_VARIANT_TYPE_BOOLEAN;
|
||||
|
||||
if (nm_ethtool_optname_is_coalesce (name))
|
||||
return G_VARIANT_TYPE_UINT32;
|
||||
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
|
|
|
|||
|
|
@ -69,9 +69,35 @@ G_BEGIN_DECLS
|
|||
#define NM_ETHTOOL_OPTNAME_FEATURE_TX_UDP_TNL_SEGMENTATION "feature-tx-udp_tnl-segmentation"
|
||||
#define NM_ETHTOOL_OPTNAME_FEATURE_TX_VLAN_STAG_HW_INSERT "feature-tx-vlan-stag-hw-insert"
|
||||
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_ADAPTIVE_RX "coalesce-adaptive-rx"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_ADAPTIVE_TX "coalesce-adaptive-tx"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_PKT_RATE_HIGH "coalesce-pkt-rate-high"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_PKT_RATE_LOW "coalesce-pkt-rate-low"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES "coalesce-rx-frames"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES_HIGH "coalesce-rx-frames-high"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES_IRQ "coalesce-rx-frames-irq"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES_LOW "coalesce-rx-frames-low"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_RX_USECS "coalesce-rx-usecs"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_RX_USECS_HIGH "coalesce-rx-usecs-high"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_RX_USECS_IRQ "coalesce-rx-usecs-irq"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_RX_USECS_LOW "coalesce-rx-usecs-low"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_SAMPLE_INTERVAL "coalesce-sample-interval"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_STATS_BLOCK_USECS "coalesce-stats-block-usecs"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_TX_FRAMES "coalesce-tx-frames"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_TX_FRAMES_HIGH "coalesce-tx-frames-high"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_TX_FRAMES_IRQ "coalesce-tx-frames-irq"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_TX_FRAMES_LOW "coalesce-tx-frames-low"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_TX_USECS "coalesce-tx-usecs"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_TX_USECS_HIGH "coalesce-tx-usecs-high"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_TX_USECS_IRQ "coalesce-tx-usecs-irq"
|
||||
#define NM_ETHTOOL_OPTNAME_COALESCE_TX_USECS_LOW "coalesce-tx-usecs-low"
|
||||
|
||||
NM_AVAILABLE_IN_1_20
|
||||
gboolean nm_ethtool_optname_is_feature (const char *optname);
|
||||
|
||||
NM_AVAILABLE_IN_1_26
|
||||
gboolean nm_ethtool_optname_is_coalesce (const char *optname);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_TYPE_SETTING_ETHTOOL (nm_setting_ethtool_get_type ())
|
||||
|
|
@ -109,6 +135,23 @@ NM_AVAILABLE_IN_1_20
|
|||
const char ** nm_setting_ethtool_get_optnames (NMSettingEthtool *setting,
|
||||
guint *out_length);
|
||||
|
||||
NM_AVAILABLE_IN_1_26
|
||||
gboolean nm_setting_ethtool_get_coalesce (NMSettingEthtool *setting,
|
||||
const char *optname,
|
||||
guint32 *out_value);
|
||||
|
||||
NM_AVAILABLE_IN_1_26
|
||||
void nm_setting_ethtool_set_coalesce (NMSettingEthtool *setting,
|
||||
const char *optname,
|
||||
guint32 value);
|
||||
|
||||
NM_AVAILABLE_IN_1_26
|
||||
void nm_setting_ethtool_clear_coalesce (NMSettingEthtool *setting,
|
||||
const char *optname);
|
||||
|
||||
NM_AVAILABLE_IN_1_26
|
||||
void nm_setting_ethtool_clear_coalesce_all (NMSettingEthtool *setting);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __NM_SETTING_ETHTOOL_H__ */
|
||||
|
|
|
|||
|
|
@ -1571,6 +1571,90 @@ test_ethtool_1 (void)
|
|||
g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_SG), ==, NM_TERNARY_DEFAULT);
|
||||
}
|
||||
|
||||
static void
|
||||
test_ethtool_coalesce (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;
|
||||
gs_unref_keyfile GKeyFile *keyfile = NULL;
|
||||
NMSettingConnection *s_con;
|
||||
NMSettingEthtool *s_ethtool;
|
||||
NMSettingEthtool *s_ethtool2;
|
||||
NMSettingEthtool *s_ethtool3;
|
||||
guint32 out_value;
|
||||
|
||||
con = nmtst_create_minimal_connection ("ethtool-coalesce",
|
||||
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_ethtool_set_coalesce (s_ethtool,
|
||||
NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES,
|
||||
4);
|
||||
|
||||
g_assert_true (nm_setting_ethtool_get_coalesce (s_ethtool, NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, &out_value));
|
||||
g_assert_cmpuint (out_value, ==, 4);
|
||||
|
||||
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_ethtool_get_coalesce (s_ethtool2, NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, &out_value));
|
||||
g_assert_cmpuint (out_value, ==, 4);
|
||||
|
||||
nmtst_assert_connection_verifies_without_normalization (con2);
|
||||
|
||||
nmtst_assert_connection_equals (con, FALSE, con2, FALSE);
|
||||
|
||||
keyfile = nm_keyfile_write (con, NULL, NULL, &error);
|
||||
nmtst_assert_success (keyfile, error);
|
||||
|
||||
con3 = nm_keyfile_read (keyfile,
|
||||
"/ignored/current/working/directory/for/loading/relative/paths",
|
||||
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_ethtool_get_coalesce (s_ethtool3, NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, &out_value));
|
||||
g_assert_cmpuint (out_value, ==, 4);
|
||||
|
||||
|
||||
nm_setting_ethtool_clear_coalesce (s_ethtool, NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES);
|
||||
g_assert_false (nm_setting_ethtool_get_coalesce (s_ethtool, NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, NULL));
|
||||
|
||||
nm_setting_ethtool_set_coalesce (s_ethtool,
|
||||
NM_ETHTOOL_OPTNAME_COALESCE_TX_FRAMES,
|
||||
8);
|
||||
|
||||
g_assert_true (nm_setting_ethtool_get_coalesce (s_ethtool, NM_ETHTOOL_OPTNAME_COALESCE_TX_FRAMES, &out_value));
|
||||
g_assert_cmpuint (out_value, ==, 8);
|
||||
|
||||
nm_setting_ethtool_clear_coalesce_all (s_ethtool);
|
||||
g_assert_false (nm_setting_ethtool_get_coalesce (s_ethtool, NM_ETHTOOL_OPTNAME_COALESCE_RX_FRAMES, NULL));
|
||||
g_assert_false (nm_setting_ethtool_get_coalesce (s_ethtool, NM_ETHTOOL_OPTNAME_COALESCE_TX_FRAMES, NULL));
|
||||
g_assert_false (nm_setting_ethtool_get_coalesce (s_ethtool, NM_ETHTOOL_OPTNAME_COALESCE_TX_USECS, NULL));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
|
|
@ -3771,6 +3855,7 @@ main (int argc, char **argv)
|
|||
g_test_add_func ("/libnm/settings/dcb/bandwidth-sums", test_dcb_bandwidth_sums);
|
||||
|
||||
g_test_add_func ("/libnm/settings/ethtool/1", test_ethtool_1);
|
||||
g_test_add_func ("/libnm/settings/ethtool/coalesce", test_ethtool_coalesce);
|
||||
|
||||
g_test_add_func ("/libnm/settings/sriov/vf", test_sriov_vf);
|
||||
g_test_add_func ("/libnm/settings/sriov/vf-dup", test_sriov_vf_dup);
|
||||
|
|
|
|||
|
|
@ -1698,6 +1698,7 @@ global:
|
|||
|
||||
libnm_1_26_0 {
|
||||
global:
|
||||
nm_ethtool_optname_is_coalesce;
|
||||
nm_setting_bridge_get_multicast_hash_max;
|
||||
nm_setting_bridge_get_multicast_last_member_count;
|
||||
nm_setting_bridge_get_multicast_last_member_interval;
|
||||
|
|
@ -1708,6 +1709,10 @@ global:
|
|||
nm_setting_bridge_get_multicast_startup_query_count;
|
||||
nm_setting_bridge_get_multicast_startup_query_interval;
|
||||
nm_setting_connection_get_mud_url;
|
||||
nm_setting_ethtool_clear_coalesce;
|
||||
nm_setting_ethtool_clear_coalesce_all;
|
||||
nm_setting_ethtool_get_coalesce;
|
||||
nm_setting_ethtool_set_coalesce;
|
||||
nm_setting_match_add_driver;
|
||||
nm_setting_match_add_kernel_command_line;
|
||||
nm_setting_match_clear_drivers;
|
||||
|
|
|
|||
|
|
@ -3243,6 +3243,22 @@ _read_setting (KeyfileReaderInfo *info)
|
|||
continue;
|
||||
}
|
||||
variant = g_variant_new_boolean (v);
|
||||
} else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_UINT32)) {
|
||||
guint64 v;
|
||||
|
||||
v = g_key_file_get_uint64 (info->keyfile,
|
||||
info->group,
|
||||
key,
|
||||
&local);
|
||||
|
||||
if (local) {
|
||||
if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("key '%s.%s' is not a uint32"),
|
||||
info->group, key))
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
variant = g_variant_new_uint32 ((guint32) v);
|
||||
} else {
|
||||
nm_assert_not_reached ();
|
||||
continue;
|
||||
|
|
@ -3851,6 +3867,11 @@ nm_keyfile_write (NMConnection *connection,
|
|||
setting_name,
|
||||
key,
|
||||
g_variant_get_boolean (v));
|
||||
} else if (g_variant_is_of_type (v, G_VARIANT_TYPE_UINT32)) {
|
||||
g_key_file_set_uint64 (info.keyfile,
|
||||
setting_name,
|
||||
key,
|
||||
(guint64) g_variant_get_uint32 (v));
|
||||
} else {
|
||||
/* BUG: The variant type is not implemented. Since the connection
|
||||
* verifies, this can only mean we either wrongly didn't reject
|
||||
|
|
|
|||
|
|
@ -19,6 +19,28 @@
|
|||
|
||||
const NMEthtoolData *const nm_ethtool_data[_NM_ETHTOOL_ID_NUM + 1] = {
|
||||
/* indexed by NMEthtoolID */
|
||||
ETHT_DATA (COALESCE_ADAPTIVE_RX),
|
||||
ETHT_DATA (COALESCE_ADAPTIVE_TX),
|
||||
ETHT_DATA (COALESCE_PKT_RATE_HIGH),
|
||||
ETHT_DATA (COALESCE_PKT_RATE_LOW),
|
||||
ETHT_DATA (COALESCE_RX_FRAMES),
|
||||
ETHT_DATA (COALESCE_RX_FRAMES_HIGH),
|
||||
ETHT_DATA (COALESCE_RX_FRAMES_IRQ),
|
||||
ETHT_DATA (COALESCE_RX_FRAMES_LOW),
|
||||
ETHT_DATA (COALESCE_RX_USECS),
|
||||
ETHT_DATA (COALESCE_RX_USECS_HIGH),
|
||||
ETHT_DATA (COALESCE_RX_USECS_IRQ),
|
||||
ETHT_DATA (COALESCE_RX_USECS_LOW),
|
||||
ETHT_DATA (COALESCE_SAMPLE_INTERVAL),
|
||||
ETHT_DATA (COALESCE_STATS_BLOCK_USECS),
|
||||
ETHT_DATA (COALESCE_TX_FRAMES),
|
||||
ETHT_DATA (COALESCE_TX_FRAMES_HIGH),
|
||||
ETHT_DATA (COALESCE_TX_FRAMES_IRQ),
|
||||
ETHT_DATA (COALESCE_TX_FRAMES_LOW),
|
||||
ETHT_DATA (COALESCE_TX_USECS),
|
||||
ETHT_DATA (COALESCE_TX_USECS_HIGH),
|
||||
ETHT_DATA (COALESCE_TX_USECS_IRQ),
|
||||
ETHT_DATA (COALESCE_TX_USECS_LOW),
|
||||
ETHT_DATA (FEATURE_ESP_HW_OFFLOAD),
|
||||
ETHT_DATA (FEATURE_ESP_TX_CSUM_HW_OFFLOAD),
|
||||
ETHT_DATA (FEATURE_FCOE_MTU),
|
||||
|
|
@ -76,6 +98,28 @@ const NMEthtoolData *const nm_ethtool_data[_NM_ETHTOOL_ID_NUM + 1] = {
|
|||
|
||||
static const guint8 _by_name[_NM_ETHTOOL_ID_NUM] = {
|
||||
/* sorted by optname. */
|
||||
NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX,
|
||||
NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX,
|
||||
NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH,
|
||||
NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_FRAMES,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_FRAMES_HIGH,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_FRAMES_IRQ,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_FRAMES_LOW,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_USECS,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_USECS_HIGH,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_USECS_IRQ,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_USECS_LOW,
|
||||
NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL,
|
||||
NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_FRAMES,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_FRAMES_HIGH,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_FRAMES_IRQ,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_FRAMES_LOW,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_USECS,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW,
|
||||
NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD,
|
||||
NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD,
|
||||
NM_ETHTOOL_ID_FEATURE_FCOE_MTU,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,32 @@ typedef enum {
|
|||
|
||||
_NM_ETHTOOL_ID_FIRST = 0,
|
||||
|
||||
_NM_ETHTOOL_ID_FEATURE_FIRST = _NM_ETHTOOL_ID_FIRST,
|
||||
_NM_ETHTOOL_ID_COALESCE_FIRST = _NM_ETHTOOL_ID_FIRST,
|
||||
NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX = _NM_ETHTOOL_ID_COALESCE_FIRST,
|
||||
NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX,
|
||||
NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH,
|
||||
NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_FRAMES,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_FRAMES_HIGH,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_FRAMES_IRQ,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_FRAMES_LOW,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_USECS,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_USECS_HIGH,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_USECS_IRQ,
|
||||
NM_ETHTOOL_ID_COALESCE_RX_USECS_LOW,
|
||||
NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL,
|
||||
NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_FRAMES,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_FRAMES_HIGH,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_FRAMES_IRQ,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_FRAMES_LOW,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_USECS,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ,
|
||||
NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW,
|
||||
_NM_ETHTOOL_ID_COALESCE_LAST = NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW,
|
||||
|
||||
_NM_ETHTOOL_ID_FEATURE_FIRST = _NM_ETHTOOL_ID_COALESCE_LAST + 1,
|
||||
NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD = _NM_ETHTOOL_ID_FEATURE_FIRST,
|
||||
NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD,
|
||||
NM_ETHTOOL_ID_FEATURE_FCOE_MTU,
|
||||
|
|
@ -67,10 +92,11 @@ typedef enum {
|
|||
NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION,
|
||||
NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT,
|
||||
_NM_ETHTOOL_ID_FEATURE_LAST = NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT,
|
||||
_NM_ETHTOOL_ID_FEATURE_NUM = (_NM_ETHTOOL_ID_FEATURE_LAST - _NM_ETHTOOL_ID_FEATURE_FIRST + 1),
|
||||
|
||||
_NM_ETHTOOL_ID_LAST = _NM_ETHTOOL_ID_FEATURE_LAST,
|
||||
|
||||
_NM_ETHTOOL_ID_COALESCE_NUM = (_NM_ETHTOOL_ID_COALESCE_LAST - _NM_ETHTOOL_ID_COALESCE_FIRST + 1),
|
||||
_NM_ETHTOOL_ID_FEATURE_NUM = (_NM_ETHTOOL_ID_FEATURE_LAST - _NM_ETHTOOL_ID_FEATURE_FIRST + 1),
|
||||
_NM_ETHTOOL_ID_NUM = (_NM_ETHTOOL_ID_LAST - _NM_ETHTOOL_ID_FIRST + 1),
|
||||
} NMEthtoolID;
|
||||
|
||||
|
|
@ -100,6 +126,12 @@ nm_ethtool_id_is_feature (NMEthtoolID id)
|
|||
return id >= _NM_ETHTOOL_ID_FEATURE_FIRST && id <= _NM_ETHTOOL_ID_FEATURE_LAST;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
nm_ethtool_id_is_coalesce (NMEthtoolID id)
|
||||
{
|
||||
return id >= _NM_ETHTOOL_ID_COALESCE_FIRST && id <= _NM_ETHTOOL_ID_COALESCE_LAST;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#endif /* __NM_ETHTOOL_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ typedef struct {
|
|||
int ifindex;
|
||||
NMEthtoolFeatureStates *features;
|
||||
NMTernary requested[_NM_ETHTOOL_ID_FEATURE_NUM];
|
||||
NMEthtoolCoalesceStates *coalesce;
|
||||
} EthtoolState;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -812,64 +813,47 @@ NM_UTILS_LOOKUP_STR_DEFINE (mtu_source_to_str, NMDeviceMtuSource,
|
|||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_ethtool_state_reset (NMDevice *self)
|
||||
_ethtool_features_reset (NMDevice *self,
|
||||
NMPlatform *platform,
|
||||
EthtoolState *ethtool_state)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
gs_free NMEthtoolFeatureStates *features;
|
||||
|
||||
if (priv->ethtool_state) {
|
||||
gs_free NMEthtoolFeatureStates *features = priv->ethtool_state->features;
|
||||
gs_free EthtoolState *ethtool_state = g_steal_pointer (&priv->ethtool_state);
|
||||
features = g_steal_pointer (ðtool_state->features);
|
||||
|
||||
if (!nm_platform_ethtool_set_features (nm_device_get_platform (self),
|
||||
ethtool_state->ifindex,
|
||||
features,
|
||||
ethtool_state->requested,
|
||||
FALSE))
|
||||
_LOGW (LOGD_DEVICE, "ethtool: failure resetting one or more offload features");
|
||||
else
|
||||
_LOGD (LOGD_DEVICE, "ethtool: offload features successfully reset");
|
||||
}
|
||||
if (!nm_platform_ethtool_set_features (platform,
|
||||
ethtool_state->ifindex,
|
||||
features,
|
||||
ethtool_state->requested,
|
||||
FALSE))
|
||||
_LOGW (LOGD_DEVICE, "ethtool: failure resetting one or more offload features");
|
||||
else
|
||||
_LOGD (LOGD_DEVICE, "ethtool: offload features successfully reset");
|
||||
}
|
||||
|
||||
static void
|
||||
_ethtool_state_set (NMDevice *self)
|
||||
_ethtool_features_set (NMDevice *self,
|
||||
NMPlatform *platform,
|
||||
EthtoolState *ethtool_state,
|
||||
NMSettingEthtool *s_ethtool)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
int ifindex;
|
||||
NMConnection *connection;
|
||||
NMSettingEthtool *s_ethtool;
|
||||
NMPlatform *platform;
|
||||
gs_free EthtoolState *ethtool_state = NULL;
|
||||
gs_free NMEthtoolFeatureStates *features = NULL;
|
||||
|
||||
_ethtool_state_reset (self);
|
||||
if (ethtool_state->features)
|
||||
_ethtool_features_reset (self, platform, ethtool_state);
|
||||
|
||||
connection = nm_device_get_applied_connection (self);
|
||||
if (!connection)
|
||||
return;
|
||||
|
||||
ifindex = nm_device_get_ip_ifindex (self);
|
||||
if (ifindex <= 0)
|
||||
return;
|
||||
|
||||
s_ethtool = NM_SETTING_ETHTOOL (nm_connection_get_setting (connection, NM_TYPE_SETTING_ETHTOOL));
|
||||
if (!s_ethtool)
|
||||
return;
|
||||
|
||||
ethtool_state = g_new (EthtoolState, 1);
|
||||
if (nm_setting_ethtool_init_features (s_ethtool, ethtool_state->requested) == 0)
|
||||
return;
|
||||
|
||||
platform = nm_device_get_platform (self);
|
||||
|
||||
features = nm_platform_ethtool_get_link_features (platform, ifindex);
|
||||
features = nm_platform_ethtool_get_link_features (platform,
|
||||
ethtool_state->ifindex);
|
||||
if (!features) {
|
||||
_LOGW (LOGD_DEVICE, "ethtool: failure setting offload features (cannot read features)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nm_platform_ethtool_set_features (platform,
|
||||
ifindex,
|
||||
ethtool_state->ifindex,
|
||||
features,
|
||||
ethtool_state->requested,
|
||||
TRUE))
|
||||
|
|
@ -877,9 +861,170 @@ _ethtool_state_set (NMDevice *self)
|
|||
else
|
||||
_LOGD (LOGD_DEVICE, "ethtool: offload features successfully set");
|
||||
|
||||
ethtool_state->ifindex = ifindex;
|
||||
ethtool_state->features = g_steal_pointer (&features);
|
||||
priv->ethtool_state = g_steal_pointer (ðtool_state);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_ethtool_init_coalesce (NMDevice *self,
|
||||
NMPlatform *platform,
|
||||
NMSettingEthtool *s_ethtool,
|
||||
NMEthtoolCoalesceStates *coalesce)
|
||||
{
|
||||
GHashTable *hash;
|
||||
GHashTableIter iter;
|
||||
const char *name;
|
||||
GVariant *variant;
|
||||
gsize n_coalesce_set = 0;
|
||||
|
||||
nm_assert (self);
|
||||
nm_assert (platform);
|
||||
nm_assert (coalesce);
|
||||
nm_assert (NM_IS_SETTING_ETHTOOL (s_ethtool));
|
||||
|
||||
hash = _nm_setting_gendata_hash (NM_SETTING (s_ethtool), FALSE);
|
||||
if (!hash)
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_iter_init (&iter, hash);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) {
|
||||
if (!g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32))
|
||||
continue;
|
||||
|
||||
if (!nm_platform_ethtool_init_coalesce (platform,
|
||||
coalesce,
|
||||
name,
|
||||
g_variant_get_uint32(variant))) {
|
||||
_LOGW (LOGD_DEVICE, "ethtool: invalid coalesce setting %s", name);
|
||||
return FALSE;
|
||||
}
|
||||
++n_coalesce_set;
|
||||
|
||||
}
|
||||
|
||||
return (!!n_coalesce_set);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
_ethtool_coalesce_reset (NMDevice *self,
|
||||
NMPlatform *platform,
|
||||
EthtoolState *ethtool_state)
|
||||
{
|
||||
gs_free NMEthtoolCoalesceStates *coalesce = NULL;
|
||||
|
||||
nm_assert (NM_IS_DEVICE (self));
|
||||
nm_assert (NM_IS_PLATFORM (platform));
|
||||
nm_assert (ethtool_state);
|
||||
|
||||
coalesce = g_steal_pointer (ðtool_state->coalesce);
|
||||
|
||||
if (!nm_platform_ethtool_set_coalesce (platform,
|
||||
ethtool_state->ifindex,
|
||||
coalesce,
|
||||
FALSE))
|
||||
_LOGW (LOGD_DEVICE, "ethtool: failure resetting one or more coalesce settings");
|
||||
else
|
||||
_LOGD (LOGD_DEVICE, "ethtool: coalesce settings successfully reset");
|
||||
}
|
||||
|
||||
static void
|
||||
_ethtool_coalesce_set (NMDevice *self,
|
||||
NMPlatform *platform,
|
||||
EthtoolState *ethtool_state,
|
||||
NMSettingEthtool *s_ethtool)
|
||||
{
|
||||
gs_free NMEthtoolCoalesceStates *coalesce = NULL;
|
||||
|
||||
nm_assert (ethtool_state);
|
||||
nm_assert (NM_IS_DEVICE (self));
|
||||
nm_assert (NM_IS_PLATFORM (platform));
|
||||
nm_assert (NM_IS_SETTING_ETHTOOL (s_ethtool));
|
||||
|
||||
coalesce = nm_platform_ethtool_get_link_coalesce (platform,
|
||||
ethtool_state->ifindex);
|
||||
|
||||
if (!coalesce) {
|
||||
_LOGW (LOGD_DEVICE, "ethtool: failure getting coalesce settings (cannot read)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_ethtool_init_coalesce (self,
|
||||
platform,
|
||||
s_ethtool,
|
||||
coalesce))
|
||||
return;
|
||||
|
||||
if (!nm_platform_ethtool_set_coalesce (platform,
|
||||
ethtool_state->ifindex,
|
||||
coalesce,
|
||||
TRUE)) {
|
||||
_LOGW (LOGD_DEVICE, "ethtool: failure setting coalesce settings");
|
||||
return;
|
||||
}
|
||||
_LOGD (LOGD_DEVICE, "ethtool: coalesce settings successfully set");
|
||||
|
||||
ethtool_state->coalesce = g_steal_pointer (&coalesce);
|
||||
}
|
||||
|
||||
static void
|
||||
_ethtool_state_reset (NMDevice *self)
|
||||
{
|
||||
NMPlatform *platform = nm_device_get_platform (self);
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
gs_free EthtoolState *ethtool_state = g_steal_pointer (&priv->ethtool_state);
|
||||
|
||||
if (!ethtool_state)
|
||||
return;
|
||||
|
||||
if (ethtool_state->features)
|
||||
_ethtool_features_reset (self, platform, ethtool_state);
|
||||
if (ethtool_state->coalesce)
|
||||
_ethtool_coalesce_reset (self, platform, ethtool_state);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
_ethtool_state_set (NMDevice *self)
|
||||
{
|
||||
int ifindex;
|
||||
NMPlatform *platform;
|
||||
NMConnection *connection;
|
||||
NMSettingEthtool *s_ethtool;
|
||||
gs_free EthtoolState *ethtool_state = NULL;
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
ifindex = nm_device_get_ip_ifindex (self);
|
||||
if (ifindex <= 0)
|
||||
return;
|
||||
|
||||
platform = nm_device_get_platform (self);
|
||||
nm_assert (platform);
|
||||
|
||||
connection = nm_device_get_applied_connection (self);
|
||||
if (!connection)
|
||||
return;
|
||||
|
||||
s_ethtool = NM_SETTING_ETHTOOL (nm_connection_get_setting (connection, NM_TYPE_SETTING_ETHTOOL));
|
||||
if (!s_ethtool)
|
||||
return;
|
||||
|
||||
ethtool_state = g_new0 (EthtoolState, 1);
|
||||
ethtool_state->ifindex = ifindex;
|
||||
|
||||
_ethtool_features_set (self,
|
||||
platform,
|
||||
ethtool_state,
|
||||
s_ethtool);
|
||||
_ethtool_coalesce_set (self,
|
||||
platform,
|
||||
ethtool_state,
|
||||
s_ethtool);
|
||||
|
||||
if ( ethtool_state->features
|
||||
|| ethtool_state->coalesce)
|
||||
priv->ethtool_state = g_steal_pointer (ðtool_state);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -264,6 +264,7 @@ out:
|
|||
|
||||
static
|
||||
NM_UTILS_ENUM2STR_DEFINE (_ethtool_cmd_to_string, guint32,
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GCOALESCE, "ETHTOOL_GCOALESCE"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GDRVINFO, "ETHTOOL_GDRVINFO"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GFEATURES, "ETHTOOL_GFEATURES"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GLINK, "ETHTOOL_GLINK"),
|
||||
|
|
@ -273,6 +274,7 @@ NM_UTILS_ENUM2STR_DEFINE (_ethtool_cmd_to_string, guint32,
|
|||
NM_UTILS_ENUM2STR (ETHTOOL_GSTATS, "ETHTOOL_GSTATS"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GSTRINGS, "ETHTOOL_GSTRINGS"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GWOL, "ETHTOOL_GWOL"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_SCOALESCE, "ETHTOOL_SCOALESCE"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_SFEATURES, "ETHTOOL_SFEATURES"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_SSET, "ETHTOOL_SSET"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_SWOL, "ETHTOOL_SWOL"),
|
||||
|
|
@ -804,6 +806,145 @@ nmp_utils_ethtool_set_features (int ifindex,
|
|||
return success;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ethtool_get_coalesce (SocketHandle *shandle,
|
||||
NMEthtoolCoalesceState *out_state)
|
||||
{
|
||||
struct ethtool_coalesce eth_data;
|
||||
|
||||
eth_data.cmd = ETHTOOL_GCOALESCE;
|
||||
|
||||
if (_ethtool_call_handle (shandle,
|
||||
ð_data,
|
||||
sizeof (struct ethtool_coalesce)) != 0)
|
||||
return FALSE;
|
||||
|
||||
out_state->rx_coalesce_usecs = eth_data.rx_coalesce_usecs;
|
||||
out_state->rx_max_coalesced_frames = eth_data.rx_max_coalesced_frames;
|
||||
out_state->rx_coalesce_usecs_irq = eth_data.rx_coalesce_usecs_irq;
|
||||
out_state->rx_max_coalesced_frames_irq = eth_data.rx_max_coalesced_frames_irq;
|
||||
out_state->tx_coalesce_usecs = eth_data.tx_coalesce_usecs;
|
||||
out_state->tx_max_coalesced_frames = eth_data.tx_max_coalesced_frames;
|
||||
out_state->tx_coalesce_usecs_irq = eth_data.tx_coalesce_usecs_irq;
|
||||
out_state->tx_max_coalesced_frames_irq = eth_data.tx_max_coalesced_frames_irq;
|
||||
out_state->stats_block_coalesce_usecs = eth_data.stats_block_coalesce_usecs;
|
||||
out_state->use_adaptive_rx_coalesce = eth_data.use_adaptive_rx_coalesce;
|
||||
out_state->use_adaptive_tx_coalesce = eth_data.use_adaptive_tx_coalesce;
|
||||
out_state->pkt_rate_low = eth_data.pkt_rate_low;
|
||||
out_state->rx_coalesce_usecs_low = eth_data.rx_coalesce_usecs_low;
|
||||
out_state->rx_max_coalesced_frames_low = eth_data.rx_max_coalesced_frames_low;
|
||||
out_state->tx_coalesce_usecs_low = eth_data.tx_coalesce_usecs_low;
|
||||
out_state->tx_max_coalesced_frames_low = eth_data.tx_max_coalesced_frames_low;
|
||||
out_state->pkt_rate_high = eth_data.pkt_rate_high;
|
||||
out_state->rx_coalesce_usecs_high = eth_data.rx_coalesce_usecs_high;
|
||||
out_state->rx_max_coalesced_frames_high = eth_data.rx_max_coalesced_frames_high;
|
||||
out_state->tx_coalesce_usecs_high = eth_data.tx_coalesce_usecs_high;
|
||||
out_state->tx_max_coalesced_frames_high = eth_data.tx_max_coalesced_frames_high;
|
||||
out_state->rate_sample_interval = eth_data.rate_sample_interval;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
NMEthtoolCoalesceStates *
|
||||
nmp_utils_ethtool_get_coalesce (int ifindex)
|
||||
{
|
||||
gs_free NMEthtoolCoalesceStates *coalesce = NULL;
|
||||
nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT (ifindex);
|
||||
|
||||
g_return_val_if_fail (ifindex > 0, NULL);
|
||||
|
||||
coalesce = g_new0 (NMEthtoolCoalesceStates, 1);
|
||||
|
||||
if (!ethtool_get_coalesce (&shandle, &coalesce->old_state)) {
|
||||
nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure getting coalesce settings",
|
||||
ifindex,
|
||||
"get-coalesce");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* copy into requested as well, so that they're merged when applying */
|
||||
coalesce->requested_state = coalesce->old_state;
|
||||
|
||||
nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: retrieved kernel coalesce settings",
|
||||
ifindex,
|
||||
"get-coalesce");
|
||||
return g_steal_pointer (&coalesce);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ethtool_set_coalesce (SocketHandle *shandle,
|
||||
const NMEthtoolCoalesceState *state)
|
||||
{
|
||||
gboolean success;
|
||||
struct ethtool_coalesce eth_data;
|
||||
|
||||
g_return_val_if_fail (shandle, FALSE);
|
||||
g_return_val_if_fail (state, FALSE);
|
||||
|
||||
eth_data = (struct ethtool_coalesce) {
|
||||
.cmd = ETHTOOL_SCOALESCE,
|
||||
.rx_coalesce_usecs = state->rx_coalesce_usecs,
|
||||
.rx_max_coalesced_frames = state->rx_max_coalesced_frames,
|
||||
.rx_coalesce_usecs_irq = state->rx_coalesce_usecs_irq,
|
||||
.rx_max_coalesced_frames_irq = state->rx_max_coalesced_frames_irq,
|
||||
.tx_coalesce_usecs = state->tx_coalesce_usecs,
|
||||
.tx_max_coalesced_frames = state->tx_max_coalesced_frames,
|
||||
.tx_coalesce_usecs_irq = state->tx_coalesce_usecs_irq,
|
||||
.tx_max_coalesced_frames_irq = state->tx_max_coalesced_frames_irq,
|
||||
.stats_block_coalesce_usecs = state->stats_block_coalesce_usecs,
|
||||
.use_adaptive_rx_coalesce = state->use_adaptive_rx_coalesce,
|
||||
.use_adaptive_tx_coalesce = state->use_adaptive_tx_coalesce,
|
||||
.pkt_rate_low = state->pkt_rate_low,
|
||||
.rx_coalesce_usecs_low = state->rx_coalesce_usecs_low,
|
||||
.rx_max_coalesced_frames_low = state->rx_max_coalesced_frames_low,
|
||||
.tx_coalesce_usecs_low = state->tx_coalesce_usecs_low,
|
||||
.tx_max_coalesced_frames_low = state->tx_max_coalesced_frames_low,
|
||||
.pkt_rate_high = state->pkt_rate_high,
|
||||
.rx_coalesce_usecs_high = state->rx_coalesce_usecs_high,
|
||||
.rx_max_coalesced_frames_high = state->rx_max_coalesced_frames_high,
|
||||
.tx_coalesce_usecs_high = state->tx_coalesce_usecs_high,
|
||||
.tx_max_coalesced_frames_high = state->tx_max_coalesced_frames_high,
|
||||
.rate_sample_interval = state->rate_sample_interval,
|
||||
};
|
||||
|
||||
success = (_ethtool_call_handle (shandle,
|
||||
ð_data,
|
||||
sizeof (struct ethtool_coalesce)) == 0);
|
||||
return success;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nmp_utils_ethtool_set_coalesce (int ifindex,
|
||||
const NMEthtoolCoalesceStates *coalesce,
|
||||
gboolean do_set)
|
||||
{
|
||||
gboolean success;
|
||||
nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT (ifindex);
|
||||
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
g_return_val_if_fail (coalesce, FALSE);
|
||||
|
||||
if (do_set)
|
||||
success = ethtool_set_coalesce (&shandle, &coalesce->requested_state);
|
||||
else
|
||||
success = ethtool_set_coalesce (&shandle, &coalesce->old_state);
|
||||
|
||||
if (!success) {
|
||||
nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure %s coalesce settings",
|
||||
ifindex,
|
||||
"set-coalesce",
|
||||
do_set ? "setting" : "resetting");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: %s kernel coalesce settings",
|
||||
ifindex,
|
||||
"set-coalesce",
|
||||
do_set ? "set" : "reset");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
|
|
|
|||
|
|
@ -92,6 +92,42 @@ gboolean nmp_utils_ethtool_set_features (int ifindex,
|
|||
const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */,
|
||||
gboolean do_set /* or reset */);
|
||||
|
||||
typedef struct {
|
||||
guint32 rx_coalesce_usecs;
|
||||
guint32 rx_max_coalesced_frames;
|
||||
guint32 rx_coalesce_usecs_irq;
|
||||
guint32 rx_max_coalesced_frames_irq;
|
||||
guint32 tx_coalesce_usecs;
|
||||
guint32 tx_max_coalesced_frames;
|
||||
guint32 tx_coalesce_usecs_irq;
|
||||
guint32 tx_max_coalesced_frames_irq;
|
||||
guint32 stats_block_coalesce_usecs;
|
||||
guint32 use_adaptive_rx_coalesce;
|
||||
guint32 use_adaptive_tx_coalesce;
|
||||
guint32 pkt_rate_low;
|
||||
guint32 rx_coalesce_usecs_low;
|
||||
guint32 rx_max_coalesced_frames_low;
|
||||
guint32 tx_coalesce_usecs_low;
|
||||
guint32 tx_max_coalesced_frames_low;
|
||||
guint32 pkt_rate_high;
|
||||
guint32 rx_coalesce_usecs_high;
|
||||
guint32 rx_max_coalesced_frames_high;
|
||||
guint32 tx_coalesce_usecs_high;
|
||||
guint32 tx_max_coalesced_frames_high;
|
||||
guint32 rate_sample_interval;
|
||||
} NMEthtoolCoalesceState;
|
||||
|
||||
struct _NMEthtoolCoalesceStates {
|
||||
NMEthtoolCoalesceState old_state;
|
||||
NMEthtoolCoalesceState requested_state;
|
||||
};
|
||||
|
||||
NMEthtoolCoalesceStates * nmp_utils_ethtool_get_coalesce (int ifindex);
|
||||
|
||||
gboolean nmp_utils_ethtool_set_coalesce (int ifindex,
|
||||
const NMEthtoolCoalesceStates *coalesce,
|
||||
gboolean do_set);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean nmp_utils_mii_supports_carrier_detect (int ifindex);
|
||||
|
|
|
|||
|
|
@ -3214,6 +3214,121 @@ nm_platform_ethtool_set_features (NMPlatform *self,
|
|||
return nmp_utils_ethtool_set_features (ifindex, features, requested, do_set);
|
||||
}
|
||||
|
||||
NMEthtoolCoalesceStates *
|
||||
nm_platform_ethtool_get_link_coalesce (NMPlatform *self, int ifindex)
|
||||
{
|
||||
_CHECK_SELF_NETNS (self, klass, netns, NULL);
|
||||
|
||||
g_return_val_if_fail (ifindex > 0, NULL);
|
||||
|
||||
return nmp_utils_ethtool_get_coalesce (ifindex);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_platform_ethtool_init_coalesce (NMPlatform *self,
|
||||
NMEthtoolCoalesceStates *coalesce,
|
||||
const char *option_name,
|
||||
guint32 value)
|
||||
{
|
||||
NMEthtoolID ethtool_id;
|
||||
NMEthtoolCoalesceState *state;
|
||||
|
||||
g_return_val_if_fail (coalesce, FALSE);
|
||||
g_return_val_if_fail (option_name, FALSE);
|
||||
|
||||
state = &coalesce->requested_state;
|
||||
ethtool_id = nm_ethtool_id_get_by_name (option_name);
|
||||
|
||||
if (!nm_ethtool_id_is_coalesce (ethtool_id))
|
||||
return FALSE;
|
||||
|
||||
switch (ethtool_id) {
|
||||
case NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX:
|
||||
state->use_adaptive_rx_coalesce = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX:
|
||||
state->use_adaptive_tx_coalesce = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH:
|
||||
state->pkt_rate_high = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW:
|
||||
state->pkt_rate_low = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_RX_FRAMES:
|
||||
state->rx_max_coalesced_frames = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_RX_FRAMES_HIGH:
|
||||
state->rx_max_coalesced_frames_high = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_RX_FRAMES_IRQ:
|
||||
state->rx_max_coalesced_frames_irq = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_RX_FRAMES_LOW:
|
||||
state->rx_max_coalesced_frames_low = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_RX_USECS:
|
||||
state->rx_coalesce_usecs = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_RX_USECS_HIGH:
|
||||
state->rx_coalesce_usecs_high = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_RX_USECS_IRQ:
|
||||
state->rx_coalesce_usecs_irq = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_RX_USECS_LOW:
|
||||
state->rx_coalesce_usecs_low = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL:
|
||||
state->rate_sample_interval = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS:
|
||||
state->stats_block_coalesce_usecs = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_TX_FRAMES:
|
||||
state->tx_max_coalesced_frames = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_TX_FRAMES_HIGH:
|
||||
state->tx_max_coalesced_frames_high = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_TX_FRAMES_IRQ:
|
||||
state->tx_max_coalesced_frames_irq = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_TX_FRAMES_LOW:
|
||||
state->tx_max_coalesced_frames_low = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_TX_USECS:
|
||||
state->tx_coalesce_usecs = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH:
|
||||
state->tx_coalesce_usecs_high = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ:
|
||||
state->tx_coalesce_usecs_irq = value;
|
||||
break;
|
||||
case NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW:
|
||||
state->tx_coalesce_usecs_low = value;
|
||||
break;
|
||||
default:
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_platform_ethtool_set_coalesce (NMPlatform *self,
|
||||
int ifindex,
|
||||
const NMEthtoolCoalesceStates *coalesce,
|
||||
gboolean do_set)
|
||||
{
|
||||
_CHECK_SELF_NETNS (self, klass, netns, FALSE);
|
||||
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
|
||||
return nmp_utils_ethtool_set_coalesce (ifindex, coalesce, do_set);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const NMDedupMultiHeadEntry *
|
||||
|
|
|
|||
|
|
@ -1952,6 +1952,21 @@ gboolean nm_platform_ethtool_set_features (NMPlatform *self,
|
|||
const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */,
|
||||
gboolean do_set /* or reset */);
|
||||
|
||||
typedef struct _NMEthtoolCoalesceStates NMEthtoolCoalesceStates;
|
||||
|
||||
NMEthtoolCoalesceStates *nm_platform_ethtool_get_link_coalesce (NMPlatform *self,
|
||||
int ifindex);
|
||||
|
||||
gboolean nm_platform_ethtool_init_coalesce (NMPlatform *self,
|
||||
NMEthtoolCoalesceStates *coalesce,
|
||||
const char *option_name,
|
||||
guint32 value);
|
||||
|
||||
gboolean nm_platform_ethtool_set_coalesce (NMPlatform *self,
|
||||
int ifindex,
|
||||
const NMEthtoolCoalesceStates *coalesce,
|
||||
gboolean do_set);
|
||||
|
||||
const char * nm_platform_link_duplex_type_to_string (NMPlatformLinkDuplexType duplex);
|
||||
|
||||
void nm_platform_ip4_dev_route_blacklist_set (NMPlatform *self,
|
||||
|
|
|
|||
|
|
@ -3290,14 +3290,14 @@ test_ethtool_features_get (void)
|
|||
g_ptr_array_add (gfree_keeper, requested);
|
||||
|
||||
if (i_run == 0) {
|
||||
requested[NM_ETHTOOL_ID_FEATURE_RX] = NM_TERNARY_FALSE;
|
||||
requested[NM_ETHTOOL_ID_FEATURE_TSO] = NM_TERNARY_FALSE;
|
||||
requested[NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION] = NM_TERNARY_FALSE;
|
||||
requested[NM_ETHTOOL_ID_FEATURE_RX - _NM_ETHTOOL_ID_FEATURE_FIRST] = NM_TERNARY_FALSE;
|
||||
requested[NM_ETHTOOL_ID_FEATURE_TSO - _NM_ETHTOOL_ID_FEATURE_FIRST] = NM_TERNARY_FALSE;
|
||||
requested[NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION - _NM_ETHTOOL_ID_FEATURE_FIRST] = NM_TERNARY_FALSE;
|
||||
} else if (i_run == 1)
|
||||
do_set = FALSE;
|
||||
else if (i_run == 2) {
|
||||
requested[NM_ETHTOOL_ID_FEATURE_TSO] = NM_TERNARY_FALSE;
|
||||
requested[NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION] = NM_TERNARY_TRUE;
|
||||
requested[NM_ETHTOOL_ID_FEATURE_TSO - _NM_ETHTOOL_ID_FEATURE_FIRST] = NM_TERNARY_FALSE;
|
||||
requested[NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION - _NM_ETHTOOL_ID_FEATURE_FIRST] = NM_TERNARY_TRUE;
|
||||
} else if (i_run == 3)
|
||||
do_set = FALSE;
|
||||
|
||||
|
|
|
|||
|
|
@ -4288,7 +4288,8 @@ parse_ethtool_option (const char *value,
|
|||
|
||||
d = nms_ifcfg_rh_utils_get_ethtool_by_name (opt);
|
||||
|
||||
if (!d) {
|
||||
if ( !d
|
||||
|| !nm_ethtool_id_is_feature (d->id)) {
|
||||
if (onoff != NM_TERNARY_DEFAULT) {
|
||||
/* the next value is just the on/off argument. Skip it too. */
|
||||
i++;
|
||||
|
|
@ -4309,6 +4310,45 @@ parse_ethtool_option (const char *value,
|
|||
d->optname,
|
||||
onoff);
|
||||
}
|
||||
} else if (NM_IN_STRSET (words[0], "-C", "--coalesce")) {
|
||||
if (!words[1]) {
|
||||
/* first argument must be the interface name. This is invalid. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (!*out_s_ethtool)
|
||||
*out_s_ethtool = NM_SETTING_ETHTOOL (nm_setting_ethtool_new ());
|
||||
|
||||
for (i = 2; words[i]; ) {
|
||||
const char *opt = words[i];
|
||||
const char *opt_val = words[++i];
|
||||
const NMEthtoolData *d = NULL;
|
||||
gint64 i64;
|
||||
|
||||
i64 = _nm_utils_ascii_str_to_int64 (opt_val, 10, 0, G_MAXUINT32, -1);
|
||||
d = nms_ifcfg_rh_utils_get_ethtool_by_name (opt);
|
||||
|
||||
if ( !d
|
||||
|| !nm_ethtool_id_is_coalesce (d->id)) {
|
||||
if (i64 != -1) {
|
||||
/* the next value is just the argument. Skip it too. */
|
||||
i++;
|
||||
}
|
||||
/* silently ignore unsupported coalesce settings. */
|
||||
continue;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (i64 == -1) {
|
||||
PARSE_WARNING ("Expects integer argument for setting '%s'", opt);
|
||||
continue;
|
||||
}
|
||||
|
||||
nm_setting_ethtool_set_coalesce (*out_s_ethtool,
|
||||
d->optname,
|
||||
(guint32) i64);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -522,9 +522,30 @@ nms_ifcfg_rh_utils_user_key_decode (const char *name, GString *str_buffer)
|
|||
/*****************************************************************************/
|
||||
|
||||
const char *const _nm_ethtool_ifcfg_names[] = {
|
||||
#define ETHT_NAME(eid, ename) \
|
||||
[eid - _NM_ETHTOOL_ID_FEATURE_FIRST] = ""ename""
|
||||
/* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */
|
||||
#define ETHT_NAME(eid, ename) [eid] = ""ename""
|
||||
/* indexed by NMEthtoolID */
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX, "adaptive-rx"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX, "adaptive-tx"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_RX_FRAMES, "rx-frames"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_RX_FRAMES_HIGH, "rx-frames-high"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_RX_FRAMES_IRQ, "rx-frames-irq"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_RX_FRAMES_LOW, "rx-frames-low"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH, "pkt-rate-high"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW, "pkt-rate-low"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_RX_USECS, "rx-usecs"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_RX_USECS_HIGH, "rx-usecs-high"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_RX_USECS_IRQ, "rx-usecs-irq"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_RX_USECS_LOW, "rx-usecs-low"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL, "sample-interval"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS, "stats-block-usecs"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_TX_FRAMES, "tx-frames"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_TX_FRAMES_HIGH, "tx-frames-high"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_TX_FRAMES_IRQ, "tx-frames-irq"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_TX_FRAMES_LOW, "tx-frames-low"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_TX_USECS, "tx-usecs"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH, "tx-usecs-high"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ, "tx-usecs-irq"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW, "tx-usecs-low"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD, "esp-hw-offload"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD, "esp-tx-csum-hw-offload"),
|
||||
ETHT_NAME (NM_ETHTOOL_ID_FEATURE_FCOE_MTU, "fcoe-mtu"),
|
||||
|
|
@ -598,6 +619,8 @@ NM_UTILS_STRING_TABLE_LOOKUP_DEFINE (
|
|||
* the case and if yes, map them to the corresponding NetworkManager's features.
|
||||
*
|
||||
* That is why there are duplicate IDs in this list. */
|
||||
{ "adaptive-rx", NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX },
|
||||
{ "adaptive-tx", NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX },
|
||||
{ "esp-hw-offload", NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD },
|
||||
{ "esp-tx-csum-hw-offload", NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD },
|
||||
{ "fcoe-mtu", NM_ETHTOOL_ID_FEATURE_FCOE_MTU },
|
||||
|
|
@ -609,23 +632,35 @@ NM_UTILS_STRING_TABLE_LOOKUP_DEFINE (
|
|||
{ "loopback", NM_ETHTOOL_ID_FEATURE_LOOPBACK },
|
||||
{ "lro", NM_ETHTOOL_ID_FEATURE_LRO },
|
||||
{ "ntuple", NM_ETHTOOL_ID_FEATURE_NTUPLE },
|
||||
{ "pkt-rate-high", NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH },
|
||||
{ "pkt-rate-low", NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW },
|
||||
{ "rx", NM_ETHTOOL_ID_FEATURE_RX },
|
||||
{ "rx-all", NM_ETHTOOL_ID_FEATURE_RX_ALL },
|
||||
{ "rx-checksum", NM_ETHTOOL_ID_FEATURE_RX }, // kernel-only name
|
||||
{ "rx-fcs", NM_ETHTOOL_ID_FEATURE_RX_FCS },
|
||||
{ "rx-frames", NM_ETHTOOL_ID_COALESCE_RX_FRAMES },
|
||||
{ "rx-frames-high", NM_ETHTOOL_ID_COALESCE_RX_FRAMES_HIGH },
|
||||
{ "rx-frames-irq", NM_ETHTOOL_ID_COALESCE_RX_FRAMES_IRQ },
|
||||
{ "rx-frames-low", NM_ETHTOOL_ID_COALESCE_RX_FRAMES_LOW },
|
||||
{ "rx-gro", NM_ETHTOOL_ID_FEATURE_GRO }, // kernel-only name
|
||||
{ "rx-gro-hw", NM_ETHTOOL_ID_FEATURE_RX_GRO_HW },
|
||||
{ "rx-hashing", NM_ETHTOOL_ID_FEATURE_RXHASH }, // kernel-only name
|
||||
{ "rx-lro", NM_ETHTOOL_ID_FEATURE_LRO }, // kernel-only name
|
||||
{ "rx-ntuple-filter", NM_ETHTOOL_ID_FEATURE_NTUPLE }, // kernel-only name
|
||||
{ "rx-udp_tunnel-port-offload", NM_ETHTOOL_ID_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD },
|
||||
{ "rx-usecs", NM_ETHTOOL_ID_COALESCE_RX_USECS },
|
||||
{ "rx-usecs-high", NM_ETHTOOL_ID_COALESCE_RX_USECS_HIGH },
|
||||
{ "rx-usecs-irq", NM_ETHTOOL_ID_COALESCE_RX_USECS_IRQ },
|
||||
{ "rx-usecs-low", NM_ETHTOOL_ID_COALESCE_RX_USECS_LOW },
|
||||
{ "rx-vlan-filter", NM_ETHTOOL_ID_FEATURE_RX_VLAN_FILTER },
|
||||
{ "rx-vlan-hw-parse", NM_ETHTOOL_ID_FEATURE_RXVLAN }, // kernel-only name
|
||||
{ "rx-vlan-stag-filter", NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_FILTER },
|
||||
{ "rx-vlan-stag-hw-parse", NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_HW_PARSE },
|
||||
{ "rxhash", NM_ETHTOOL_ID_FEATURE_RXHASH },
|
||||
{ "rxvlan", NM_ETHTOOL_ID_FEATURE_RXVLAN },
|
||||
{ "sample-interval", NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL },
|
||||
{ "sg", NM_ETHTOOL_ID_FEATURE_SG },
|
||||
{ "stats-block-usecs", NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS },
|
||||
{ "tls-hw-record", NM_ETHTOOL_ID_FEATURE_TLS_HW_RECORD },
|
||||
{ "tls-hw-tx-offload", NM_ETHTOOL_ID_FEATURE_TLS_HW_TX_OFFLOAD },
|
||||
{ "tso", NM_ETHTOOL_ID_FEATURE_TSO },
|
||||
|
|
@ -637,6 +672,10 @@ NM_UTILS_STRING_TABLE_LOOKUP_DEFINE (
|
|||
{ "tx-checksum-sctp", NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_SCTP },
|
||||
{ "tx-esp-segmentation", NM_ETHTOOL_ID_FEATURE_TX_ESP_SEGMENTATION },
|
||||
{ "tx-fcoe-segmentation", NM_ETHTOOL_ID_FEATURE_TX_FCOE_SEGMENTATION },
|
||||
{ "tx-frames", NM_ETHTOOL_ID_COALESCE_TX_FRAMES },
|
||||
{ "tx-frames-high", NM_ETHTOOL_ID_COALESCE_TX_FRAMES_HIGH },
|
||||
{ "tx-frames-irq", NM_ETHTOOL_ID_COALESCE_TX_FRAMES_IRQ },
|
||||
{ "tx-frames-low", NM_ETHTOOL_ID_COALESCE_TX_FRAMES_LOW },
|
||||
{ "tx-generic-segmentation", NM_ETHTOOL_ID_FEATURE_GSO }, // kernel-only name
|
||||
{ "tx-gre-csum-segmentation", NM_ETHTOOL_ID_FEATURE_TX_GRE_CSUM_SEGMENTATION },
|
||||
{ "tx-gre-segmentation", NM_ETHTOOL_ID_FEATURE_TX_GRE_SEGMENTATION },
|
||||
|
|
@ -655,6 +694,10 @@ NM_UTILS_STRING_TABLE_LOOKUP_DEFINE (
|
|||
{ "tx-udp-segmentation", NM_ETHTOOL_ID_FEATURE_TX_UDP_SEGMENTATION },
|
||||
{ "tx-udp_tnl-csum-segmentation", NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION },
|
||||
{ "tx-udp_tnl-segmentation", NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION },
|
||||
{ "tx-usecs", NM_ETHTOOL_ID_COALESCE_TX_USECS },
|
||||
{ "tx-usecs-high", NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH },
|
||||
{ "tx-usecs-irq", NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ },
|
||||
{ "tx-usecs-low", NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW },
|
||||
{ "tx-vlan-hw-insert", NM_ETHTOOL_ID_FEATURE_TXVLAN }, // kernel-only name
|
||||
{ "tx-vlan-stag-hw-insert", NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT },
|
||||
{ "txvlan", NM_ETHTOOL_ID_FEATURE_TXVLAN },
|
||||
|
|
|
|||
|
|
@ -141,16 +141,16 @@ const NMSIfcfgKeyTypeInfo *nms_ifcfg_rh_utils_is_well_known_key (const char *key
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
extern const char *const _nm_ethtool_ifcfg_names[_NM_ETHTOOL_ID_FEATURE_NUM];
|
||||
extern const char *const _nm_ethtool_ifcfg_names[_NM_ETHTOOL_ID_NUM];
|
||||
|
||||
static inline const char *
|
||||
nms_ifcfg_rh_utils_get_ethtool_name (NMEthtoolID ethtool_id)
|
||||
{
|
||||
nm_assert (ethtool_id >= _NM_ETHTOOL_ID_FEATURE_FIRST && ethtool_id <= _NM_ETHTOOL_ID_FEATURE_LAST);
|
||||
nm_assert ((ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST) < G_N_ELEMENTS (_nm_ethtool_ifcfg_names));
|
||||
nm_assert (_nm_ethtool_ifcfg_names[ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST]);
|
||||
nm_assert (ethtool_id >= _NM_ETHTOOL_ID_FIRST && ethtool_id <= _NM_ETHTOOL_ID_LAST);
|
||||
nm_assert (ethtool_id < G_N_ELEMENTS (_nm_ethtool_ifcfg_names));
|
||||
nm_assert (_nm_ethtool_ifcfg_names[ethtool_id]);
|
||||
|
||||
return _nm_ethtool_ifcfg_names[ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST];
|
||||
return _nm_ethtool_ifcfg_names[ethtool_id];
|
||||
}
|
||||
|
||||
const NMEthtoolData *nms_ifcfg_rh_utils_get_ethtool_by_name (const char *name);
|
||||
|
|
|
|||
|
|
@ -1195,6 +1195,23 @@ write_ethtool_setting (NMConnection *connection, shvarFile *ifcfg, GError **erro
|
|||
g_string_append (str, nms_ifcfg_rh_utils_get_ethtool_name (ethtool_id));
|
||||
g_string_append (str, val == NM_TERNARY_TRUE ? " on" : " off");
|
||||
}
|
||||
|
||||
g_string_append (str, " ; -C ");
|
||||
g_string_append (str, iface ?: "net0");
|
||||
|
||||
for (ethtool_id = _NM_ETHTOOL_ID_COALESCE_FIRST; ethtool_id <= _NM_ETHTOOL_ID_COALESCE_LAST; ethtool_id++) {
|
||||
const NMEthtoolData *ed = nm_ethtool_data[ethtool_id];
|
||||
guint32 val;
|
||||
|
||||
nm_assert (nms_ifcfg_rh_utils_get_ethtool_name (ethtool_id));
|
||||
|
||||
if (!nm_setting_ethtool_get_coalesce (s_ethtool, ed->optname, &val))
|
||||
continue;
|
||||
|
||||
g_string_append_c (str, ' ');
|
||||
g_string_append (str, nms_ifcfg_rh_utils_get_ethtool_name (ethtool_id));
|
||||
g_string_append_printf (str, " %"G_GUINT32_FORMAT, val);
|
||||
}
|
||||
}
|
||||
|
||||
if (str) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
TYPE=Ethernet
|
||||
PROXY_METHOD=none
|
||||
BROWSER_ONLY=no
|
||||
ETHTOOL_OPTS="autoneg on ; -K net0 rxvlan off tx on"
|
||||
ETHTOOL_OPTS="autoneg on ; -K net0 rxvlan off tx on ; -C net0"
|
||||
BOOTPROTO=dhcp
|
||||
DEFROUTE=yes
|
||||
IPV4_FAILURE_FATAL=no
|
||||
|
|
|
|||
|
|
@ -10368,18 +10368,16 @@ test_ethtool_names (void)
|
|||
NMEthtoolID id;
|
||||
int i;
|
||||
|
||||
for (id = _NM_ETHTOOL_ID_FEATURE_FIRST; id <= _NM_ETHTOOL_ID_FEATURE_LAST; id++) {
|
||||
for (id = _NM_ETHTOOL_ID_FIRST; id <= _NM_ETHTOOL_ID_LAST; id++) {
|
||||
const char *ifcfg_rh_name;
|
||||
int idx;
|
||||
|
||||
idx = id - _NM_ETHTOOL_ID_FEATURE_FIRST;
|
||||
g_assert (idx >= 0);
|
||||
g_assert (idx < G_N_ELEMENTS (_nm_ethtool_ifcfg_names));
|
||||
ifcfg_rh_name = _nm_ethtool_ifcfg_names[idx];
|
||||
g_assert (id >= 0);
|
||||
g_assert (id < G_N_ELEMENTS (_nm_ethtool_ifcfg_names));
|
||||
ifcfg_rh_name = _nm_ethtool_ifcfg_names[id];
|
||||
g_assert (ifcfg_rh_name && ifcfg_rh_name[0]);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (_nm_ethtool_ifcfg_names); i++) {
|
||||
if (i != idx)
|
||||
if (i != id)
|
||||
g_assert_cmpstr (ifcfg_rh_name, !=, _nm_ethtool_ifcfg_names[i]);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue