From 858fb211ad11bd9a7e89f63fe62d4fa7f8cee7b1 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Thu, 7 May 2020 17:09:49 +0200 Subject: [PATCH 1/6] keyfile: add support for uint32 variant types when using gendata https://bugzilla.redhat.com/show_bug.cgi?id=1614700 --- shared/nm-keyfile/nm-keyfile.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/shared/nm-keyfile/nm-keyfile.c b/shared/nm-keyfile/nm-keyfile.c index 0caef893e0..372ae202e3 100644 --- a/shared/nm-keyfile/nm-keyfile.c +++ b/shared/nm-keyfile/nm-keyfile.c @@ -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 From b0240db06883157636c0efb364c9fad0066dafa4 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Thu, 7 May 2020 16:58:32 +0200 Subject: [PATCH 2/6] ethtool: add coalesce settings This is the initial support for coalesce settings and only allows getting/setting, nothing is yet implemented in nm-device. Also add unit test. https://bugzilla.redhat.com/show_bug.cgi?id=1614700 --- libnm-core/nm-setting-ethtool.c | 186 +++++++++++++++++- libnm-core/nm-setting-ethtool.h | 43 ++++ libnm-core/tests/test-setting.c | 85 ++++++++ libnm/libnm.ver | 5 + .../nm-libnm-core-intern/nm-ethtool-utils.c | 44 +++++ .../nm-libnm-core-intern/nm-ethtool-utils.h | 36 +++- src/platform/tests/test-link.c | 10 +- 7 files changed, 392 insertions(+), 17 deletions(-) diff --git a/libnm-core/nm-setting-ethtool.c b/libnm-core/nm-setting-ethtool.c index a8976b69f5..6dc6d5d75a 100644 --- a/libnm-core/nm-setting-ethtool.c +++ b/libnm-core/nm-setting-ethtool.c @@ -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, diff --git a/libnm-core/nm-setting-ethtool.h b/libnm-core/nm-setting-ethtool.h index ba8c6a6e7e..a62a33159c 100644 --- a/libnm-core/nm-setting-ethtool.h +++ b/libnm-core/nm-setting-ethtool.h @@ -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__ */ diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index f77ba9fd17..1e82e245f9 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -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); diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 59e7db4ff1..e8203f5b6e 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -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; diff --git a/shared/nm-libnm-core-intern/nm-ethtool-utils.c b/shared/nm-libnm-core-intern/nm-ethtool-utils.c index ace47680f5..3842e3122e 100644 --- a/shared/nm-libnm-core-intern/nm-ethtool-utils.c +++ b/shared/nm-libnm-core-intern/nm-ethtool-utils.c @@ -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, diff --git a/shared/nm-libnm-core-intern/nm-ethtool-utils.h b/shared/nm-libnm-core-intern/nm-ethtool-utils.h index b3413de2b7..0505328364 100644 --- a/shared/nm-libnm-core-intern/nm-ethtool-utils.h +++ b/shared/nm-libnm-core-intern/nm-ethtool-utils.h @@ -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__ */ diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index ea4a2c5ab9..7398d2ee27 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -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; From 4fce8b3efbd633d6fd99f96e468818f7a7ddd02f Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Thu, 7 May 2020 17:12:19 +0200 Subject: [PATCH 3/6] ifcfg-rh: add support for ethtool coalesce settings Also update unit tests. https://bugzilla.redhat.com/show_bug.cgi?id=1614700 --- .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 42 +++++++++++++++- .../plugins/ifcfg-rh/nms-ifcfg-rh-utils.c | 49 +++++++++++++++++-- .../plugins/ifcfg-rh/nms-ifcfg-rh-utils.h | 10 ++-- .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 17 +++++++ ...st_write_wired_auto_negotiate_on.cexpected | 2 +- .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 12 ++--- 6 files changed, 115 insertions(+), 17 deletions(-) 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 6b1f169563..11754e70fa 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -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; } 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 06d4928ae5..08700a8a2f 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -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 }, 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 805f1581f1..ed41a3eab0 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h @@ -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); 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 b9f8161b9c..64fdd8b182 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -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) { 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 426085765c..39fdce8683 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" +ETHTOOL_OPTS="autoneg on ; -K net0 rxvlan off tx on ; -C 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 d0b9ffb8d3..34d4061b1a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -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]); } From 56c48b162bf72cf478922f82ed3796a9826f6b1e Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Thu, 7 May 2020 17:04:56 +0200 Subject: [PATCH 4/6] clients: add support for ethtool coalesce settings https://bugzilla.redhat.com/show_bug.cgi?id=1614700 --- clients/common/nm-meta-setting-desc.c | 145 +++++++++++++++++++------- 1 file changed, 107 insertions(+), 38 deletions(-) diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index 2df48493de..272c089d98 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -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, }; From d8f551cf4a443c980f0f2ee15097cd58c43b2165 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Thu, 7 May 2020 17:11:34 +0200 Subject: [PATCH 5/6] platform: add support for coalesce settings using ioctl() https://bugzilla.redhat.com/show_bug.cgi?id=1614700 --- src/platform/nm-platform-utils.c | 141 +++++++++++++++++++++++++++++++ src/platform/nm-platform-utils.h | 36 ++++++++ src/platform/nm-platform.c | 115 +++++++++++++++++++++++++ src/platform/nm-platform.h | 15 ++++ 4 files changed, 307 insertions(+) diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index 98884cd717..c47d8476fc 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -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 diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h index a62d828c89..56fdb5e4d3 100644 --- a/src/platform/nm-platform-utils.h +++ b/src/platform/nm-platform-utils.h @@ -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); diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 9bbc37453c..c17cd305dc 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -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 * diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 7edaaf58e3..931ab16391 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -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, From e2be41cbbefc2b58d4ced977c89d54898bd82374 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Thu, 7 May 2020 17:13:46 +0200 Subject: [PATCH 6/6] nm-device: apply ethtool coalesce settings when activating a connection nm-device now applies ethtool coalesce settings during stage 2 "device config" of the connection activation. Coalesce settings will be then restored (according to what the state was before the connection got activated on the device) when the connection is deactivated during the device cleanup. One thing to be noted is that unset coalesce settings (in the profile) will not be touched at all by NetworkManager so that if the NIC driver sets some default values these will be preserved unless specifically overridden by the connection profile. https://bugzilla.redhat.com/show_bug.cgi?id=1614700 --- src/devices/nm-device.c | 227 ++++++++++++++++++++++++++++++++-------- 1 file changed, 186 insertions(+), 41 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index fb926c945d..de72b1d15a 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -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); } /*****************************************************************************/