Commit 0212e5d9 authored by Joe Damato's avatar Joe Damato Committed by David S. Miller
Browse files

net/mlx5: Fix flowhash key set/get for custom RSS



mlx5 flow hash field retrieval and set only worked on the default
RSS context as of commit f01cc58c ("net/mlx5e: Support multiple RSS
contexts"), not custom RSS contexts.

For example, before this patch attempting to retrieve the flow hash fields
for RSS context 1 fails:

$ sudo ethtool -u eth1 rx-flow-hash tcp4 context 1
Cannot get RX network flow hashing options: Invalid argument

This patch fixes getting and setting the flow hash fields for contexts
other than the default context.

Getting the flow hash fields for RSS context 1:

$ sudo ethtool -u eth1 rx-flow-hash tcp4 context 1
For RSS context 1:
TCP over IPV4 flows use these fields for computing Hash flow key:
IP DA

Now, setting the flash hash fields to a custom value:

$ sudo ethtool -U eth1 rx-flow-hash tcp4 sdfn context 1

And retrieving them again:

$ sudo ethtool -u eth1 rx-flow-hash tcp4 context 1
For RSS context 1:
TCP over IPV4 flows use these fields for computing Hash flow key:
IP SA
IP DA
L4 bytes 0 & 1 [TCP/UDP src port]
L4 bytes 2 & 3 [TCP/UDP dst port]

Signed-off-by: default avatarJoe Damato <jdamato@fastly.com>
Reviewed-by: default avatarTariq Toukan <tariqt@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 801b27e8
Loading
Loading
Loading
Loading
+20 −5
Original line number Diff line number Diff line
@@ -218,17 +218,32 @@ int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
	return mlx5e_rss_set_rxfh(rss, indir, key, hfunc, res->rss_rqns, res->rss_nch);
}

u8 mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt)
int mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx,
				     enum mlx5_traffic_types tt)
{
	struct mlx5e_rss *rss = res->rss[0];
	struct mlx5e_rss *rss;

	if (rss_idx >= MLX5E_MAX_NUM_RSS)
		return -EINVAL;

	rss = res->rss[rss_idx];
	if (!rss)
		return -ENOENT;

	return mlx5e_rss_get_hash_fields(rss, tt);
}

int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt,
				     u8 rx_hash_fields)
int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx,
				     enum mlx5_traffic_types tt, u8 rx_hash_fields)
{
	struct mlx5e_rss *rss = res->rss[0];
	struct mlx5e_rss *rss;

	if (rss_idx >= MLX5E_MAX_NUM_RSS)
		return -EINVAL;

	rss = res->rss[rss_idx];
	if (!rss)
		return -ENOENT;

	return mlx5e_rss_set_hash_fields(rss, tt, rx_hash_fields);
}
+4 −3
Original line number Diff line number Diff line
@@ -48,9 +48,10 @@ int mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
			      const u32 *indir, const u8 *key, const u8 *hfunc);

u8 mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt);
int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt,
				     u8 rx_hash_fields);
int mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx,
				     enum mlx5_traffic_types tt);
int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, u32 rss_idx,
				     enum mlx5_traffic_types tt, u8 rx_hash_fields);
int mlx5e_rx_res_packet_merge_set_param(struct mlx5e_rx_res *res,
					struct mlx5e_packet_merge_param *pkt_merge_param);

+24 −9
Original line number Diff line number Diff line
@@ -900,10 +900,16 @@ static int mlx5e_set_rss_hash_opt(struct mlx5e_priv *priv,
				  struct ethtool_rxnfc *nfc)
{
	u8 rx_hash_field = 0;
	u32 flow_type = 0;
	u32 rss_idx = 0;
	int err;
	int tt;

	tt = flow_type_to_traffic_type(nfc->flow_type);
	if (nfc->flow_type & FLOW_RSS)
		rss_idx = nfc->rss_context;

	flow_type = flow_type_mask(nfc->flow_type);
	tt = flow_type_to_traffic_type(flow_type);
	if (tt < 0)
		return tt;

@@ -911,10 +917,10 @@ static int mlx5e_set_rss_hash_opt(struct mlx5e_priv *priv,
	 *  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)
	if (flow_type != TCP_V4_FLOW &&
	    flow_type != TCP_V6_FLOW &&
	    flow_type != UDP_V4_FLOW &&
	    flow_type != UDP_V6_FLOW)
		return -EOPNOTSUPP;

	if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
@@ -931,7 +937,7 @@ static int mlx5e_set_rss_hash_opt(struct mlx5e_priv *priv,
		rx_hash_field |= MLX5_HASH_FIELD_SEL_L4_DPORT;

	mutex_lock(&priv->state_lock);
	err = mlx5e_rx_res_rss_set_hash_fields(priv->rx_res, tt, rx_hash_field);
	err = mlx5e_rx_res_rss_set_hash_fields(priv->rx_res, rss_idx, tt, rx_hash_field);
	mutex_unlock(&priv->state_lock);

	return err;
@@ -940,14 +946,23 @@ static int mlx5e_set_rss_hash_opt(struct mlx5e_priv *priv,
static int mlx5e_get_rss_hash_opt(struct mlx5e_priv *priv,
				  struct ethtool_rxnfc *nfc)
{
	u32 hash_field = 0;
	int hash_field = 0;
	u32 flow_type = 0;
	u32 rss_idx = 0;
	int tt;

	tt = flow_type_to_traffic_type(nfc->flow_type);
	if (nfc->flow_type & FLOW_RSS)
		rss_idx = nfc->rss_context;

	flow_type = flow_type_mask(nfc->flow_type);
	tt = flow_type_to_traffic_type(flow_type);
	if (tt < 0)
		return tt;

	hash_field = mlx5e_rx_res_rss_get_hash_fields(priv->rx_res, tt);
	hash_field = mlx5e_rx_res_rss_get_hash_fields(priv->rx_res, rss_idx, tt);
	if (hash_field < 0)
		return hash_field;

	nfc->data = 0;

	if (hash_field & MLX5_HASH_FIELD_SEL_SRC_IP)