net/mlx5: Fix flowhash key set/get for custom RSS
authorJoe Damato <jdamato@fastly.com>
Tue, 25 Jul 2023 20:56:55 +0000 (20:56 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 28 Jul 2023 08:35:53 +0000 (09:35 +0100)
mlx5 flow hash field retrieval and set only worked on the default
RSS context as of commit f01cc58c18d6 ("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: Joe Damato <jdamato@fastly.com>
Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h
drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c

index e1095bc..56e6b8c 100644 (file)
@@ -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);
 }
index 5d5f64f..580fe8b 100644 (file)
@@ -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);
 
index aac32e5..aed599d 100644 (file)
@@ -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)