From 12063d6cb657b3e4cf007a5eb3549efe89d83abf Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 14 May 2020 09:16:30 +0200 Subject: [PATCH 01/10] platform: simplify NMEthtoolCoalesceState to only track one state Only in one moment we need the old and requested settings together: during _ethtool_coalesce_set(). But for that we shouldn't track both states in "NMEthtoolCoalesceState". Simplify "NMEthtoolCoalesceState" to only contain one set of options. By tracking less state, the code becomes simpler, because you don't need to wonder where the old and requested state is used. --- src/devices/nm-device.c | 43 ++++++++++++--------- src/platform/nm-platform-utils.c | 42 +++++++------------- src/platform/nm-platform-utils.h | 13 ++----- src/platform/nm-platform.c | 66 ++++++++++++++++---------------- src/platform/nm-platform.h | 12 +++--- 5 files changed, 81 insertions(+), 95 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 66eea16ce4..c20c078002 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,7 @@ typedef struct { int ifindex; NMEthtoolFeatureStates *features; NMTernary requested[_NM_ETHTOOL_ID_FEATURE_NUM]; - NMEthtoolCoalesceStates *coalesce; + NMEthtoolCoalesceState *coalesce; } EthtoolState; /*****************************************************************************/ @@ -868,7 +869,7 @@ static gboolean _ethtool_init_coalesce (NMDevice *self, NMPlatform *platform, NMSettingEthtool *s_ethtool, - NMEthtoolCoalesceStates *coalesce) + NMEthtoolCoalesceState *coalesce) { GHashTable *hash; GHashTableIter iter; @@ -904,14 +905,12 @@ _ethtool_init_coalesce (NMDevice *self, 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)); @@ -919,13 +918,17 @@ _ethtool_coalesce_reset (NMDevice *self, 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"); + return; + } + + _LOGD (LOGD_DEVICE, "ethtool: coalesce settings successfully reset"); } static void @@ -934,37 +937,39 @@ _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"); - ethtool_state->coalesce = g_steal_pointer (&coalesce); + _LOGD (LOGD_DEVICE, "ethtool: coalesce settings successfully set"); } static void diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index c47d8476fc..b0510c077a 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -845,31 +845,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); + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (coalesce, FALSE); - coalesce = g_new0 (NMEthtoolCoalesceStates, 1); - - 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 +911,23 @@ 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 (!success) { - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure %s coalesce settings", + if (!ethtool_set_coalesce (&shandle, coalesce)) { + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure setting coalesce settings", ifindex, - "set-coalesce", - do_set ? "setting" : "resetting"); + "set-coalesce"); return FALSE; } - nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: %s kernel coalesce settings", + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: set kernel coalesce settings", ifindex, - "set-coalesce", - do_set ? "set" : "reset"); + "set-coalesce"); return TRUE; } diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h index 56fdb5e4d3..b511c12cc6 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,13 @@ 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); /*****************************************************************************/ diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index c17cd305dc..03ca152fa8 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -3214,29 +3214,30 @@ 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)) @@ -3244,70 +3245,70 @@ nm_platform_ethtool_init_coalesce (NMPlatform *self, 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 +3320,13 @@ 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, do_set); + return nmp_utils_ethtool_set_coalesce (ifindex, coalesce); } /*****************************************************************************/ diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 260b5356ff..87571dd180 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -1954,20 +1954,20 @@ 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); const char * nm_platform_link_duplex_type_to_string (NMPlatformLinkDuplexType duplex); From 572f82a77b94fb0f1b39c27bc4075c3437201211 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Fri, 15 May 2020 15:25:30 +0200 Subject: [PATCH 02/10] nm-setting: add internal gendata API to get/set uint32 https://bugzilla.redhat.com/show_bug.cgi?id=1614700 --- libnm-core/nm-core-internal.h | 8 ++++++++ libnm-core/nm-setting.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 00645a7618..33062d74ab 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -334,6 +334,14 @@ 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_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.c b/libnm-core/nm-setting.c index 5a16d5cbe7..bf721301f4 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -2616,6 +2616,39 @@ _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))); +} + /*****************************************************************************/ static void From e08c3a6e180e9a9a9ad9b3198176e3dd6eb671f4 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Fri, 15 May 2020 15:26:30 +0200 Subject: [PATCH 03/10] nm-setting: add internal gendata API to clear value(s) The filter function in nm_setting_gendata_clear_all() is useful for when you want to only clear values according to a predicate, if no such function is supplied all values will be cleared. https://bugzilla.redhat.com/show_bug.cgi?id=1614700 --- libnm-core/nm-core-internal.h | 8 +++++++ libnm-core/nm-setting.c | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 33062d74ab..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,12 @@ 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); diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index bf721301f4..50a277d8b8 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -2649,6 +2649,48 @@ nm_setting_gendata_set_uint32 (NMSetting *setting, 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 From 55d2df665899e7a07550769b8fa8fc46af1fe8a6 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Fri, 15 May 2020 16:08:09 +0200 Subject: [PATCH 04/10] nm-setting: use nm_setting_gendata_clear_all() to clear features https://bugzilla.redhat.com/show_bug.cgi?id=1614700 --- libnm-core/nm-setting-ethtool.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/libnm-core/nm-setting-ethtool.c b/libnm-core/nm-setting-ethtool.c index 6dc6d5d75a..92e82ab7ef 100644 --- a/libnm-core/nm-setting-ethtool.c +++ b/libnm-core/nm-setting-ethtool.c @@ -193,26 +193,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); } From 3e50221d7efa9e116bd0dfd8e7e52918d79c16bb Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Fri, 15 May 2020 19:16:20 +0200 Subject: [PATCH 05/10] ethtool: refactor coalesce settings using gendata APIs https://bugzilla.redhat.com/show_bug.cgi?id=1614700 --- libnm-core/nm-setting-ethtool.c | 51 +++++++-------------------------- 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/libnm-core/nm-setting-ethtool.c b/libnm-core/nm-setting-ethtool.c index 92e82ab7ef..c33fdd847a 100644 --- a/libnm-core/nm-setting-ethtool.c +++ b/libnm-core/nm-setting-ethtool.c @@ -260,19 +260,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); } /** @@ -293,7 +286,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)); @@ -302,17 +294,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); } @@ -329,16 +318,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); } @@ -353,26 +336,14 @@ 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)); - hash = _nm_setting_gendata_hash (NM_SETTING (setting), FALSE); - if (!hash) - return; + if (nm_setting_gendata_clear_all (NM_SETTING (setting), + &nm_ethtool_optname_is_coalesce)) + + - 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); } From 7109ac667ac4587eb94ee50173ea8768cd83a2fb Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Tue, 12 May 2020 17:27:45 +0200 Subject: [PATCH 06/10] ethtool: add ring settings This is the initial support for ring 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 | 123 +++++++++++++++++- libnm-core/nm-setting-ethtool.h | 25 ++++ libnm-core/tests/test-setting.c | 89 ++++++++++++- libnm/libnm.ver | 5 + .../nm-libnm-core-intern/nm-ethtool-utils.c | 8 ++ .../nm-libnm-core-intern/nm-ethtool-utils.h | 15 ++- 6 files changed, 258 insertions(+), 7 deletions(-) diff --git a/libnm-core/nm-setting-ethtool.c b/libnm-core/nm-setting-ethtool.c index c33fdd847a..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)); +} + /*****************************************************************************/ /** @@ -340,10 +356,105 @@ nm_setting_ethtool_clear_coalesce_all (NMSettingEthtool *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)); + + ethtool_id = nm_ethtool_id_get_by_name (optname); + + g_return_if_fail (nm_ethtool_id_is_ring (ethtool_id)); + + 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); } @@ -401,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; } @@ -431,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/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..340dd5bfa1 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, }; /*****************************************************************************/ diff --git a/shared/nm-libnm-core-intern/nm-ethtool-utils.h b/shared/nm-libnm-core-intern/nm-ethtool-utils.h index 0505328364..6ee4eb6d86 100644 --- a/shared/nm-libnm-core-intern/nm-ethtool-utils.h +++ b/shared/nm-libnm-core-intern/nm-ethtool-utils.h @@ -93,10 +93,18 @@ 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; @@ -132,6 +140,11 @@ 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__ */ From e04e5a5c2a338b9946fbbfd09c957d84681eee35 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Thu, 14 May 2020 17:55:17 +0200 Subject: [PATCH 07/10] ifcfg-rh: add support for ethtool ring settings Also update unit tests. https://bugzilla.redhat.com/show_bug.cgi?id=1614700 --- .../nm-libnm-core-intern/nm-ethtool-utils.c | 13 + .../nm-libnm-core-intern/nm-ethtool-utils.h | 10 + .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 263 ++++++++++++------ .../plugins/ifcfg-rh/nms-ifcfg-rh-utils.c | 89 ++++-- .../plugins/ifcfg-rh/nms-ifcfg-rh-utils.h | 3 +- .../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 | 47 ++-- 8 files changed, 314 insertions(+), 130 deletions(-) diff --git a/shared/nm-libnm-core-intern/nm-ethtool-utils.c b/shared/nm-libnm-core-intern/nm-ethtool-utils.c index 340dd5bfa1..3e3c28d36a 100644 --- a/shared/nm-libnm-core-intern/nm-ethtool-utils.c +++ b/shared/nm-libnm-core-intern/nm-ethtool-utils.c @@ -261,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 6ee4eb6d86..0df3d3d00c 100644 --- a/shared/nm-libnm-core-intern/nm-ethtool-utils.h +++ b/shared/nm-libnm-core-intern/nm-ethtool-utils.h @@ -108,6 +108,13 @@ typedef enum { _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; @@ -117,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 @@ -145,6 +154,7 @@ 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/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 (words[0]) + ethtool_type = _get_ethtool_type_by_name (words[0]); - 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; - NMTernary onoff = NM_TERNARY_DEFAULT; - - 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); - - 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++; - } - - /* 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 (!*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); - } + if (ethtool_type != NM_ETHTOOL_TYPE_UNKNOWN) { + if (!words[1]) { + /* first argument must be the interface name. This is invalid. */ + return; } - return; + + if (!*out_s_ethtool) + *out_s_ethtool = NM_SETTING_ETHTOOL (nm_setting_ethtool_new ()); + + /* skip ethtool type && interface name */ + w_iter = &words[2]; + + if (ethtool_type == NM_ETHTOOL_TYPE_FEATURE) { + while (w_iter && *w_iter) { + w_iter = _next_ethtool_options_nmternary (w_iter, + ethtool_type, + &ifcfg_option); + + if (ifcfg_option.has_value) + nm_setting_ethtool_set_feature (*out_s_ethtool, + ifcfg_option.optname, + ifcfg_option.v.nmternary); + } + 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); + } + } + 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); + + 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); } - - 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); } 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); From 126995a4d854935f1ab9041dfdb39fd04be5e9d9 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Thu, 14 May 2020 17:57:44 +0200 Subject: [PATCH 08/10] clients: add support for ethtool ring settings https://bugzilla.redhat.com/show_bug.cgi?id=1614700 --- clients/common/nm-meta-setting-desc.c | 41 +++++++++++++++++++++------ 1 file changed, 33 insertions(+), 8 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, }; From 2d2c111304ed34a8d004cfa6e6bdde3fd3c71fa2 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Thu, 14 May 2020 18:27:54 +0200 Subject: [PATCH 09/10] platform: add support for ring settings using ioctl() https://bugzilla.redhat.com/show_bug.cgi?id=1614700 --- src/platform/nm-platform-utils.c | 91 ++++++++++++++++++++++++++++++++ src/platform/nm-platform-utils.h | 13 +++++ src/platform/nm-platform.c | 63 +++++++++++++++++++++- src/platform/nm-platform.h | 15 ++++++ 4 files changed, 180 insertions(+), 2 deletions(-) diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index b0510c077a..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"), ); @@ -931,6 +933,95 @@ nmp_utils_ethtool_set_coalesce (int ifindex, 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 (!ethtool_set_ring (&shandle, ring)) { + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: failure setting ring settings", + ifindex, + "set-ring"); + return FALSE; + } + + nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: set kernel ring settings", + ifindex, + "set-ring"); + return TRUE; +} + /*****************************************************************************/ gboolean diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h index b511c12cc6..242b97f168 100644 --- a/src/platform/nm-platform-utils.h +++ b/src/platform/nm-platform-utils.h @@ -123,6 +123,19 @@ gboolean nmp_utils_ethtool_get_coalesce (int ifindex, gboolean nmp_utils_ethtool_set_coalesce (int ifindex, 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); + /*****************************************************************************/ gboolean nmp_utils_mii_supports_carrier_detect (int ifindex); diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 03ca152fa8..596f08542e 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -3240,8 +3240,7 @@ nm_platform_ethtool_init_coalesce (NMPlatform *self, 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: @@ -3329,6 +3328,66 @@ nm_platform_ethtool_set_coalesce (NMPlatform *self, 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_ring (ifindex, ring); +} + /*****************************************************************************/ const NMDedupMultiHeadEntry * diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 87571dd180..8957de429c 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -1969,6 +1969,21 @@ gboolean nm_platform_ethtool_set_coalesce (NMPlatform *self, int ifindex, 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); void nm_platform_ip4_dev_route_blacklist_set (NMPlatform *self, From 2ce0e714b60aa59b1d0a46333de29d5c95ef07a4 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Thu, 14 May 2020 18:36:40 +0200 Subject: [PATCH 10/10] nm-device: apply ethtool ring settings when activating a connection nm-device now applies ethtool ring settings during stage 2 "device config" of the connection activation. ring 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 ring 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 | 131 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 123 insertions(+), 8 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index c20c078002..418641358d 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -187,6 +187,7 @@ typedef struct { NMEthtoolFeatureStates *features; NMTernary requested[_NM_ETHTOOL_ID_FEATURE_NUM]; NMEthtoolCoalesceState *coalesce; + NMEthtoolRingState *ring; } EthtoolState; /*****************************************************************************/ @@ -890,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, @@ -902,7 +905,7 @@ _ethtool_init_coalesce (NMDevice *self, } - return (!!n_coalesce_set); + return !!n_coalesce_set; } static void @@ -917,18 +920,15 @@ _ethtool_coalesce_reset (NMDevice *self, 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)) { + coalesce)) _LOGW (LOGD_DEVICE, "ethtool: failure resetting one or more coalesce settings"); - return; - } - - _LOGD (LOGD_DEVICE, "ethtool: coalesce settings successfully reset"); + else + _LOGD (LOGD_DEVICE, "ethtool: coalesce settings successfully reset"); } static void @@ -972,6 +972,114 @@ _ethtool_coalesce_set (NMDevice *self, _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; + } + + _LOGD (LOGD_DEVICE, "ethtool: ring settings successfully set"); +} + static void _ethtool_state_reset (NMDevice *self) { @@ -986,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); } @@ -1026,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); }