net/mlx5: fix RSS flow rule with L4 mismatch
authorLior Margalit <lmargalit@nvidia.com>
Tue, 27 Jul 2021 06:46:19 +0000 (09:46 +0300)
committerRaslan Darawsheh <rasland@nvidia.com>
Thu, 29 Jul 2021 16:01:20 +0000 (18:01 +0200)
The RSS hash types defined in the API do not support setting the L4 proto
type (TCP or UDP) without setting the L3 proto. For example, ETH_RSS_TCP
is defined as
(ETH_RSS_NONFRAG_IPV4_TCP | \
 ETH_RSS_NONFRAG_IPV6_TCP | \
 ETH_RSS_IPV6_TCP_EX).

The L3 proto of the RSS hash type may be different than the one defined
in the pattern, for example:
testpmd> flow create .../ ipv4 / tcp / end actions rss types ipv6-tcp-ex
end / end

If the RSS hash type also includes L4 proto type as in the above example,
the selection flags for the RX hash are currently set with SPORT/DPORT
without setting SRC/DST IP. As this combination is not supported, it does
not match any of the pre-created TIRs of the indirect RSS action
and the flow creation fails.

The fix is to prevent setting the selection flags for the RX hash with
SPORT/DPORT without setting SRC/DST IP. It applies non-RSS processing of
the received packets. In case of indirect RSS action, it will match the
MLX5_RSS_HASH_NONE pre-created TIR.

Fixes: b1d63d829378 ("net/mlx5: support RSS on src or dst fields only")
Fixes: 4a78c88e3bae ("net/mlx5: fix Verbs flow tunnel")
Cc: stable@dpdk.org
Signed-off-by: Lior Margalit <lmargalit@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
drivers/net/mlx5/mlx5_flow_dv.c
drivers/net/mlx5/mlx5_flow_verbs.c

index 736227b..0538c85 100644 (file)
@@ -10896,10 +10896,8 @@ flow_dv_hashfields_set(struct mlx5_flow *dev_flow,
 
        dev_flow->hash_fields = 0;
 #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT
-       if (rss_desc->level >= 2) {
-               dev_flow->hash_fields |= IBV_RX_HASH_INNER;
+       if (rss_desc->level >= 2)
                rss_inner = 1;
-       }
 #endif
        if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L3_IPV4)) ||
            (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L3_IPV4))) {
@@ -10922,6 +10920,12 @@ flow_dv_hashfields_set(struct mlx5_flow *dev_flow,
                                dev_flow->hash_fields |= MLX5_IPV6_IBV_RX_HASH;
                }
        }
+       if (dev_flow->hash_fields == 0)
+               /*
+                * There is no match between the RSS types and the
+                * L3 protocol (IPv4/IPv6) defined in the flow rule.
+                */
+               return;
        if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_UDP)) ||
            (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_UDP))) {
                if (rss_types & ETH_RSS_UDP) {
@@ -10947,6 +10951,8 @@ flow_dv_hashfields_set(struct mlx5_flow *dev_flow,
                                dev_flow->hash_fields |= MLX5_TCP_IBV_RX_HASH;
                }
        }
+       if (rss_inner)
+               dev_flow->hash_fields |= IBV_RX_HASH_INNER;
 }
 
 /**
index 7b3d0b3..a36b8ad 100644 (file)
@@ -1821,8 +1821,9 @@ flow_verbs_translate(struct rte_eth_dev *dev,
                        flow_verbs_translate_item_tcp(dev_flow, items,
                                                      item_flags);
                        subpriority = MLX5_PRIORITY_MAP_L4;
-                       dev_flow->hash_fields |=
-                               mlx5_flow_hashfields_adjust
+                       if (dev_flow->hash_fields != 0)
+                               dev_flow->hash_fields |=
+                                       mlx5_flow_hashfields_adjust
                                        (rss_desc, tunnel, ETH_RSS_TCP,
                                         (IBV_RX_HASH_SRC_PORT_TCP |
                                          IBV_RX_HASH_DST_PORT_TCP));
@@ -1833,8 +1834,9 @@ flow_verbs_translate(struct rte_eth_dev *dev,
                        flow_verbs_translate_item_udp(dev_flow, items,
                                                      item_flags);
                        subpriority = MLX5_PRIORITY_MAP_L4;
-                       dev_flow->hash_fields |=
-                               mlx5_flow_hashfields_adjust
+                       if (dev_flow->hash_fields != 0)
+                               dev_flow->hash_fields |=
+                                       mlx5_flow_hashfields_adjust
                                        (rss_desc, tunnel, ETH_RSS_UDP,
                                         (IBV_RX_HASH_SRC_PORT_UDP |
                                          IBV_RX_HASH_DST_PORT_UDP));