mirror of https://gitee.com/openkylin/linux.git
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:
parent
bbeb53b8b2
commit
756c41603a
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue