net/mlx5e: ethtool, Support user configuration for RX hash fields

Enable user configuration of RX hash fields that are used for traffic
spreading into RX queues. User can change built-in RSS (Receive Side
Scaling) profiles on the following traffic types: UDP4, UDP6, TCP4 and
TCP6.  This configuration effects both outer and inner headers.  Added
support for ethtool commands: ETHTOOL_SRXFH and ETHTOOL_GRXFH.

Command example respectively:
$ethtool -N eth1 rx-flow-hash tcp4 sdfn
$ethtool -n eth1 rx-flow-hash tcpp4
IP SA
IP DA
L4 bytes 0 & 1 [TCP/UDP src port]
L4 bytes 2 & 3 [TCP/UDP dst port]

Signed-off-by: Aya Levin <ayal@mellanox.com>
Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
This commit is contained in:
Aya Levin 2018-10-23 16:03:33 +03:00 committed by Saeed Mahameed
parent bbeb53b8b2
commit 756c41603a
3 changed files with 134 additions and 6 deletions

View File

@ -650,6 +650,7 @@ enum {
struct mlx5e_rss_params {
u32 indirection_rqt[MLX5E_INDIR_RQT_SIZE];
u32 rx_hash_fields[MLX5E_NUM_INDIR_TIRS];
u8 toeplitz_hash_key[40];
u8 hfunc;
};

View File

@ -771,6 +771,112 @@ void mlx5e_ethtool_init_steering(struct mlx5e_priv *priv)
INIT_LIST_HEAD(&priv->fs.ethtool.rules);
}
static enum mlx5e_traffic_types flow_type_to_traffic_type(u32 flow_type)
{
switch (flow_type) {
case TCP_V4_FLOW:
return MLX5E_TT_IPV4_TCP;
case TCP_V6_FLOW:
return MLX5E_TT_IPV6_TCP;
case UDP_V4_FLOW:
return MLX5E_TT_IPV4_UDP;
case UDP_V6_FLOW:
return MLX5E_TT_IPV6_UDP;
case AH_V4_FLOW:
return MLX5E_TT_IPV4_IPSEC_AH;
case AH_V6_FLOW:
return MLX5E_TT_IPV6_IPSEC_AH;
case ESP_V4_FLOW:
return MLX5E_TT_IPV4_IPSEC_ESP;
case ESP_V6_FLOW:
return MLX5E_TT_IPV6_IPSEC_ESP;
case IPV4_FLOW:
return MLX5E_TT_IPV4;
case IPV6_FLOW:
return MLX5E_TT_IPV6;
default:
return MLX5E_NUM_INDIR_TIRS;
}
}
static int mlx5e_set_rss_hash_opt(struct mlx5e_priv *priv,
struct ethtool_rxnfc *nfc)
{
int inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
enum mlx5e_traffic_types tt;
u8 rx_hash_field = 0;
void *in;
tt = flow_type_to_traffic_type(nfc->flow_type);
if (tt == MLX5E_NUM_INDIR_TIRS)
return -EINVAL;
/* RSS does not support anything other than hashing to queues
* on src IP, dest IP, TCP/UDP src port and TCP/UDP dest
* port.
*/
if (nfc->flow_type != TCP_V4_FLOW &&
nfc->flow_type != TCP_V6_FLOW &&
nfc->flow_type != UDP_V4_FLOW &&
nfc->flow_type != UDP_V6_FLOW)
return -EOPNOTSUPP;
if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
RXH_L4_B_0_1 | RXH_L4_B_2_3))
return -EOPNOTSUPP;
if (nfc->data & RXH_IP_SRC)
rx_hash_field |= MLX5_HASH_FIELD_SEL_SRC_IP;
if (nfc->data & RXH_IP_DST)
rx_hash_field |= MLX5_HASH_FIELD_SEL_DST_IP;
if (nfc->data & RXH_L4_B_0_1)
rx_hash_field |= MLX5_HASH_FIELD_SEL_L4_SPORT;
if (nfc->data & RXH_L4_B_2_3)
rx_hash_field |= MLX5_HASH_FIELD_SEL_L4_DPORT;
in = kvzalloc(inlen, GFP_KERNEL);
if (!in)
return -ENOMEM;
mutex_lock(&priv->state_lock);
if (rx_hash_field == priv->rss_params.rx_hash_fields[tt])
goto out;
priv->rss_params.rx_hash_fields[tt] = rx_hash_field;
mlx5e_modify_tirs_hash(priv, in, inlen);
out:
mutex_unlock(&priv->state_lock);
kvfree(in);
return 0;
}
static int mlx5e_get_rss_hash_opt(struct mlx5e_priv *priv,
struct ethtool_rxnfc *nfc)
{
enum mlx5e_traffic_types tt;
u32 hash_field = 0;
tt = flow_type_to_traffic_type(nfc->flow_type);
if (tt == MLX5E_NUM_INDIR_TIRS)
return -EINVAL;
hash_field = priv->rss_params.rx_hash_fields[tt];
nfc->data = 0;
if (hash_field & MLX5_HASH_FIELD_SEL_SRC_IP)
nfc->data |= RXH_IP_SRC;
if (hash_field & MLX5_HASH_FIELD_SEL_DST_IP)
nfc->data |= RXH_IP_DST;
if (hash_field & MLX5_HASH_FIELD_SEL_L4_SPORT)
nfc->data |= RXH_L4_B_0_1;
if (hash_field & MLX5_HASH_FIELD_SEL_L4_DPORT)
nfc->data |= RXH_L4_B_2_3;
return 0;
}
int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
{
int err = 0;
@ -783,6 +889,9 @@ int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
case ETHTOOL_SRXCLSRLDEL:
err = mlx5e_ethtool_flow_remove(priv, cmd->fs.location);
break;
case ETHTOOL_SRXFH:
err = mlx5e_set_rss_hash_opt(priv, cmd);
break;
default:
err = -EOPNOTSUPP;
break;
@ -810,6 +919,9 @@ int mlx5e_get_rxnfc(struct net_device *dev,
case ETHTOOL_GRXCLSRLALL:
err = mlx5e_ethtool_get_all_flows(priv, info, rule_locs);
break;
case ETHTOOL_GRXFH:
err = mlx5e_get_rss_hash_opt(priv, info);
break;
default:
err = -EOPNOTSUPP;
break;

View File

@ -2695,20 +2695,30 @@ void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_rss_params *rss_params,
ttconfig->rx_hash_fields);
}
static void mlx5e_update_rx_hash_fields(struct mlx5e_tirc_config *ttconfig,
enum mlx5e_traffic_types tt,
u32 rx_hash_fields)
{
*ttconfig = tirc_default_config[tt];
ttconfig->rx_hash_fields = rx_hash_fields;
}
void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in, int inlen)
{
void *tirc = MLX5_ADDR_OF(modify_tir_in, in, ctx);
struct mlx5e_rss_params *rss = &priv->rss_params;
struct mlx5_core_dev *mdev = priv->mdev;
int ctxlen = MLX5_ST_SZ_BYTES(tirc);
struct mlx5e_tirc_config ttconfig;
int tt;
MLX5_SET(modify_tir_in, in, bitmask.hash, 1);
for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
memset(tirc, 0, ctxlen);
mlx5e_build_indir_tir_ctx_hash(&priv->rss_params,
&tirc_default_config[tt],
tirc, false);
mlx5e_update_rx_hash_fields(&ttconfig, tt,
rss->rx_hash_fields[tt]);
mlx5e_build_indir_tir_ctx_hash(rss, &ttconfig, tirc, false);
mlx5_core_modify_tir(mdev, priv->indir_tir[tt].tirn, in, inlen);
}
@ -2717,9 +2727,9 @@ void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in, int inlen)
for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
memset(tirc, 0, ctxlen);
mlx5e_build_indir_tir_ctx_hash(&priv->rss_params,
&tirc_default_config[tt],
tirc, true);
mlx5e_update_rx_hash_fields(&ttconfig, tt,
rss->rx_hash_fields[tt]);
mlx5e_build_indir_tir_ctx_hash(rss, &ttconfig, tirc, true);
mlx5_core_modify_tir(mdev, priv->inner_indir_tir[tt].tirn, in,
inlen);
}
@ -4514,11 +4524,16 @@ void mlx5e_build_rq_params(struct mlx5_core_dev *mdev,
void mlx5e_build_rss_params(struct mlx5e_rss_params *rss_params,
u16 num_channels)
{
enum mlx5e_traffic_types tt;
rss_params->hfunc = ETH_RSS_HASH_XOR;
netdev_rss_key_fill(rss_params->toeplitz_hash_key,
sizeof(rss_params->toeplitz_hash_key));
mlx5e_build_default_indir_rqt(rss_params->indirection_rqt,
MLX5E_INDIR_RQT_SIZE, num_channels);
for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
rss_params->rx_hash_fields[tt] =
tirc_default_config[tt].rx_hash_fields;
}
void mlx5e_build_nic_params(struct mlx5_core_dev *mdev,