diff options
author | Antonio Cardace <acardace@redhat.com> | 2020-05-20 10:55:57 +0200 |
---|---|---|
committer | Antonio Cardace <acardace@redhat.com> | 2020-05-20 10:55:57 +0200 |
commit | 2eccd19b9132340a667d278c27ed28df53d09168 (patch) | |
tree | 4b09b2b5e3298823d7d4ce1c86bb305b5bb9663b | |
parent | d71f920f2e5e5f1bbe1760695787d1e998d56c0e (diff) | |
parent | 2ce0e714b60aa59b1d0a46333de29d5c95ef07a4 (diff) | |
download | NetworkManager-2eccd19b9132340a667d278c27ed28df53d09168.tar.gz |
ethtool: merge branch 'ac/ethtool_opts_ring'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/508
20 files changed, 1074 insertions, 289 deletions
diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index aca6c396a7..2c3e0d534a 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -4132,6 +4132,16 @@ _get_fcn_ethtool (ARGS_GET_FCN) if (s && get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) s = gettext (s); return s; + } else if (nm_ethtool_id_is_ring (ethtool_id)) { + if (!nm_setting_ethtool_get_ring (NM_SETTING_ETHTOOL (setting), + nm_ethtool_data[ethtool_id]->optname, + &u32)) { + NM_SET_OUT (out_is_default, TRUE); + return NULL; + } + + return_str = g_strdup_printf ("%"G_GUINT32_FORMAT, u32); + RETURN_STR_TO_FREE (return_str); } nm_assert_not_reached(); return NULL; @@ -4142,12 +4152,18 @@ _set_fcn_ethtool (ARGS_SET_FCN) { gint64 i64; NMEthtoolID ethtool_id = property_info->property_typ_data->subtype.ethtool.ethtool_id; + NMEthtoolType ethtool_type = nm_ethtool_id_to_type (ethtool_id); - if (nm_ethtool_id_is_coalesce (ethtool_id)) { - + if (NM_IN_SET (ethtool_type, + NM_ETHTOOL_TYPE_COALESCE, + NM_ETHTOOL_TYPE_RING)) { if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) { - nm_setting_ethtool_clear_coalesce (NM_SETTING_ETHTOOL (setting), - nm_ethtool_data[ethtool_id]->optname); + if (ethtool_type == NM_ETHTOOL_TYPE_COALESCE) + nm_setting_ethtool_clear_coalesce (NM_SETTING_ETHTOOL (setting), + nm_ethtool_data[ethtool_id]->optname); + else + nm_setting_ethtool_clear_ring (NM_SETTING_ETHTOOL (setting), + nm_ethtool_data[ethtool_id]->optname); return TRUE; } @@ -4160,13 +4176,18 @@ _set_fcn_ethtool (ARGS_SET_FCN) return FALSE; } - nm_setting_ethtool_set_coalesce (NM_SETTING_ETHTOOL (setting), - nm_ethtool_data[ethtool_id]->optname, - (guint32) i64); + if (ethtool_type == NM_ETHTOOL_TYPE_COALESCE) + nm_setting_ethtool_set_coalesce (NM_SETTING_ETHTOOL (setting), + nm_ethtool_data[ethtool_id]->optname, + (guint32) i64); + else + nm_setting_ethtool_set_ring (NM_SETTING_ETHTOOL (setting), + nm_ethtool_data[ethtool_id]->optname, + (guint32) i64); return TRUE; } - if (nm_ethtool_id_is_feature (ethtool_id)) { + if (ethtool_type == NM_ETHTOOL_TYPE_FEATURE) { gs_free char *value_to_free = NULL; NMTernary val; @@ -5507,6 +5528,10 @@ static const NMMetaPropertyInfo *const property_infos_ETHTOOL[] = { PROPERTY_INFO_ETHTOOL (COALESCE_TX_USECS_IRQ), PROPERTY_INFO_ETHTOOL (COALESCE_TX_USECS_HIGH), PROPERTY_INFO_ETHTOOL (COALESCE_TX_USECS_LOW), + PROPERTY_INFO_ETHTOOL (RING_RX), + PROPERTY_INFO_ETHTOOL (RING_RX_JUMBO), + PROPERTY_INFO_ETHTOOL (RING_RX_MINI), + PROPERTY_INFO_ETHTOOL (RING_TX), NULL, }; diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 00645a7618..cc37e68df0 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -310,6 +310,8 @@ gboolean _nm_setting_get_property (NMSetting *setting, const char *name, GValue /*****************************************************************************/ +typedef gboolean (*nm_setting_gendata_filter_fcn)(const char *name); + GHashTable *_nm_setting_gendata_hash (NMSetting *setting, gboolean create_if_necessary); @@ -334,6 +336,20 @@ const char *const*nm_setting_gendata_get_all_names (NMSetting *setting, GVariant *const*nm_setting_gendata_get_all_values (NMSetting *setting); +gboolean nm_setting_gendata_clear (NMSetting *setting, + const char *optname); + +gboolean nm_setting_gendata_clear_all (NMSetting *setting, + nm_setting_gendata_filter_fcn filter); + +gboolean nm_setting_gendata_get_uint32 (NMSetting *setting, + const char *optname, + guint32 *out_value); + +void nm_setting_gendata_set_uint32 (NMSetting *setting, + const char *optname, + guint32 value); + /*****************************************************************************/ guint nm_setting_ethtool_init_features (NMSettingEthtool *setting, diff --git a/libnm-core/nm-setting-ethtool.c b/libnm-core/nm-setting-ethtool.c index 6dc6d5d75a..deb1d96cca 100644 --- a/libnm-core/nm-setting-ethtool.c +++ b/libnm-core/nm-setting-ethtool.c @@ -58,6 +58,22 @@ nm_ethtool_optname_is_coalesce (const char *optname) return optname && nm_ethtool_id_is_coalesce (nm_ethtool_id_get_by_name (optname)); } +/** + * nm_ethtool_optname_is_ring: + * @optname: (allow-none): the option name to check + * + * Checks whether @optname is a valid option name for a ring setting. + * + * %Returns: %TRUE, if @optname is valid + * + * Since: 1.26 + */ +gboolean +nm_ethtool_optname_is_ring (const char *optname) +{ + return optname && nm_ethtool_id_is_ring (nm_ethtool_id_get_by_name (optname)); +} + /*****************************************************************************/ /** @@ -193,26 +209,10 @@ nm_setting_ethtool_set_feature (NMSettingEthtool *setting, void nm_setting_ethtool_clear_features (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_feature (name)) { - g_hash_table_iter_remove (&iter); - changed = TRUE; - } - } - - if (changed) + if (nm_setting_gendata_clear_all (NM_SETTING (setting), + &nm_ethtool_optname_is_feature)) _notify_attributes (setting); } @@ -276,19 +276,12 @@ 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; + return nm_setting_gendata_get_uint32 (NM_SETTING (setting), + optname, + out_value); } /** @@ -309,7 +302,6 @@ 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)); @@ -318,17 +310,14 @@ nm_setting_ethtool_set_coalesce (NMSettingEthtool *setting, 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))); + nm_setting_gendata_set_uint32 (NM_SETTING (setting), + optname, + value); _notify_attributes (setting); } @@ -345,16 +334,10 @@ 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)) + if (nm_setting_gendata_clear (NM_SETTING (setting), optname)) _notify_attributes (setting); } @@ -369,26 +352,109 @@ nm_setting_ethtool_clear_coalesce (NMSettingEthtool *setting, 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)); + + if (nm_setting_gendata_clear_all (NM_SETTING (setting), + &nm_ethtool_optname_is_coalesce)) + _notify_attributes (setting); +} + +/** + * nm_setting_ethtool_get_ring: + * @setting: the #NMSettingEthtool + * @optname: option name of the ring setting to get + * @out_value (out) (allow-none): value of the ring setting + * + * Gets the value of ring setting. + * + * Note that @optname must be a valid name for a setting, according to + * nm_ethtool_optname_is_ring(). + * + * + * Returns: %TRUE and places the ring setting value in @out_value or %FALSE if unset. + * + * Since: 1.26 + */ +gboolean +nm_setting_ethtool_get_ring (NMSettingEthtool *setting, + const char *optname, + guint32 *out_value) +{ + g_return_val_if_fail (NM_IS_SETTING_ETHTOOL (setting), FALSE); + g_return_val_if_fail (nm_ethtool_optname_is_ring (optname), FALSE); + + return nm_setting_gendata_get_uint32 (NM_SETTING (setting), + optname, + out_value); +} + +/** + * nm_setting_ethtool_set_ring: + * @setting: the #NMSettingEthtool + * @optname: option name of the ring setting + * @value: the new value to set. + * + * Sets a ring setting. + * + * Note that @optname must be a valid name for a ring setting, according to + * nm_ethtool_optname_is_ring(). + * + * Since: 1.26 + */ +void +nm_setting_ethtool_set_ring (NMSettingEthtool *setting, + const char *optname, + guint32 value) +{ + NMEthtoolID ethtool_id; g_return_if_fail (NM_IS_SETTING_ETHTOOL (setting)); - hash = _nm_setting_gendata_hash (NM_SETTING (setting), FALSE); - if (!hash) - return; + ethtool_id = nm_ethtool_id_get_by_name (optname); - 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; - } - } + g_return_if_fail (nm_ethtool_id_is_ring (ethtool_id)); - if (changed) + nm_setting_gendata_set_uint32 (NM_SETTING (setting), + optname, + value); + _notify_attributes (setting); +} + +/** + * nm_setting_ethtool_clear_ring: + * @setting: the #NMSettingEthtool + * @optname: option name of the ring setting + * + * Clear a ring setting + * + * Since: 1.26 + */ +void +nm_setting_ethtool_clear_ring (NMSettingEthtool *setting, + const char *optname) +{ + g_return_if_fail (NM_IS_SETTING_ETHTOOL (setting)); + g_return_if_fail (nm_str_not_empty (optname)); + + if (nm_setting_gendata_clear (NM_SETTING (setting), optname)) + _notify_attributes (setting); +} + +/** + * nm_setting_ethtool_clear_ring_all: + * @setting: the #NMSettingEthtool + * + * Clears all ring settings + * + * Since: 1.26 + */ +void +nm_setting_ethtool_clear_ring_all (NMSettingEthtool *setting) +{ + g_return_if_fail (NM_IS_SETTING_ETHTOOL (setting)); + + if (nm_setting_gendata_clear_all (NM_SETTING (setting), + &nm_ethtool_optname_is_ring)) _notify_attributes (setting); } @@ -446,12 +512,13 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) g_prefix_error (error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname); return FALSE; } - } else if (nm_ethtool_optname_is_coalesce (optname)) { + } else if ( nm_ethtool_optname_is_coalesce (optname) + || nm_ethtool_optname_is_ring (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")); + _("setting has invalid variant type")); g_prefix_error (error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname); return FALSE; } @@ -476,10 +543,13 @@ get_variant_type (const NMSettInfoSetting *sett_info, const char *name, GError **error) { - if (nm_ethtool_optname_is_feature (name)) + NMEthtoolID ethtool_id = nm_ethtool_id_get_by_name (name); + + if (nm_ethtool_id_is_feature (ethtool_id)) return G_VARIANT_TYPE_BOOLEAN; - if (nm_ethtool_optname_is_coalesce (name)) + if ( nm_ethtool_id_is_coalesce (ethtool_id) + || nm_ethtool_id_is_ring (ethtool_id)) return G_VARIANT_TYPE_UINT32; g_set_error (error, diff --git a/libnm-core/nm-setting-ethtool.h b/libnm-core/nm-setting-ethtool.h index a62a33159c..795b3a38dc 100644 --- a/libnm-core/nm-setting-ethtool.h +++ b/libnm-core/nm-setting-ethtool.h @@ -92,12 +92,20 @@ G_BEGIN_DECLS #define NM_ETHTOOL_OPTNAME_COALESCE_TX_USECS_IRQ "coalesce-tx-usecs-irq" #define NM_ETHTOOL_OPTNAME_COALESCE_TX_USECS_LOW "coalesce-tx-usecs-low" +#define NM_ETHTOOL_OPTNAME_RING_RX "ring-rx" +#define NM_ETHTOOL_OPTNAME_RING_RX_JUMBO "ring-rx-jumbo" +#define NM_ETHTOOL_OPTNAME_RING_RX_MINI "ring-rx-mini" +#define NM_ETHTOOL_OPTNAME_RING_TX "ring-tx" + 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); +NM_AVAILABLE_IN_1_26 +gboolean nm_ethtool_optname_is_ring (const char *optname); + /*****************************************************************************/ #define NM_TYPE_SETTING_ETHTOOL (nm_setting_ethtool_get_type ()) @@ -152,6 +160,23 @@ void nm_setting_ethtool_clear_coalesce (NMSettingEthtool *setting, NM_AVAILABLE_IN_1_26 void nm_setting_ethtool_clear_coalesce_all (NMSettingEthtool *setting); +NM_AVAILABLE_IN_1_26 +gboolean nm_setting_ethtool_get_ring (NMSettingEthtool *setting, + const char *optname, + guint32 *out_value); + +NM_AVAILABLE_IN_1_26 +void nm_setting_ethtool_set_ring (NMSettingEthtool *setting, + const char *optname, + guint32 value); + +NM_AVAILABLE_IN_1_26 +void nm_setting_ethtool_clear_ring (NMSettingEthtool *setting, + const char *optname); + +NM_AVAILABLE_IN_1_26 +void nm_setting_ethtool_clear_ring_all (NMSettingEthtool *setting); + G_END_DECLS #endif /* __NM_SETTING_ETHTOOL_H__ */ diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index 5a16d5cbe7..50a277d8b8 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -2616,6 +2616,81 @@ _nm_setting_gendata_reset_from_hash (NMSetting *setting, return TRUE; } +gboolean +nm_setting_gendata_get_uint32 (NMSetting *setting, + const char *optname, + guint32 *out_value) +{ + GVariant *v; + + nm_assert (NM_IS_SETTING (setting)); + nm_assert (nm_str_not_empty (optname)); + + v = nm_setting_gendata_get (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; +} + +void +nm_setting_gendata_set_uint32 (NMSetting *setting, + const char *optname, + guint32 value) +{ + nm_assert (NM_IS_SETTING (setting)); + nm_assert (nm_str_not_empty (optname)); + + g_hash_table_insert (_nm_setting_gendata_hash (setting, TRUE), + g_strdup (optname), + g_variant_ref_sink (g_variant_new_uint32 (value))); +} + +gboolean +nm_setting_gendata_clear (NMSetting *setting, + const char *optname) +{ + GHashTable *ht; + + nm_assert (NM_IS_SETTING (setting)); + nm_assert (nm_str_not_empty (optname)); + + ht = _nm_setting_gendata_hash (setting, FALSE); + if (!ht) + return FALSE; + + return g_hash_table_remove (ht, optname); +} + +gboolean +nm_setting_gendata_clear_all (NMSetting *setting, + nm_setting_gendata_filter_fcn filter) +{ + GHashTable *ht; + const char *name; + GHashTableIter iter; + gboolean changed = FALSE; + + nm_assert (NM_IS_SETTING (setting)); + + ht = _nm_setting_gendata_hash (setting, FALSE); + if (!ht) + return FALSE; + + g_hash_table_iter_init (&iter, ht); + while (g_hash_table_iter_next (&iter, (gpointer *) &name, NULL)) { + if (!filter || filter (name)) { + g_hash_table_iter_remove (&iter); + changed = TRUE; + } + } + + return changed; +} + /*****************************************************************************/ static void diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index 32eac0236b..d861fbcb33 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -1499,7 +1499,7 @@ test_team_setting (void) /*****************************************************************************/ static void -test_ethtool_1 (void) +test_ethtool_features (void) { gs_unref_object NMConnection *con = NULL; gs_unref_object NMConnection *con2 = NULL; @@ -1655,6 +1655,90 @@ test_ethtool_coalesce (void) g_assert_false (nm_setting_ethtool_get_coalesce (s_ethtool, NM_ETHTOOL_OPTNAME_COALESCE_TX_USECS, NULL)); } +static void +test_ethtool_ring (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-ring", + 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_ring (s_ethtool, + NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, + 4); + + g_assert_true (nm_setting_ethtool_get_ring (s_ethtool, NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, &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_ring (s_ethtool2, NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, &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_ring (s_ethtool3, NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, &out_value)); + g_assert_cmpuint (out_value, ==, 4); + + + nm_setting_ethtool_clear_ring (s_ethtool, NM_ETHTOOL_OPTNAME_RING_RX_JUMBO); + g_assert_false (nm_setting_ethtool_get_ring (s_ethtool, NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, NULL)); + + nm_setting_ethtool_set_ring (s_ethtool, + NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, + 8); + + g_assert_true (nm_setting_ethtool_get_ring (s_ethtool, NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, &out_value)); + g_assert_cmpuint (out_value, ==, 8); + + nm_setting_ethtool_clear_ring_all (s_ethtool); + g_assert_false (nm_setting_ethtool_get_ring (s_ethtool, NM_ETHTOOL_OPTNAME_RING_RX_JUMBO, NULL)); + g_assert_false (nm_setting_ethtool_get_ring (s_ethtool, NM_ETHTOOL_OPTNAME_RING_RX, NULL)); + g_assert_false (nm_setting_ethtool_get_ring (s_ethtool, NM_ETHTOOL_OPTNAME_RING_TX, NULL)); +} + /*****************************************************************************/ static void @@ -3854,8 +3938,9 @@ main (int argc, char **argv) g_test_add_func ("/libnm/settings/dcb/priorities", test_dcb_priorities_valid); 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/features", test_ethtool_features); g_test_add_func ("/libnm/settings/ethtool/coalesce", test_ethtool_coalesce); + g_test_add_func ("/libnm/settings/ethtool/ring", test_ethtool_ring); g_test_add_func ("/libnm/settings/sriov/vf", test_sriov_vf); g_test_add_func ("/libnm/settings/sriov/vf-dup", test_sriov_vf_dup); diff --git a/libnm/libnm.ver b/libnm/libnm.ver index e8203f5b6e..effa41d162 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1699,6 +1699,7 @@ global: libnm_1_26_0 { global: nm_ethtool_optname_is_coalesce; + nm_ethtool_optname_is_ring; nm_setting_bridge_get_multicast_hash_max; nm_setting_bridge_get_multicast_last_member_count; nm_setting_bridge_get_multicast_last_member_interval; @@ -1711,8 +1712,12 @@ global: nm_setting_connection_get_mud_url; nm_setting_ethtool_clear_coalesce; nm_setting_ethtool_clear_coalesce_all; + nm_setting_ethtool_clear_ring; + nm_setting_ethtool_clear_ring_all; nm_setting_ethtool_get_coalesce; + nm_setting_ethtool_get_ring; nm_setting_ethtool_set_coalesce; + nm_setting_ethtool_set_ring; nm_setting_match_add_driver; nm_setting_match_add_kernel_command_line; nm_setting_match_clear_drivers; diff --git a/shared/nm-libnm-core-intern/nm-ethtool-utils.c b/shared/nm-libnm-core-intern/nm-ethtool-utils.c index 3842e3122e..3e3c28d36a 100644 --- a/shared/nm-libnm-core-intern/nm-ethtool-utils.c +++ b/shared/nm-libnm-core-intern/nm-ethtool-utils.c @@ -93,6 +93,10 @@ const NMEthtoolData *const nm_ethtool_data[_NM_ETHTOOL_ID_NUM + 1] = { ETHT_DATA (FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION), ETHT_DATA (FEATURE_TX_UDP_TNL_SEGMENTATION), ETHT_DATA (FEATURE_TX_VLAN_STAG_HW_INSERT), + ETHT_DATA (RING_RX), + ETHT_DATA (RING_RX_JUMBO), + ETHT_DATA (RING_RX_MINI), + ETHT_DATA (RING_TX), [_NM_ETHTOOL_ID_NUM] = NULL, }; @@ -172,6 +176,10 @@ 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_RING_RX, + NM_ETHTOOL_ID_RING_RX_JUMBO, + NM_ETHTOOL_ID_RING_RX_MINI, + NM_ETHTOOL_ID_RING_TX, }; /*****************************************************************************/ @@ -253,3 +261,16 @@ nm_ethtool_data_get_by_optname (const char *optname) NULL); return (idx < 0) ? NULL : nm_ethtool_data[_by_name[idx]]; } + +NMEthtoolType +nm_ethtool_id_to_type (NMEthtoolID id) +{ + if (nm_ethtool_id_is_coalesce (id)) + return NM_ETHTOOL_TYPE_COALESCE; + if (nm_ethtool_id_is_feature (id)) + return NM_ETHTOOL_TYPE_FEATURE; + if (nm_ethtool_id_is_ring (id)) + return NM_ETHTOOL_TYPE_RING; + + return NM_ETHTOOL_TYPE_UNKNOWN; +} diff --git a/shared/nm-libnm-core-intern/nm-ethtool-utils.h b/shared/nm-libnm-core-intern/nm-ethtool-utils.h index 0505328364..0df3d3d00c 100644 --- a/shared/nm-libnm-core-intern/nm-ethtool-utils.h +++ b/shared/nm-libnm-core-intern/nm-ethtool-utils.h @@ -93,13 +93,28 @@ typedef enum { 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_LAST = _NM_ETHTOOL_ID_FEATURE_LAST, + _NM_ETHTOOL_ID_RING_FIRST = _NM_ETHTOOL_ID_FEATURE_LAST + 1, + NM_ETHTOOL_ID_RING_RX = _NM_ETHTOOL_ID_RING_FIRST, + NM_ETHTOOL_ID_RING_RX_JUMBO, + NM_ETHTOOL_ID_RING_RX_MINI, + NM_ETHTOOL_ID_RING_TX, + _NM_ETHTOOL_ID_RING_LAST = NM_ETHTOOL_ID_RING_TX, + + _NM_ETHTOOL_ID_LAST = _NM_ETHTOOL_ID_RING_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_RING_NUM = (_NM_ETHTOOL_ID_RING_LAST - _NM_ETHTOOL_ID_RING_FIRST + 1), _NM_ETHTOOL_ID_NUM = (_NM_ETHTOOL_ID_LAST - _NM_ETHTOOL_ID_FIRST + 1), } NMEthtoolID; +typedef enum { + NM_ETHTOOL_TYPE_UNKNOWN, + NM_ETHTOOL_TYPE_COALESCE, + NM_ETHTOOL_TYPE_FEATURE, + NM_ETHTOOL_TYPE_RING, +} NMEthtoolType; + typedef struct { const char *optname; NMEthtoolID id; @@ -109,6 +124,8 @@ extern const NMEthtoolData *const nm_ethtool_data[_NM_ETHTOOL_ID_NUM + 1]; const NMEthtoolData *nm_ethtool_data_get_by_optname (const char *optname); +NMEthtoolType nm_ethtool_id_to_type (NMEthtoolID id); + /****************************************************************************/ static inline NMEthtoolID @@ -132,6 +149,12 @@ nm_ethtool_id_is_coalesce (NMEthtoolID id) return id >= _NM_ETHTOOL_ID_COALESCE_FIRST && id <= _NM_ETHTOOL_ID_COALESCE_LAST; } +static inline gboolean +nm_ethtool_id_is_ring (NMEthtoolID id) +{ + return id >= _NM_ETHTOOL_ID_RING_FIRST && id <= _NM_ETHTOOL_ID_RING_LAST; +} + /****************************************************************************/ #endif /* __NM_ETHTOOL_UTILS_H__ */ diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 66eea16ce4..418641358d 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -32,6 +32,7 @@ #include "NetworkManagerUtils.h" #include "nm-manager.h" #include "platform/nm-platform.h" +#include "platform/nm-platform-utils.h" #include "platform/nmp-object.h" #include "platform/nmp-rules-manager.h" #include "ndisc/nm-ndisc.h" @@ -185,7 +186,8 @@ typedef struct { int ifindex; NMEthtoolFeatureStates *features; NMTernary requested[_NM_ETHTOOL_ID_FEATURE_NUM]; - NMEthtoolCoalesceStates *coalesce; + NMEthtoolCoalesceState *coalesce; + NMEthtoolRingState *ring; } EthtoolState; /*****************************************************************************/ @@ -868,7 +870,7 @@ static gboolean _ethtool_init_coalesce (NMDevice *self, NMPlatform *platform, NMSettingEthtool *s_ethtool, - NMEthtoolCoalesceStates *coalesce) + NMEthtoolCoalesceState *coalesce) { GHashTable *hash; GHashTableIter iter; @@ -889,6 +891,8 @@ _ethtool_init_coalesce (NMDevice *self, 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_ethtool_optname_is_coalesce (name)) + continue; if (!nm_platform_ethtool_init_coalesce (platform, coalesce, @@ -901,28 +905,27 @@ _ethtool_init_coalesce (NMDevice *self, } - return (!!n_coalesce_set); + return !!n_coalesce_set; } - - static void _ethtool_coalesce_reset (NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state) { - gs_free NMEthtoolCoalesceStates *coalesce = NULL; + gs_free NMEthtoolCoalesceState *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 (!coalesce) + return; if (!nm_platform_ethtool_set_coalesce (platform, ethtool_state->ifindex, - coalesce, - FALSE)) + coalesce)) _LOGW (LOGD_DEVICE, "ethtool: failure resetting one or more coalesce settings"); else _LOGD (LOGD_DEVICE, "ethtool: coalesce settings successfully reset"); @@ -934,37 +937,147 @@ _ethtool_coalesce_set (NMDevice *self, EthtoolState *ethtool_state, NMSettingEthtool *s_ethtool) { - gs_free NMEthtoolCoalesceStates *coalesce = NULL; + NMEthtoolCoalesceState coalesce_old; + NMEthtoolCoalesceState coalesce_new; 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) { + if (!nm_platform_ethtool_get_link_coalesce (platform, + ethtool_state->ifindex, + &coalesce_old)) { _LOGW (LOGD_DEVICE, "ethtool: failure getting coalesce settings (cannot read)"); return; } + coalesce_new = coalesce_old; + if (!_ethtool_init_coalesce (self, platform, s_ethtool, - coalesce)) + &coalesce_new)) return; + ethtool_state->coalesce = nm_memdup (&coalesce_old, sizeof (coalesce_old)); + if (!nm_platform_ethtool_set_coalesce (platform, ethtool_state->ifindex, - coalesce, - TRUE)) { + &coalesce_new)) { _LOGW (LOGD_DEVICE, "ethtool: failure setting coalesce settings"); return; } + _LOGD (LOGD_DEVICE, "ethtool: coalesce settings successfully set"); +} + +static gboolean +_ethtool_init_ring (NMDevice *self, + NMPlatform *platform, + NMSettingEthtool *s_ethtool, + NMEthtoolRingState *ring) +{ + GHashTable *hash; + GHashTableIter iter; + const char *name; + GVariant *variant; + gsize n_ring_set = 0; + + nm_assert (self); + nm_assert (platform); + nm_assert (ring); + 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_ethtool_optname_is_ring (name)) + continue; + + if (!nm_platform_ethtool_init_ring (platform, + ring, + name, + g_variant_get_uint32(variant))) { + _LOGW (LOGD_DEVICE, "ethtool: invalid ring setting %s", name); + return FALSE; + } + ++n_ring_set; + + } + + return !!n_ring_set; +} + + + +static void +_ethtool_ring_reset (NMDevice *self, + NMPlatform *platform, + EthtoolState *ethtool_state) +{ + gs_free NMEthtoolRingState *ring = NULL; + + nm_assert (NM_IS_DEVICE (self)); + nm_assert (NM_IS_PLATFORM (platform)); + nm_assert (ethtool_state); + + ring = g_steal_pointer (ðtool_state->ring); + if (!ring) + return; + + if (!nm_platform_ethtool_set_ring (platform, + ethtool_state->ifindex, + ring)) + _LOGW (LOGD_DEVICE, "ethtool: failure resetting one or more ring settings"); + else + _LOGD (LOGD_DEVICE, "ethtool: ring settings successfully reset"); +} + +static void +_ethtool_ring_set (NMDevice *self, + NMPlatform *platform, + EthtoolState *ethtool_state, + NMSettingEthtool *s_ethtool) +{ + NMEthtoolRingState ring_old; + NMEthtoolRingState ring_new; + + nm_assert (ethtool_state); + nm_assert (NM_IS_DEVICE (self)); + nm_assert (NM_IS_PLATFORM (platform)); + nm_assert (NM_IS_SETTING_ETHTOOL (s_ethtool)); + + if (!nm_platform_ethtool_get_link_ring (platform, + ethtool_state->ifindex, + &ring_old)) { + _LOGW (LOGD_DEVICE, "ethtool: failure getting ring settings (cannot read)"); + return; + } + + ring_new = ring_old; + + if (!_ethtool_init_ring (self, + platform, + s_ethtool, + &ring_new)) + return; + + ethtool_state->ring = nm_memdup (&ring_old, sizeof (ring_old)); + + if (!nm_platform_ethtool_set_ring (platform, + ethtool_state->ifindex, + &ring_new)) { + _LOGW (LOGD_DEVICE, "ethtool: failure setting ring settings"); + return; + } - ethtool_state->coalesce = g_steal_pointer (&coalesce); + _LOGD (LOGD_DEVICE, "ethtool: ring settings successfully set"); } static void @@ -981,6 +1094,8 @@ _ethtool_state_reset (NMDevice *self) _ethtool_features_reset (self, platform, ethtool_state); if (ethtool_state->coalesce) _ethtool_coalesce_reset (self, platform, ethtool_state); + if (ethtool_state->ring) + _ethtool_ring_reset (self, platform, ethtool_state); } @@ -1021,9 +1136,14 @@ _ethtool_state_set (NMDevice *self) platform, ethtool_state, s_ethtool); + _ethtool_ring_set (self, + platform, + ethtool_state, + s_ethtool); if ( ethtool_state->features - || ethtool_state->coalesce) + || ethtool_state->coalesce + || ethtool_state->ring) priv->ethtool_state = g_steal_pointer (ðtool_state); } diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index c47d8476fc..3b799e2f11 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -269,6 +269,7 @@ NM_UTILS_ENUM2STR_DEFINE (_ethtool_cmd_to_string, guint32, NM_UTILS_ENUM2STR (ETHTOOL_GFEATURES, "ETHTOOL_GFEATURES"), NM_UTILS_ENUM2STR (ETHTOOL_GLINK, "ETHTOOL_GLINK"), NM_UTILS_ENUM2STR (ETHTOOL_GPERMADDR, "ETHTOOL_GPERMADDR"), + NM_UTILS_ENUM2STR (ETHTOOL_GRINGPARAM, "ETHTOOL_GRINGPARAM"), NM_UTILS_ENUM2STR (ETHTOOL_GSET, "ETHTOOL_GSET"), NM_UTILS_ENUM2STR (ETHTOOL_GSSET_INFO, "ETHTOOL_GSSET_INFO"), NM_UTILS_ENUM2STR (ETHTOOL_GSTATS, "ETHTOOL_GSTATS"), @@ -276,6 +277,7 @@ NM_UTILS_ENUM2STR_DEFINE (_ethtool_cmd_to_string, guint32, 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_SRINGPARAM, "ETHTOOL_SRINGPARAM"), NM_UTILS_ENUM2STR (ETHTOOL_SSET, "ETHTOOL_SSET"), NM_UTILS_ENUM2STR (ETHTOOL_SWOL, "ETHTOOL_SWOL"), ); @@ -845,31 +847,26 @@ ethtool_get_coalesce (SocketHandle *shandle, return TRUE; } - -NMEthtoolCoalesceStates * -nmp_utils_ethtool_get_coalesce (int ifindex) +gboolean +nmp_utils_ethtool_get_coalesce (int ifindex, + NMEthtoolCoalesceState *coalesce) { - 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); + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (coalesce, FALSE); - if (!ethtool_get_coalesce (&shandle, &coalesce->old_state)) { + if (!ethtool_get_coalesce (&shandle, coalesce)) { nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure getting coalesce settings", ifindex, "get-coalesce"); - return NULL; + return FALSE; } - /* 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); + return TRUE; } static gboolean @@ -916,32 +913,112 @@ ethtool_set_coalesce (SocketHandle *shandle, gboolean nmp_utils_ethtool_set_coalesce (int ifindex, - const NMEthtoolCoalesceStates *coalesce, - gboolean do_set) + const NMEthtoolCoalesceState *coalesce) { - 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 (!ethtool_set_coalesce (&shandle, coalesce)) { + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure setting coalesce settings", + ifindex, + "set-coalesce"); + return FALSE; + } + + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: set kernel coalesce settings", + ifindex, + "set-coalesce"); + return TRUE; +} + +static gboolean +ethtool_get_ring (SocketHandle *shandle, + NMEthtoolRingState *ring) +{ + struct ethtool_ringparam eth_data; + + eth_data.cmd = ETHTOOL_GRINGPARAM; + + if (_ethtool_call_handle (shandle, + ð_data, + sizeof (struct ethtool_ringparam)) != 0) + return FALSE; + + ring->rx_pending = eth_data.rx_pending; + ring->rx_jumbo_pending = eth_data.rx_jumbo_pending; + ring->rx_mini_pending = eth_data.rx_mini_pending; + ring->tx_pending = eth_data.tx_pending; + + return TRUE; +} + +gboolean +nmp_utils_ethtool_get_ring (int ifindex, + NMEthtoolRingState *ring) +{ + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT (ifindex); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (ring, FALSE); + + if (!ethtool_get_ring (&shandle, ring)) { + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure getting ring settings", + ifindex, + "get-ring"); + return FALSE; + } + + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: retrieved kernel ring settings", + ifindex, + "get-ring"); + return TRUE; +} + +static gboolean +ethtool_set_ring (SocketHandle *shandle, + const NMEthtoolRingState *ring) +{ + gboolean success; + struct ethtool_ringparam eth_data; + + g_return_val_if_fail (shandle, FALSE); + g_return_val_if_fail (ring, FALSE); + + eth_data = (struct ethtool_ringparam) { + .cmd = ETHTOOL_SRINGPARAM, + .rx_pending = ring->rx_pending, + .rx_jumbo_pending = ring->rx_jumbo_pending, + .rx_mini_pending = ring->rx_mini_pending, + .tx_pending = ring->tx_pending, + }; + + success = (_ethtool_call_handle (shandle, + ð_data, + sizeof (struct ethtool_ringparam)) == 0); + return success; +} + +gboolean +nmp_utils_ethtool_set_ring (int ifindex, + const NMEthtoolRingState *ring) +{ + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT (ifindex); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (ring, FALSE); - if (!success) { - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure %s coalesce settings", + if (!ethtool_set_ring (&shandle, ring)) { + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure setting ring settings", ifindex, - "set-coalesce", - do_set ? "setting" : "resetting"); + "set-ring"); return FALSE; } - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: %s kernel coalesce settings", + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: set kernel ring settings", ifindex, - "set-coalesce", - do_set ? "set" : "reset"); + "set-ring"); return TRUE; } diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h index 56fdb5e4d3..242b97f168 100644 --- a/src/platform/nm-platform-utils.h +++ b/src/platform/nm-platform-utils.h @@ -92,7 +92,7 @@ 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 { +struct _NMEthtoolCoalesceState { guint32 rx_coalesce_usecs; guint32 rx_max_coalesced_frames; guint32 rx_coalesce_usecs_irq; @@ -115,18 +115,26 @@ typedef struct { 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_get_coalesce (int ifindex, + NMEthtoolCoalesceState *coalesce); gboolean nmp_utils_ethtool_set_coalesce (int ifindex, - const NMEthtoolCoalesceStates *coalesce, - gboolean do_set); + const NMEthtoolCoalesceState *coalesce); + +struct _NMEthtoolRingState { + guint32 rx_pending; + guint32 rx_mini_pending; + guint32 rx_jumbo_pending; + guint32 tx_pending; +}; + +gboolean nmp_utils_ethtool_get_ring (int ifindex, + NMEthtoolRingState *ring); + +gboolean nmp_utils_ethtool_set_ring (int ifindex, + const NMEthtoolRingState *ring); /*****************************************************************************/ diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index c17cd305dc..596f08542e 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -3214,100 +3214,100 @@ 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) +gboolean +nm_platform_ethtool_get_link_coalesce (NMPlatform *self, + int ifindex, + NMEthtoolCoalesceState *coalesce) { - _CHECK_SELF_NETNS (self, klass, netns, NULL); + _CHECK_SELF_NETNS (self, klass, netns, FALSE); - g_return_val_if_fail (ifindex > 0, NULL); + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (coalesce, FALSE); - return nmp_utils_ethtool_get_coalesce (ifindex); + return nmp_utils_ethtool_get_coalesce (ifindex, coalesce); } gboolean nm_platform_ethtool_init_coalesce (NMPlatform *self, - NMEthtoolCoalesceStates *coalesce, + NMEthtoolCoalesceState *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; + g_return_val_if_fail (nm_ethtool_id_is_coalesce (ethtool_id), FALSE); switch (ethtool_id) { case NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX: - state->use_adaptive_rx_coalesce = value; + coalesce->use_adaptive_rx_coalesce = value; break; case NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX: - state->use_adaptive_tx_coalesce = value; + coalesce->use_adaptive_tx_coalesce = value; break; case NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH: - state->pkt_rate_high = value; + coalesce->pkt_rate_high = value; break; case NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW: - state->pkt_rate_low = value; + coalesce->pkt_rate_low = value; break; case NM_ETHTOOL_ID_COALESCE_RX_FRAMES: - state->rx_max_coalesced_frames = value; + coalesce->rx_max_coalesced_frames = value; break; case NM_ETHTOOL_ID_COALESCE_RX_FRAMES_HIGH: - state->rx_max_coalesced_frames_high = value; + coalesce->rx_max_coalesced_frames_high = value; break; case NM_ETHTOOL_ID_COALESCE_RX_FRAMES_IRQ: - state->rx_max_coalesced_frames_irq = value; + coalesce->rx_max_coalesced_frames_irq = value; break; case NM_ETHTOOL_ID_COALESCE_RX_FRAMES_LOW: - state->rx_max_coalesced_frames_low = value; + coalesce->rx_max_coalesced_frames_low = value; break; case NM_ETHTOOL_ID_COALESCE_RX_USECS: - state->rx_coalesce_usecs = value; + coalesce->rx_coalesce_usecs = value; break; case NM_ETHTOOL_ID_COALESCE_RX_USECS_HIGH: - state->rx_coalesce_usecs_high = value; + coalesce->rx_coalesce_usecs_high = value; break; case NM_ETHTOOL_ID_COALESCE_RX_USECS_IRQ: - state->rx_coalesce_usecs_irq = value; + coalesce->rx_coalesce_usecs_irq = value; break; case NM_ETHTOOL_ID_COALESCE_RX_USECS_LOW: - state->rx_coalesce_usecs_low = value; + coalesce->rx_coalesce_usecs_low = value; break; case NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL: - state->rate_sample_interval = value; + coalesce->rate_sample_interval = value; break; case NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS: - state->stats_block_coalesce_usecs = value; + coalesce->stats_block_coalesce_usecs = value; break; case NM_ETHTOOL_ID_COALESCE_TX_FRAMES: - state->tx_max_coalesced_frames = value; + coalesce->tx_max_coalesced_frames = value; break; case NM_ETHTOOL_ID_COALESCE_TX_FRAMES_HIGH: - state->tx_max_coalesced_frames_high = value; + coalesce->tx_max_coalesced_frames_high = value; break; case NM_ETHTOOL_ID_COALESCE_TX_FRAMES_IRQ: - state->tx_max_coalesced_frames_irq = value; + coalesce->tx_max_coalesced_frames_irq = value; break; case NM_ETHTOOL_ID_COALESCE_TX_FRAMES_LOW: - state->tx_max_coalesced_frames_low = value; + coalesce->tx_max_coalesced_frames_low = value; break; case NM_ETHTOOL_ID_COALESCE_TX_USECS: - state->tx_coalesce_usecs = value; + coalesce->tx_coalesce_usecs = value; break; case NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH: - state->tx_coalesce_usecs_high = value; + coalesce->tx_coalesce_usecs_high = value; break; case NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ: - state->tx_coalesce_usecs_irq = value; + coalesce->tx_coalesce_usecs_irq = value; break; case NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW: - state->tx_coalesce_usecs_low = value; + coalesce->tx_coalesce_usecs_low = value; break; default: g_return_val_if_reached (FALSE); @@ -3319,14 +3319,73 @@ nm_platform_ethtool_init_coalesce (NMPlatform *self, gboolean nm_platform_ethtool_set_coalesce (NMPlatform *self, int ifindex, - const NMEthtoolCoalesceStates *coalesce, - gboolean do_set) + const NMEthtoolCoalesceState *coalesce) +{ + _CHECK_SELF_NETNS (self, klass, netns, FALSE); + + g_return_val_if_fail (ifindex > 0, FALSE); + + return nmp_utils_ethtool_set_coalesce (ifindex, coalesce); +} + +gboolean +nm_platform_ethtool_get_link_ring (NMPlatform *self, + int ifindex, + NMEthtoolRingState *ring) +{ + _CHECK_SELF_NETNS (self, klass, netns, FALSE); + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (ring, FALSE); + + return nmp_utils_ethtool_get_ring (ifindex, ring); +} + +gboolean +nm_platform_ethtool_init_ring (NMPlatform *self, + NMEthtoolRingState *ring, + const char *option_name, + guint32 value) +{ + NMEthtoolID ethtool_id; + + g_return_val_if_fail (ring, FALSE); + g_return_val_if_fail (option_name, FALSE); + + ethtool_id = nm_ethtool_id_get_by_name (option_name); + + g_return_val_if_fail (nm_ethtool_id_is_ring (ethtool_id), FALSE); + + switch (ethtool_id) { + case NM_ETHTOOL_ID_RING_RX: + ring->rx_pending = value; + break; + case NM_ETHTOOL_ID_RING_RX_JUMBO: + ring->rx_jumbo_pending = value; + break; + case NM_ETHTOOL_ID_RING_RX_MINI: + ring->rx_mini_pending = value; + break; + case NM_ETHTOOL_ID_RING_TX: + ring->tx_pending = value; + break; + default: + g_return_val_if_reached (FALSE); + } + + return TRUE; +} + +gboolean +nm_platform_ethtool_set_ring (NMPlatform *self, + int ifindex, + const NMEthtoolRingState *ring) { _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); + return nmp_utils_ethtool_set_ring (ifindex, ring); } /*****************************************************************************/ diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 260b5356ff..8957de429c 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -1954,20 +1954,35 @@ 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; +typedef struct _NMEthtoolCoalesceState NMEthtoolCoalesceState; -NMEthtoolCoalesceStates *nm_platform_ethtool_get_link_coalesce (NMPlatform *self, - int ifindex); +gboolean nm_platform_ethtool_get_link_coalesce (NMPlatform *self, + int ifindex, + NMEthtoolCoalesceState *coalesce); gboolean nm_platform_ethtool_init_coalesce (NMPlatform *self, - NMEthtoolCoalesceStates *coalesce, + NMEthtoolCoalesceState *coalesce, const char *option_name, guint32 value); gboolean nm_platform_ethtool_set_coalesce (NMPlatform *self, int ifindex, - const NMEthtoolCoalesceStates *coalesce, - gboolean do_set); + const NMEthtoolCoalesceState *coalesce); + +typedef struct _NMEthtoolRingState NMEthtoolRingState; + +gboolean nm_platform_ethtool_get_link_ring (NMPlatform *self, + int ifindex, + NMEthtoolRingState *ring); + +gboolean nm_platform_ethtool_init_ring (NMPlatform *self, + NMEthtoolRingState *ring, + const char *option_name, + guint32 value); + +gboolean nm_platform_ethtool_set_ring (NMPlatform *self, + int ifindex, + const NMEthtoolRingState *ring); const char * nm_platform_link_duplex_type_to_string (NMPlatformLinkDuplexType duplex); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 11754e70fa..b0befd88da 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -4248,6 +4248,130 @@ wireless_connection_from_ifcfg (const char *file, return connection; } +typedef struct { + const char *optname; + union { + guint32 u32; + NMTernary nmternary; + } v; + gboolean has_value; +} NMEthtoolIfcfgOption; + +/* returns an 'iterator' to words + * pointing to the next unprocessed option or NULL + * in case of failure */ +static const char ** +_next_ethtool_options_nmternary (const char **words, + NMEthtoolType ethtool_type, + NMEthtoolIfcfgOption *out_value) +{ + const char *opt; + const char *opt_val; + const NMEthtoolData *d = NULL; + NMTernary onoff = NM_TERNARY_DEFAULT; + + nm_assert (out_value); + + out_value->has_value = FALSE; + out_value->optname = NULL; + + if ( !words + || !words[0] + || !words[1]) + return NULL; + + opt = *words; + opt_val = *(++words); + + if (nm_streq0 (opt_val, "on")) + onoff = NM_TERNARY_TRUE; + else if (nm_streq0 (opt_val, "off")) + onoff = NM_TERNARY_FALSE; + + d = nms_ifcfg_rh_utils_get_ethtool_by_name (opt, ethtool_type); + if (!d) { + if (onoff != NM_TERNARY_DEFAULT) { + /* the next value is just the on/off argument. Skip it too. */ + ++words; + } + + /* silently ignore unsupported offloading features. */ + return words; + } + + if (onoff == NM_TERNARY_DEFAULT) { + PARSE_WARNING ("Expects on/off argument for feature '%s'", opt); + return words; + } + + out_value->has_value = TRUE; + out_value->optname = d->optname; + out_value->v.nmternary = onoff; + + return ++words; +} + +/* returns an 'iterator' to words + * pointing to the next unprocessed option or NULL + * in case of failure */ +static const char ** +_next_ethtool_options_uint32 (const char **words, + NMEthtoolType ethtool_type, + NMEthtoolIfcfgOption *out_value) +{ + gint64 i64; + const char *opt; + const char *opt_val; + const NMEthtoolData *d = NULL; + + nm_assert (out_value); + + out_value->has_value = FALSE; + out_value->optname = NULL; + + if ( !words + || !words[0] + || !words[1]) + return NULL; + + opt = *words; + opt_val = *(++words); + + i64 = _nm_utils_ascii_str_to_int64 (opt_val, 10, 0, G_MAXUINT32, -1); + + d = nms_ifcfg_rh_utils_get_ethtool_by_name (opt, ethtool_type); + if (!d) { + if (i64 != -1) { + /* the next value is just the on/off argument. Skip it too. */ + ++words; + } + + /* silently ignore unsupported offloading features. */ + return words; + } + + out_value->has_value = TRUE; + out_value->optname = d->optname; + out_value->v.u32 = (guint32) i64; + + return ++words; +} + +static +NM_UTILS_STRING_TABLE_LOOKUP_DEFINE ( + _get_ethtool_type_by_name, + NMEthtoolType, + { nm_assert (name); }, + { return NM_ETHTOOL_TYPE_UNKNOWN; }, + { "--coalesce", NM_ETHTOOL_TYPE_COALESCE }, + { "--features", NM_ETHTOOL_TYPE_FEATURE }, + { "--offload", NM_ETHTOOL_TYPE_FEATURE }, + { "--set-ring", NM_ETHTOOL_TYPE_RING }, + { "-C", NM_ETHTOOL_TYPE_COALESCE }, + { "-G", NM_ETHTOOL_TYPE_RING }, + { "-K", NM_ETHTOOL_TYPE_FEATURE }, +); + static void parse_ethtool_option (const char *value, NMSettingWiredWakeOnLan *out_flags, @@ -4257,100 +4381,67 @@ parse_ethtool_option (const char *value, const char **out_duplex, NMSettingEthtool **out_s_ethtool) { - gs_free const char **words = NULL; guint i; + const char **w_iter; + NMEthtoolIfcfgOption ifcfg_option; + gs_free const char **words = NULL; + NMEthtoolType ethtool_type = NM_ETHTOOL_TYPE_UNKNOWN; words = nm_utils_strsplit_set (value, " \t\n"); if (!words) return; - if (words[0] && words[0][0] == '-') { - /* /sbin/ethtool $opts */ - if (NM_IN_STRSET (words[0], "-K", "--features", "--offload")) { - 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 ()); + if (words[0]) + ethtool_type = _get_ethtool_type_by_name (words[0]); - for (i = 2; words[i]; ) { - const char *opt = words[i]; - const char *opt_val = words[++i]; - const NMEthtoolData *d = NULL; - NMTernary onoff = NM_TERNARY_DEFAULT; + if (ethtool_type != NM_ETHTOOL_TYPE_UNKNOWN) { + if (!words[1]) { + /* first argument must be the interface name. This is invalid. */ + return; + } - if (nm_streq0 (opt_val, "on")) - onoff = NM_TERNARY_TRUE; - else if (nm_streq0 (opt_val, "off")) - onoff = NM_TERNARY_FALSE; + if (!*out_s_ethtool) + *out_s_ethtool = NM_SETTING_ETHTOOL (nm_setting_ethtool_new ()); - d = nms_ifcfg_rh_utils_get_ethtool_by_name (opt); + /* skip ethtool type && interface name */ + w_iter = &words[2]; - 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++; - } + if (ethtool_type == NM_ETHTOOL_TYPE_FEATURE) { + while (w_iter && *w_iter) { + w_iter = _next_ethtool_options_nmternary (w_iter, + ethtool_type, + &ifcfg_option); - /* silently ignore unsupported offloading features. */ - continue; - } - - i++; - - if (onoff == NM_TERNARY_DEFAULT) { - PARSE_WARNING ("Expects on/off argument for feature '%s'", opt); - continue; - } - - nm_setting_ethtool_set_feature (*out_s_ethtool, - 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 (ifcfg_option.has_value) + nm_setting_ethtool_set_feature (*out_s_ethtool, + ifcfg_option.optname, + ifcfg_option.v.nmternary); } - - 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; + return; + } + if (NM_IN_SET (ethtool_type, + NM_ETHTOOL_TYPE_COALESCE, + NM_ETHTOOL_TYPE_RING)) { + while (w_iter && *w_iter) { + w_iter = _next_ethtool_options_uint32 (w_iter, + ethtool_type, + &ifcfg_option); + + if (ifcfg_option.has_value) { + if (ethtool_type == NM_ETHTOOL_TYPE_COALESCE) + nm_setting_ethtool_set_coalesce (*out_s_ethtool, + ifcfg_option.optname, + ifcfg_option.v.u32); + else + nm_setting_ethtool_set_ring (*out_s_ethtool, + ifcfg_option.optname, + ifcfg_option.v.u32); } - - nm_setting_ethtool_set_coalesce (*out_s_ethtool, - d->optname, - (guint32) i64); } + return; } - return; + /* unsupported ethtool type */ + nm_assert_not_reached(); } /* /sbin/ethtool -s ${REALDEVICE} $opts */ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c index 08700a8a2f..ccaec401ea 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -598,11 +598,45 @@ const char *const _nm_ethtool_ifcfg_names[] = { ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION, "tx-udp_tnl-csum-segmentation"), ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION, "tx-udp_tnl-segmentation"), ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT, "tx-vlan-stag-hw-insert"), + ETHT_NAME (NM_ETHTOOL_ID_RING_RX, "rx"), + ETHT_NAME (NM_ETHTOOL_ID_RING_RX_JUMBO, "rx-jumbo"), + ETHT_NAME (NM_ETHTOOL_ID_RING_RX_MINI, "rx-mini"), + ETHT_NAME (NM_ETHTOOL_ID_RING_TX, "tx"), }; static NM_UTILS_STRING_TABLE_LOOKUP_DEFINE ( - _get_ethtoolid_by_name, + _get_ethtoolid_coalesce_by_name, + NMEthtoolID, + { nm_assert (name); }, + { return NM_ETHTOOL_ID_UNKNOWN; }, + { "adaptive-rx", NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX }, + { "adaptive-tx", NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX }, + { "pkt-rate-high", NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH }, + { "pkt-rate-low", NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW }, + { "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-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 }, + { "sample-interval", NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL }, + { "stats-block-usecs", NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS }, + { "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-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 }, +); + +static +NM_UTILS_STRING_TABLE_LOOKUP_DEFINE ( + _get_ethtoolid_feature_by_name, NMEthtoolID, { nm_assert (name); }, { return NM_ETHTOOL_ID_UNKNOWN; }, @@ -619,8 +653,6 @@ 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 }, @@ -632,35 +664,23 @@ 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 }, @@ -672,10 +692,6 @@ 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 }, @@ -694,21 +710,44 @@ 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 }, ); +static +NM_UTILS_STRING_TABLE_LOOKUP_DEFINE ( + _get_ethtoolid_ring_by_name, + NMEthtoolID, + { nm_assert (name); }, + { return NM_ETHTOOL_ID_UNKNOWN; }, + { "rx", NM_ETHTOOL_ID_RING_RX }, + { "rx-jumbo", NM_ETHTOOL_ID_RING_RX_JUMBO }, + { "rx-mini", NM_ETHTOOL_ID_RING_RX_MINI }, + { "tx", NM_ETHTOOL_ID_RING_TX }, +); + const NMEthtoolData * -nms_ifcfg_rh_utils_get_ethtool_by_name (const char *name) +nms_ifcfg_rh_utils_get_ethtool_by_name (const char *name, + NMEthtoolType ethtool_type) { NMEthtoolID id; - id = _get_ethtoolid_by_name (name); + switch (ethtool_type) { + case NM_ETHTOOL_TYPE_COALESCE: + id = _get_ethtoolid_coalesce_by_name (name); + break; + case NM_ETHTOOL_TYPE_FEATURE: + id = _get_ethtoolid_feature_by_name (name); + break; + case NM_ETHTOOL_TYPE_RING: + id = _get_ethtoolid_ring_by_name (name); + break; + default: + nm_assert_not_reached(); + return NULL; + } + if (id == NM_ETHTOOL_ID_UNKNOWN) return NULL; diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h index ed41a3eab0..b6d19e8403 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h @@ -153,6 +153,7 @@ nms_ifcfg_rh_utils_get_ethtool_name (NMEthtoolID ethtool_id) return _nm_ethtool_ifcfg_names[ethtool_id]; } -const NMEthtoolData *nms_ifcfg_rh_utils_get_ethtool_by_name (const char *name); +const NMEthtoolData *nms_ifcfg_rh_utils_get_ethtool_by_name (const char *name, + NMEthtoolType ethtool_type); #endif /* _UTILS_H_ */ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 64fdd8b182..aaa330685d 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -1212,6 +1212,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_printf (str, " %"G_GUINT32_FORMAT, val); } + + g_string_append (str, " ; -G "); + g_string_append (str, iface ?: "net0"); + + for (ethtool_id = _NM_ETHTOOL_ID_RING_FIRST; ethtool_id <= _NM_ETHTOOL_ID_RING_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_ring (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) { diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected index 39fdce8683..644fa06754 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected @@ -1,7 +1,7 @@ TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no -ETHTOOL_OPTS="autoneg on ; -K net0 rxvlan off tx on ; -C net0" +ETHTOOL_OPTS="autoneg on ; -K net0 rxvlan off tx on ; -C net0 ; -G net0" BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 34d4061b1a..a028d5281f 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -10364,35 +10364,48 @@ test_ethtool_names (void) { NM_ETHTOOL_ID_FEATURE_RXVLAN, "rx-vlan-hw-parse" }, { NM_ETHTOOL_ID_FEATURE_TXVLAN, "tx-vlan-hw-insert" }, }; + const struct { + guint nm_ethtool_id_first; + guint nm_ethtool_id_last; + } s_idxs[] = { + { _NM_ETHTOOL_ID_FEATURE_FIRST, _NM_ETHTOOL_ID_FEATURE_LAST }, + { _NM_ETHTOOL_ID_COALESCE_FIRST, _NM_ETHTOOL_ID_COALESCE_LAST }, + { _NM_ETHTOOL_ID_RING_FIRST, _NM_ETHTOOL_ID_RING_LAST }, + }; const NMEthtoolData *data; NMEthtoolID id; - int i; + guint i, k; - for (id = _NM_ETHTOOL_ID_FIRST; id <= _NM_ETHTOOL_ID_LAST; id++) { - const char *ifcfg_rh_name; + for (k = 0; k < sizeof(s_idxs) / sizeof(*s_idxs); ++k) { + for (id = s_idxs[k].nm_ethtool_id_first; id <= s_idxs[k].nm_ethtool_id_last; id++) { + const char *ifcfg_rh_name; - 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]); + 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 != id) - g_assert_cmpstr (ifcfg_rh_name, !=, _nm_ethtool_ifcfg_names[i]); - } + for (i = s_idxs[k].nm_ethtool_id_first; i < s_idxs[k].nm_ethtool_id_last; i++) { + if (i != id) + g_assert_cmpstr (ifcfg_rh_name, !=, _nm_ethtool_ifcfg_names[i]); + } - g_assert_cmpstr (nms_ifcfg_rh_utils_get_ethtool_name (id), ==, ifcfg_rh_name); + g_assert_cmpstr (nms_ifcfg_rh_utils_get_ethtool_name (id), ==, ifcfg_rh_name); - data = nms_ifcfg_rh_utils_get_ethtool_by_name (ifcfg_rh_name); - g_assert (data); - g_assert (data->id == id); + data = nms_ifcfg_rh_utils_get_ethtool_by_name (ifcfg_rh_name, nm_ethtool_id_to_type (id)); + + g_assert (data); + g_assert (data->id == id); + } } for (i = 0; i < G_N_ELEMENTS (kernel_names); i++) { const char *name = kernel_names[i].kernel_name; id = kernel_names[i].ethtool_id; - data = nms_ifcfg_rh_utils_get_ethtool_by_name (name); + + data = nms_ifcfg_rh_utils_get_ethtool_by_name (name, nm_ethtool_id_to_type (id)); + g_assert (data); g_assert (data->id == id); g_assert_cmpstr (nms_ifcfg_rh_utils_get_ethtool_name (id), !=, name); |