platform: add support for coalesce settings using ioctl()

https://bugzilla.redhat.com/show_bug.cgi?id=1614700
This commit is contained in:
Antonio Cardace 2020-05-07 17:11:34 +02:00
parent 56c48b162b
commit d8f551cf4a
No known key found for this signature in database
GPG key ID: 6BF80ABD43E377D3
4 changed files with 307 additions and 0 deletions

View file

@ -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,
&eth_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,
&eth_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

View file

@ -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);

View file

@ -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 *

View file

@ -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,