Skip to content

Commit

Permalink
net/mlx5e: ethtool, Support user configuration for RX hash fields
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Aya Levin authored and Saeed Mahameed committed Dec 6, 2018
1 parent bbeb53b commit 756c416
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 6 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
112 changes: 112 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
27 changes: 21 additions & 6 deletions drivers/net/ethernet/mellanox/mlx5/core/en_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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);
}
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 756c416

Please sign in to comment.