From d8f551cf4a443c980f0f2ee15097cd58c43b2165 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Thu, 7 May 2020 17:11:34 +0200 Subject: [PATCH] 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,