net/enic: avoid error message when no advanced filtering
[dpdk.git] / drivers / net / mlx5 / mlx5_flow.c
index 549b305..9904bc5 100644 (file)
@@ -98,12 +98,27 @@ struct mlx5_flow_expand_node {
        uint64_t rss_types;
        /**<
         * RSS types bit-field associated with this node
-        * (see ETH_RSS_* definitions).
+        * (see RTE_ETH_RSS_* definitions).
+        */
+       uint64_t node_flags;
+       /**<
+        *  Bit-fields that define how the node is used in the expansion.
+        * (see MLX5_EXPANSION_NODE_* definitions).
         */
-       uint8_t optional;
-       /**< optional expand field. Default 0 to expand, 1 not go deeper. */
 };
 
+/* Optional expand field. The expansion alg will not go deeper. */
+#define MLX5_EXPANSION_NODE_OPTIONAL (UINT64_C(1) << 0)
+
+/* The node is not added implicitly as expansion to the flow pattern.
+ * If the node type does not match the flow pattern item type, the
+ * expansion alg will go deeper to its next items.
+ * In the current implementation, the list of next nodes indexes can
+ * have up to one node with this flag set and it has to be the last
+ * node index (before the list terminator).
+ */
+#define MLX5_EXPANSION_NODE_EXPLICIT (UINT64_C(1) << 1)
+
 /** Object returned by mlx5_flow_expand_rss(). */
 struct mlx5_flow_expand_rss {
        uint32_t entries;
@@ -117,6 +132,12 @@ struct mlx5_flow_expand_rss {
 static void
 mlx5_dbg__print_pattern(const struct rte_flow_item *item);
 
+static const struct mlx5_flow_expand_node *
+mlx5_flow_expand_rss_adjust_node(const struct rte_flow_item *pattern,
+               unsigned int item_idx,
+               const struct mlx5_flow_expand_node graph[],
+               const struct mlx5_flow_expand_node *node);
+
 static bool
 mlx5_flow_is_rss_expandable_item(const struct rte_flow_item *item)
 {
@@ -135,6 +156,7 @@ mlx5_flow_is_rss_expandable_item(const struct rte_flow_item *item)
        case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
        case RTE_FLOW_ITEM_TYPE_GRE_KEY:
        case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT:
+       case RTE_FLOW_ITEM_TYPE_GTP:
                return true;
        default:
                break;
@@ -243,6 +265,26 @@ mlx5_flow_expand_rss_item_complete(const struct rte_flow_item *item)
        return ret;
 }
 
+static const int *
+mlx5_flow_expand_rss_skip_explicit(const struct mlx5_flow_expand_node graph[],
+               const int *next_node)
+{
+       const struct mlx5_flow_expand_node *node = NULL;
+       const int *next = next_node;
+
+       while (next && *next) {
+               /*
+                * Skip the nodes with the MLX5_EXPANSION_NODE_EXPLICIT
+                * flag set, because they were not found in the flow pattern.
+                */
+               node = &graph[*next];
+               if (!(node->node_flags & MLX5_EXPANSION_NODE_EXPLICIT))
+                       break;
+               next = node->next;
+       }
+       return next;
+}
+
 #define MLX5_RSS_EXP_ELT_N 16
 
 /**
@@ -256,7 +298,7 @@ mlx5_flow_expand_rss_item_complete(const struct rte_flow_item *item)
  * @param[in] pattern
  *   User flow pattern.
  * @param[in] types
- *   RSS types to expand (see ETH_RSS_* definitions).
+ *   RSS types to expand (see RTE_ETH_RSS_* definitions).
  * @param[in] graph
  *   Input graph to expand @p pattern according to @p types.
  * @param[in] graph_root_index
@@ -282,7 +324,7 @@ mlx5_flow_expand_rss(struct mlx5_flow_expand_rss *buf, size_t size,
        const int *stack[MLX5_RSS_EXP_ELT_N];
        int stack_pos = 0;
        struct rte_flow_item flow_items[MLX5_RSS_EXP_ELT_N];
-       unsigned int i;
+       unsigned int i, item_idx, last_expand_item_idx = 0;
        size_t lsize;
        size_t user_pattern_size = 0;
        void *addr = NULL;
@@ -290,7 +332,7 @@ mlx5_flow_expand_rss(struct mlx5_flow_expand_rss *buf, size_t size,
        struct rte_flow_item missed_item;
        int missed = 0;
        int elt = 0;
-       const struct rte_flow_item *last_item = NULL;
+       const struct rte_flow_item *last_expand_item = NULL;
 
        memset(&missed_item, 0, sizeof(missed_item));
        lsize = offsetof(struct mlx5_flow_expand_rss, entry) +
@@ -301,16 +343,26 @@ mlx5_flow_expand_rss(struct mlx5_flow_expand_rss *buf, size_t size,
        buf->entry[0].pattern = (void *)&buf->entry[MLX5_RSS_EXP_ELT_N];
        buf->entries = 0;
        addr = buf->entry[0].pattern;
-       for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+       for (item = pattern, item_idx = 0;
+                       item->type != RTE_FLOW_ITEM_TYPE_END;
+                       item++, item_idx++) {
                if (!mlx5_flow_is_rss_expandable_item(item)) {
                        user_pattern_size += sizeof(*item);
                        continue;
                }
-               last_item = item;
-               for (i = 0; node->next && node->next[i]; ++i) {
+               last_expand_item = item;
+               last_expand_item_idx = item_idx;
+               i = 0;
+               while (node->next && node->next[i]) {
                        next = &graph[node->next[i]];
                        if (next->type == item->type)
                                break;
+                       if (next->node_flags & MLX5_EXPANSION_NODE_EXPLICIT) {
+                               node = next;
+                               i = 0;
+                       } else {
+                               ++i;
+                       }
                }
                if (next)
                        node = next;
@@ -331,7 +383,7 @@ mlx5_flow_expand_rss(struct mlx5_flow_expand_rss *buf, size_t size,
         * Check if the last valid item has spec set, need complete pattern,
         * and the pattern can be used for expansion.
         */
-       missed_item.type = mlx5_flow_expand_rss_item_complete(last_item);
+       missed_item.type = mlx5_flow_expand_rss_item_complete(last_expand_item);
        if (missed_item.type == RTE_FLOW_ITEM_TYPE_END) {
                /* Item type END indicates expansion is not required. */
                return lsize;
@@ -339,13 +391,20 @@ mlx5_flow_expand_rss(struct mlx5_flow_expand_rss *buf, size_t size,
        if (missed_item.type != RTE_FLOW_ITEM_TYPE_VOID) {
                next = NULL;
                missed = 1;
-               for (i = 0; node->next && node->next[i]; ++i) {
+               i = 0;
+               while (node->next && node->next[i]) {
                        next = &graph[node->next[i]];
                        if (next->type == missed_item.type) {
                                flow_items[0].type = missed_item.type;
                                flow_items[1].type = RTE_FLOW_ITEM_TYPE_END;
                                break;
                        }
+                       if (next->node_flags & MLX5_EXPANSION_NODE_EXPLICIT) {
+                               node = next;
+                               i = 0;
+                       } else {
+                               ++i;
+                       }
                        next = NULL;
                }
        }
@@ -366,9 +425,13 @@ mlx5_flow_expand_rss(struct mlx5_flow_expand_rss *buf, size_t size,
                        addr = (void *)(((uintptr_t)addr) +
                                        elt * sizeof(*item));
                }
+       } else if (last_expand_item != NULL) {
+               node = mlx5_flow_expand_rss_adjust_node(pattern,
+                               last_expand_item_idx, graph, node);
        }
        memset(flow_items, 0, sizeof(flow_items));
-       next_node = node->next;
+       next_node = mlx5_flow_expand_rss_skip_explicit(graph,
+                       node->next);
        stack[stack_pos] = next_node;
        node = next_node ? &graph[*next_node] : NULL;
        while (node) {
@@ -403,8 +466,10 @@ mlx5_flow_expand_rss(struct mlx5_flow_expand_rss *buf, size_t size,
                        addr = (void *)(((uintptr_t)addr) + n);
                }
                /* Go deeper. */
-               if (!node->optional && node->next) {
-                       next_node = node->next;
+               if (!(node->node_flags & MLX5_EXPANSION_NODE_OPTIONAL) &&
+                               node->next) {
+                       next_node = mlx5_flow_expand_rss_skip_explicit(graph,
+                                       node->next);
                        if (stack_pos++ == MLX5_RSS_EXP_ELT_N) {
                                rte_errno = E2BIG;
                                return -rte_errno;
@@ -412,15 +477,27 @@ mlx5_flow_expand_rss(struct mlx5_flow_expand_rss *buf, size_t size,
                        stack[stack_pos] = next_node;
                } else if (*(next_node + 1)) {
                        /* Follow up with the next possibility. */
+                       next_node = mlx5_flow_expand_rss_skip_explicit(graph,
+                                       ++next_node);
+               } else if (!stack_pos) {
+                       /*
+                        * Completing the traverse over the different paths.
+                        * The next_node is advanced to the terminator.
+                        */
                        ++next_node;
                } else {
                        /* Move to the next path. */
-                       if (stack_pos)
+                       while (stack_pos) {
                                next_node = stack[--stack_pos];
-                       next_node++;
+                               next_node++;
+                               if (*next_node)
+                                       break;
+                       }
+                       next_node = mlx5_flow_expand_rss_skip_explicit(graph,
+                                       next_node);
                        stack[stack_pos] = next_node;
                }
-               node = *next_node ? &graph[*next_node] : NULL;
+               node = next_node && *next_node ? &graph[*next_node] : NULL;
        };
        return lsize;
 }
@@ -428,10 +505,7 @@ mlx5_flow_expand_rss(struct mlx5_flow_expand_rss *buf, size_t size,
 enum mlx5_expansion {
        MLX5_EXPANSION_ROOT,
        MLX5_EXPANSION_ROOT_OUTER,
-       MLX5_EXPANSION_ROOT_ETH_VLAN,
-       MLX5_EXPANSION_ROOT_OUTER_ETH_VLAN,
        MLX5_EXPANSION_OUTER_ETH,
-       MLX5_EXPANSION_OUTER_ETH_VLAN,
        MLX5_EXPANSION_OUTER_VLAN,
        MLX5_EXPANSION_OUTER_IPV4,
        MLX5_EXPANSION_OUTER_IPV4_UDP,
@@ -440,13 +514,14 @@ enum mlx5_expansion {
        MLX5_EXPANSION_OUTER_IPV6_UDP,
        MLX5_EXPANSION_OUTER_IPV6_TCP,
        MLX5_EXPANSION_VXLAN,
+       MLX5_EXPANSION_STD_VXLAN,
+       MLX5_EXPANSION_L3_VXLAN,
        MLX5_EXPANSION_VXLAN_GPE,
        MLX5_EXPANSION_GRE,
        MLX5_EXPANSION_NVGRE,
        MLX5_EXPANSION_GRE_KEY,
        MLX5_EXPANSION_MPLS,
        MLX5_EXPANSION_ETH,
-       MLX5_EXPANSION_ETH_VLAN,
        MLX5_EXPANSION_VLAN,
        MLX5_EXPANSION_IPV4,
        MLX5_EXPANSION_IPV4_UDP,
@@ -455,6 +530,7 @@ enum mlx5_expansion {
        MLX5_EXPANSION_IPV6_UDP,
        MLX5_EXPANSION_IPV6_TCP,
        MLX5_EXPANSION_IPV6_FRAG_EXT,
+       MLX5_EXPANSION_GTP
 };
 
 /** Supported expansion of items. */
@@ -471,22 +547,7 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
                                                  MLX5_EXPANSION_OUTER_IPV6),
                .type = RTE_FLOW_ITEM_TYPE_END,
        },
-       [MLX5_EXPANSION_ROOT_ETH_VLAN] = {
-               .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH_VLAN),
-               .type = RTE_FLOW_ITEM_TYPE_END,
-       },
-       [MLX5_EXPANSION_ROOT_OUTER_ETH_VLAN] = {
-               .next = MLX5_FLOW_EXPAND_RSS_NEXT
-                                               (MLX5_EXPANSION_OUTER_ETH_VLAN),
-               .type = RTE_FLOW_ITEM_TYPE_END,
-       },
        [MLX5_EXPANSION_OUTER_ETH] = {
-               .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_IPV4,
-                                                 MLX5_EXPANSION_OUTER_IPV6),
-               .type = RTE_FLOW_ITEM_TYPE_ETH,
-               .rss_types = 0,
-       },
-       [MLX5_EXPANSION_OUTER_ETH_VLAN] = {
                .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_VLAN),
                .type = RTE_FLOW_ITEM_TYPE_ETH,
                .rss_types = 0,
@@ -495,6 +556,7 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
                .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_IPV4,
                                                  MLX5_EXPANSION_OUTER_IPV6),
                .type = RTE_FLOW_ITEM_TYPE_VLAN,
+               .node_flags = MLX5_EXPANSION_NODE_EXPLICIT,
        },
        [MLX5_EXPANSION_OUTER_IPV4] = {
                .next = MLX5_FLOW_EXPAND_RSS_NEXT
@@ -505,19 +567,20 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
                         MLX5_EXPANSION_IPV4,
                         MLX5_EXPANSION_IPV6),
                .type = RTE_FLOW_ITEM_TYPE_IPV4,
-               .rss_types = ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4 |
-                       ETH_RSS_NONFRAG_IPV4_OTHER,
+               .rss_types = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 |
+                       RTE_ETH_RSS_NONFRAG_IPV4_OTHER,
        },
        [MLX5_EXPANSION_OUTER_IPV4_UDP] = {
                .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_VXLAN,
                                                  MLX5_EXPANSION_VXLAN_GPE,
-                                                 MLX5_EXPANSION_MPLS),
+                                                 MLX5_EXPANSION_MPLS,
+                                                 MLX5_EXPANSION_GTP),
                .type = RTE_FLOW_ITEM_TYPE_UDP,
-               .rss_types = ETH_RSS_NONFRAG_IPV4_UDP,
+               .rss_types = RTE_ETH_RSS_NONFRAG_IPV4_UDP,
        },
        [MLX5_EXPANSION_OUTER_IPV4_TCP] = {
                .type = RTE_FLOW_ITEM_TYPE_TCP,
-               .rss_types = ETH_RSS_NONFRAG_IPV4_TCP,
+               .rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
        },
        [MLX5_EXPANSION_OUTER_IPV6] = {
                .next = MLX5_FLOW_EXPAND_RSS_NEXT
@@ -528,19 +591,20 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
                         MLX5_EXPANSION_GRE,
                         MLX5_EXPANSION_NVGRE),
                .type = RTE_FLOW_ITEM_TYPE_IPV6,
-               .rss_types = ETH_RSS_IPV6 | ETH_RSS_FRAG_IPV6 |
-                       ETH_RSS_NONFRAG_IPV6_OTHER,
+               .rss_types = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 |
+                       RTE_ETH_RSS_NONFRAG_IPV6_OTHER,
        },
        [MLX5_EXPANSION_OUTER_IPV6_UDP] = {
                .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_VXLAN,
                                                  MLX5_EXPANSION_VXLAN_GPE,
-                                                 MLX5_EXPANSION_MPLS),
+                                                 MLX5_EXPANSION_MPLS,
+                                                 MLX5_EXPANSION_GTP),
                .type = RTE_FLOW_ITEM_TYPE_UDP,
-               .rss_types = ETH_RSS_NONFRAG_IPV6_UDP,
+               .rss_types = RTE_ETH_RSS_NONFRAG_IPV6_UDP,
        },
        [MLX5_EXPANSION_OUTER_IPV6_TCP] = {
                .type = RTE_FLOW_ITEM_TYPE_TCP,
-               .rss_types = ETH_RSS_NONFRAG_IPV6_TCP,
+               .rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
        },
        [MLX5_EXPANSION_VXLAN] = {
                .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH,
@@ -548,6 +612,15 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
                                                  MLX5_EXPANSION_IPV6),
                .type = RTE_FLOW_ITEM_TYPE_VXLAN,
        },
+       [MLX5_EXPANSION_STD_VXLAN] = {
+                       .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH),
+                                       .type = RTE_FLOW_ITEM_TYPE_VXLAN,
+       },
+       [MLX5_EXPANSION_L3_VXLAN] = {
+                       .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4,
+                                       MLX5_EXPANSION_IPV6),
+                                       .type = RTE_FLOW_ITEM_TYPE_VXLAN,
+       },
        [MLX5_EXPANSION_VXLAN_GPE] = {
                .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH,
                                                  MLX5_EXPANSION_IPV4,
@@ -566,7 +639,7 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
                                                  MLX5_EXPANSION_IPV6,
                                                  MLX5_EXPANSION_MPLS),
                .type = RTE_FLOW_ITEM_TYPE_GRE_KEY,
-               .optional = 1,
+               .node_flags = MLX5_EXPANSION_NODE_OPTIONAL,
        },
        [MLX5_EXPANSION_NVGRE] = {
                .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH),
@@ -577,13 +650,9 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
                                                  MLX5_EXPANSION_IPV6,
                                                  MLX5_EXPANSION_ETH),
                .type = RTE_FLOW_ITEM_TYPE_MPLS,
+               .node_flags = MLX5_EXPANSION_NODE_OPTIONAL,
        },
        [MLX5_EXPANSION_ETH] = {
-               .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4,
-                                                 MLX5_EXPANSION_IPV6),
-               .type = RTE_FLOW_ITEM_TYPE_ETH,
-       },
-       [MLX5_EXPANSION_ETH_VLAN] = {
                .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_VLAN),
                .type = RTE_FLOW_ITEM_TYPE_ETH,
        },
@@ -591,41 +660,47 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
                .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4,
                                                  MLX5_EXPANSION_IPV6),
                .type = RTE_FLOW_ITEM_TYPE_VLAN,
+               .node_flags = MLX5_EXPANSION_NODE_EXPLICIT,
        },
        [MLX5_EXPANSION_IPV4] = {
                .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4_UDP,
                                                  MLX5_EXPANSION_IPV4_TCP),
                .type = RTE_FLOW_ITEM_TYPE_IPV4,
-               .rss_types = ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4 |
-                       ETH_RSS_NONFRAG_IPV4_OTHER,
+               .rss_types = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 |
+                       RTE_ETH_RSS_NONFRAG_IPV4_OTHER,
        },
        [MLX5_EXPANSION_IPV4_UDP] = {
                .type = RTE_FLOW_ITEM_TYPE_UDP,
-               .rss_types = ETH_RSS_NONFRAG_IPV4_UDP,
+               .rss_types = RTE_ETH_RSS_NONFRAG_IPV4_UDP,
        },
        [MLX5_EXPANSION_IPV4_TCP] = {
                .type = RTE_FLOW_ITEM_TYPE_TCP,
-               .rss_types = ETH_RSS_NONFRAG_IPV4_TCP,
+               .rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
        },
        [MLX5_EXPANSION_IPV6] = {
                .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV6_UDP,
                                                  MLX5_EXPANSION_IPV6_TCP,
                                                  MLX5_EXPANSION_IPV6_FRAG_EXT),
                .type = RTE_FLOW_ITEM_TYPE_IPV6,
-               .rss_types = ETH_RSS_IPV6 | ETH_RSS_FRAG_IPV6 |
-                       ETH_RSS_NONFRAG_IPV6_OTHER,
+               .rss_types = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 |
+                       RTE_ETH_RSS_NONFRAG_IPV6_OTHER,
        },
        [MLX5_EXPANSION_IPV6_UDP] = {
                .type = RTE_FLOW_ITEM_TYPE_UDP,
-               .rss_types = ETH_RSS_NONFRAG_IPV6_UDP,
+               .rss_types = RTE_ETH_RSS_NONFRAG_IPV6_UDP,
        },
        [MLX5_EXPANSION_IPV6_TCP] = {
                .type = RTE_FLOW_ITEM_TYPE_TCP,
-               .rss_types = ETH_RSS_NONFRAG_IPV6_TCP,
+               .rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
        },
        [MLX5_EXPANSION_IPV6_FRAG_EXT] = {
                .type = RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT,
        },
+       [MLX5_EXPANSION_GTP] = {
+               .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4,
+                                                 MLX5_EXPANSION_IPV6),
+               .type = RTE_FLOW_ITEM_TYPE_GTP,
+       },
 };
 
 static struct rte_flow_action_handle *
@@ -846,7 +921,7 @@ mlx5_flow_get_reg_id(struct rte_eth_dev *dev,
                        return rte_flow_error_set(error, EINVAL,
                                                  RTE_FLOW_ERROR_TYPE_ITEM,
                                                  NULL, "invalid tag id");
-               if (config->flow_mreg_c[id + start_reg - REG_C_0] == REG_NON)
+               if (priv->sh->flow_mreg_c[id + start_reg - REG_C_0] == REG_NON)
                        return rte_flow_error_set(error, ENOTSUP,
                                                  RTE_FLOW_ERROR_TYPE_ITEM,
                                                  NULL, "unsupported tag id");
@@ -856,21 +931,21 @@ mlx5_flow_get_reg_id(struct rte_eth_dev *dev,
                 * If the available index REG_C_y >= REG_C_x, skip the
                 * color register.
                 */
-               if (skip_mtr_reg && config->flow_mreg_c
+               if (skip_mtr_reg && priv->sh->flow_mreg_c
                    [id + start_reg - REG_C_0] >= priv->mtr_color_reg) {
                        if (id >= (uint32_t)(REG_C_7 - start_reg))
                                return rte_flow_error_set(error, EINVAL,
                                                       RTE_FLOW_ERROR_TYPE_ITEM,
                                                        NULL, "invalid tag id");
-                       if (config->flow_mreg_c
+                       if (priv->sh->flow_mreg_c
                            [id + 1 + start_reg - REG_C_0] != REG_NON)
-                               return config->flow_mreg_c
+                               return priv->sh->flow_mreg_c
                                               [id + 1 + start_reg - REG_C_0];
                        return rte_flow_error_set(error, ENOTSUP,
                                                  RTE_FLOW_ERROR_TYPE_ITEM,
                                                  NULL, "unsupported tag id");
                }
-               return config->flow_mreg_c[id + start_reg - REG_C_0];
+               return priv->sh->flow_mreg_c[id + start_reg - REG_C_0];
        }
        MLX5_ASSERT(false);
        return rte_flow_error_set(error, EINVAL,
@@ -891,7 +966,6 @@ bool
 mlx5_flow_ext_mreg_supported(struct rte_eth_dev *dev)
 {
        struct mlx5_priv *priv = dev->data->dev_private;
-       struct mlx5_dev_config *config = &priv->config;
 
        /*
         * Having available reg_c can be regarded inclusively as supporting
@@ -901,7 +975,7 @@ mlx5_flow_ext_mreg_supported(struct rte_eth_dev *dev)
         * - reg_c's are preserved across different domain (FDB and NIC) on
         *   packet loopback by flow lookup miss.
         */
-       return config->flow_mreg_c[2] != REG_NON;
+       return priv->sh->flow_mreg_c[2] != REG_NON;
 }
 
 /**
@@ -922,7 +996,7 @@ mlx5_get_lowest_priority(struct rte_eth_dev *dev,
        struct mlx5_priv *priv = dev->data->dev_private;
 
        if (!attr->group && !attr->transfer)
-               return priv->config.flow_prio - 2;
+               return priv->sh->flow_max_priority - 2;
        return MLX5_NON_ROOT_FLOW_MAX_PRIO - 1;
 }
 
@@ -935,21 +1009,26 @@ mlx5_get_lowest_priority(struct rte_eth_dev *dev,
  *   Pointer to device flow rule attributes.
  * @param[in] subpriority
  *   The priority based on the items.
+ * @param[in] external
+ *   Flow is user flow.
  * @return
  *   The matcher priority of the flow.
  */
 uint16_t
 mlx5_get_matcher_priority(struct rte_eth_dev *dev,
                          const struct rte_flow_attr *attr,
-                         uint32_t subpriority)
+                         uint32_t subpriority, bool external)
 {
        uint16_t priority = (uint16_t)attr->priority;
        struct mlx5_priv *priv = dev->data->dev_private;
 
        if (!attr->group && !attr->transfer) {
                if (attr->priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR)
-                       priority = priv->config.flow_prio - 1;
+                       priority = priv->sh->flow_max_priority - 1;
                return mlx5_os_flow_adjust_priority(dev, priority, subpriority);
+       } else if (!external && attr->transfer && attr->group == 0 &&
+                  attr->priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR) {
+               return (priv->sh->flow_max_priority - 1) * 3;
        }
        if (attr->priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR)
                priority = MLX5_NON_ROOT_FLOW_MAX_PRIO;
@@ -1027,7 +1106,7 @@ mlx5_flow_item_acceptable(const struct rte_flow_item *item,
  * @param[in] tunnel
  *   1 when the hash field is for a tunnel item.
  * @param[in] layer_types
- *   ETH_RSS_* types.
+ *   RTE_ETH_RSS_* types.
  * @param[in] hash_fields
  *   Item hash fields.
  *
@@ -1321,9 +1400,7 @@ mlx5_flow_rxq_dynf_metadata_set(struct rte_eth_dev *dev)
                        data->dynf_meta = 1;
                        data->flow_meta_mask = rte_flow_dynf_metadata_mask;
                        data->flow_meta_offset = rte_flow_dynf_metadata_offs;
-                       data->flow_meta_port_mask = (uint32_t)~0;
-                       if (priv->config.dv_xmeta_en == MLX5_XMETA_MODE_META16)
-                               data->flow_meta_port_mask >>= 16;
+                       data->flow_meta_port_mask = priv->sh->dv_meta_mask;
                }
        }
 }
@@ -1517,6 +1594,58 @@ mlx5_flow_validate_action_queue(const struct rte_flow_action *action,
        return 0;
 }
 
+/**
+ * Validate queue numbers for device RSS.
+ *
+ * @param[in] dev
+ *   Configured device.
+ * @param[in] queues
+ *   Array of queue numbers.
+ * @param[in] queues_n
+ *   Size of the @p queues array.
+ * @param[out] error
+ *   On error, filled with a textual error description.
+ * @param[out] queue
+ *   On error, filled with an offending queue index in @p queues array.
+ *
+ * @return
+ *   0 on success, a negative errno code on error.
+ */
+static int
+mlx5_validate_rss_queues(const struct rte_eth_dev *dev,
+                        const uint16_t *queues, uint32_t queues_n,
+                        const char **error, uint32_t *queue_idx)
+{
+       const struct mlx5_priv *priv = dev->data->dev_private;
+       enum mlx5_rxq_type rxq_type = MLX5_RXQ_TYPE_UNDEFINED;
+       uint32_t i;
+
+       for (i = 0; i != queues_n; ++i) {
+               struct mlx5_rxq_ctrl *rxq_ctrl;
+
+               if (queues[i] >= priv->rxqs_n) {
+                       *error = "queue index out of range";
+                       *queue_idx = i;
+                       return -EINVAL;
+               }
+               if (!(*priv->rxqs)[queues[i]]) {
+                       *error =  "queue is not configured";
+                       *queue_idx = i;
+                       return -EINVAL;
+               }
+               rxq_ctrl = container_of((*priv->rxqs)[queues[i]],
+                                       struct mlx5_rxq_ctrl, rxq);
+               if (i == 0)
+                       rxq_type = rxq_ctrl->type;
+               if (rxq_type != rxq_ctrl->type) {
+                       *error = "combining hairpin and regular RSS queues is not supported";
+                       *queue_idx = i;
+                       return -ENOTSUP;
+               }
+       }
+       return 0;
+}
+
 /*
  * Validate the rss action.
  *
@@ -1537,8 +1666,9 @@ mlx5_validate_action_rss(struct rte_eth_dev *dev,
 {
        struct mlx5_priv *priv = dev->data->dev_private;
        const struct rte_flow_action_rss *rss = action->conf;
-       enum mlx5_rxq_type rxq_type = MLX5_RXQ_TYPE_UNDEFINED;
-       unsigned int i;
+       int ret;
+       const char *message;
+       uint32_t queue_idx;
 
        if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT &&
            rss->func != RTE_ETH_HASH_FUNCTION_TOEPLITZ)
@@ -1582,14 +1712,14 @@ mlx5_validate_action_rss(struct rte_eth_dev *dev,
                                          &rss->types,
                                          "some RSS protocols are not"
                                          " supported");
-       if ((rss->types & (ETH_RSS_L3_SRC_ONLY | ETH_RSS_L3_DST_ONLY)) &&
-           !(rss->types & ETH_RSS_IP))
+       if ((rss->types & (RTE_ETH_RSS_L3_SRC_ONLY | RTE_ETH_RSS_L3_DST_ONLY)) &&
+           !(rss->types & RTE_ETH_RSS_IP))
                return rte_flow_error_set(error, EINVAL,
                                          RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
                                          "L3 partial RSS requested but L3 RSS"
                                          " type not specified");
-       if ((rss->types & (ETH_RSS_L4_SRC_ONLY | ETH_RSS_L4_DST_ONLY)) &&
-           !(rss->types & (ETH_RSS_UDP | ETH_RSS_TCP)))
+       if ((rss->types & (RTE_ETH_RSS_L4_SRC_ONLY | RTE_ETH_RSS_L4_DST_ONLY)) &&
+           !(rss->types & (RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP)))
                return rte_flow_error_set(error, EINVAL,
                                          RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
                                          "L4 partial RSS requested but L4 RSS"
@@ -1602,27 +1732,12 @@ mlx5_validate_action_rss(struct rte_eth_dev *dev,
                return rte_flow_error_set(error, EINVAL,
                                          RTE_FLOW_ERROR_TYPE_ACTION_CONF,
                                          NULL, "No queues configured");
-       for (i = 0; i != rss->queue_num; ++i) {
-               struct mlx5_rxq_ctrl *rxq_ctrl;
-
-               if (rss->queue[i] >= priv->rxqs_n)
-                       return rte_flow_error_set
-                               (error, EINVAL,
-                                RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-                                &rss->queue[i], "queue index out of range");
-               if (!(*priv->rxqs)[rss->queue[i]])
-                       return rte_flow_error_set
-                               (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-                                &rss->queue[i], "queue is not configured");
-               rxq_ctrl = container_of((*priv->rxqs)[rss->queue[i]],
-                                       struct mlx5_rxq_ctrl, rxq);
-               if (i == 0)
-                       rxq_type = rxq_ctrl->type;
-               if (rxq_type != rxq_ctrl->type)
-                       return rte_flow_error_set
-                               (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-                                &rss->queue[i],
-                                "combining hairpin and regular RSS queues is not supported");
+       ret = mlx5_validate_rss_queues(dev, rss->queue, rss->queue_num,
+                                      &message, &queue_idx);
+       if (ret != 0) {
+               return rte_flow_error_set(error, -ret,
+                                         RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+                                         &rss->queue[queue_idx], message);
        }
        return 0;
 }
@@ -1806,7 +1921,7 @@ mlx5_flow_validate_attributes(struct rte_eth_dev *dev,
                              struct rte_flow_error *error)
 {
        struct mlx5_priv *priv = dev->data->dev_private;
-       uint32_t priority_max = priv->config.flow_prio - 1;
+       uint32_t priority_max = priv->sh->flow_max_priority - 1;
 
        if (attributes->group)
                return rte_flow_error_set(error, ENOTSUP,
@@ -1992,6 +2107,10 @@ mlx5_flow_validate_item_eth(const struct rte_flow_item *item,
                return rte_flow_error_set(error, EINVAL,
                                          RTE_FLOW_ERROR_TYPE_ITEM, item,
                                          "L2 layer should not follow VLAN");
+       if (item_flags & MLX5_FLOW_LAYER_GTP)
+               return rte_flow_error_set(error, EINVAL,
+                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
+                                         "L2 layer should not follow GTP");
        if (!mask)
                mask = &rte_flow_item_eth_mask;
        ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
@@ -2420,6 +2539,8 @@ mlx5_flow_validate_item_tcp(const struct rte_flow_item *item,
  *
  * @param[in] dev
  *   Pointer to the Ethernet device structure.
+ * @param[in] udp_dport
+ *   UDP destination port
  * @param[in] item
  *   Item specification.
  * @param[in] item_flags
@@ -2434,6 +2555,7 @@ mlx5_flow_validate_item_tcp(const struct rte_flow_item *item,
  */
 int
 mlx5_flow_validate_item_vxlan(struct rte_eth_dev *dev,
+                             uint16_t udp_dport,
                              const struct rte_flow_item *item,
                              uint64_t item_flags,
                              const struct rte_flow_attr *attr,
@@ -2469,12 +2591,18 @@ mlx5_flow_validate_item_vxlan(struct rte_eth_dev *dev,
                                          "no outer UDP layer found");
        if (!mask)
                mask = &rte_flow_item_vxlan_mask;
-       /* FDB domain & NIC domain non-zero group */
-       if ((attr->transfer || attr->group) && priv->sh->misc5_cap)
-               valid_mask = &nic_mask;
-       /* Group zero in NIC domain */
-       if (!attr->group && !attr->transfer && priv->sh->tunnel_header_0_1)
-               valid_mask = &nic_mask;
+
+       if (priv->sh->steering_format_version !=
+           MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 ||
+           !udp_dport || udp_dport == MLX5_UDP_PORT_VXLAN) {
+               /* FDB domain & NIC domain non-zero group */
+               if ((attr->transfer || attr->group) && priv->sh->misc5_cap)
+                       valid_mask = &nic_mask;
+               /* Group zero in NIC domain */
+               if (!attr->group && !attr->transfer &&
+                   priv->sh->tunnel_header_0_1)
+                       valid_mask = &nic_mask;
+       }
        ret = mlx5_flow_item_acceptable
                (item, (const uint8_t *)mask,
                 (const uint8_t *)valid_mask,
@@ -3515,6 +3643,8 @@ flow_get_rss_action(struct rte_eth_dev *dev,
 {
        struct mlx5_priv *priv = dev->data->dev_private;
        const struct rte_flow_action_rss *rss = NULL;
+       struct mlx5_meter_policy_action_container *acg;
+       struct mlx5_meter_policy_action_container *acy;
 
        for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
                switch (actions->type) {
@@ -3550,9 +3680,18 @@ flow_get_rss_action(struct rte_eth_dev *dev,
                                        if (!policy)
                                                return NULL;
                                }
-                               if (policy->is_rss)
-                                       rss =
-                               policy->act_cnt[RTE_COLOR_GREEN].rss->conf;
+                               if (policy->is_rss) {
+                                       acg =
+                                       &policy->act_cnt[RTE_COLOR_GREEN];
+                                       acy =
+                                       &policy->act_cnt[RTE_COLOR_YELLOW];
+                                       if (acg->fate_action ==
+                                           MLX5_FLOW_FATE_SHARED_RSS)
+                                               rss = acg->rss->conf;
+                                       else if (acy->fate_action ==
+                                                MLX5_FLOW_FATE_SHARED_RSS)
+                                               rss = acy->rss->conf;
+                               }
                        }
                        break;
                }
@@ -3581,8 +3720,11 @@ flow_aso_age_get_by_idx(struct rte_eth_dev *dev, uint32_t age_idx)
        uint16_t offset = (age_idx >> 16) & UINT16_MAX;
        struct mlx5_priv *priv = dev->data->dev_private;
        struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng;
-       struct mlx5_aso_age_pool *pool = mng->pools[pool_idx];
+       struct mlx5_aso_age_pool *pool;
 
+       rte_rwlock_read_lock(&mng->resize_rwl);
+       pool = mng->pools[pool_idx];
+       rte_rwlock_read_unlock(&mng->resize_rwl);
        return &pool->actions[offset - 1];
 }
 
@@ -3753,20 +3895,8 @@ flow_get_shared_rss_action(struct rte_eth_dev *dev,
 }
 
 static unsigned int
-find_graph_root(const struct rte_flow_item pattern[], uint32_t rss_level)
+find_graph_root(uint32_t rss_level)
 {
-       const struct rte_flow_item *item;
-       unsigned int has_vlan = 0;
-
-       for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
-               if (item->type == RTE_FLOW_ITEM_TYPE_VLAN) {
-                       has_vlan = 1;
-                       break;
-               }
-       }
-       if (has_vlan)
-               return rss_level < 2 ? MLX5_EXPANSION_ROOT_ETH_VLAN :
-                                      MLX5_EXPANSION_ROOT_OUTER_ETH_VLAN;
        return rss_level < 2 ? MLX5_EXPANSION_ROOT :
                               MLX5_EXPANSION_ROOT_OUTER;
 }
@@ -4698,7 +4828,7 @@ get_meter_sub_policy(struct rte_eth_dev *dev,
                        uint8_t fate = final_policy->act_cnt[i].fate_action;
 
                        if (fate == MLX5_FLOW_FATE_SHARED_RSS) {
-                               const void *rss_act =
+                               const struct rte_flow_action_rss *rss_act =
                                        final_policy->act_cnt[i].rss->conf;
                                struct rte_flow_action rss_actions[2] = {
                                        [0] = {
@@ -4734,6 +4864,9 @@ get_meter_sub_policy(struct rte_eth_dev *dev,
                                rss_desc_v[i].tunnel =
                                                !!(dev_flow.handle->layers &
                                                   MLX5_FLOW_LAYER_TUNNEL);
+                               /* Use the RSS queues in the containers. */
+                               rss_desc_v[i].queue =
+                                       (uint16_t *)(uintptr_t)rss_act->queue;
                                rss_desc[i] = &rss_desc_v[i];
                        } else if (fate == MLX5_FLOW_FATE_QUEUE) {
                                /* This is queue action. */
@@ -5248,6 +5381,7 @@ flow_check_match_action(const struct rte_flow_action actions[],
                        int *modify_after_mirror)
 {
        const struct rte_flow_action_sample *sample;
+       const struct rte_flow_action_raw_decap *decap;
        int actions_n = 0;
        uint32_t ratio = 0;
        int sub_type = 0;
@@ -5300,12 +5434,29 @@ flow_check_match_action(const struct rte_flow_action actions[],
                case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
                case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
                case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
-               case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
                case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
                case RTE_FLOW_ACTION_TYPE_METER:
                        if (fdb_mirror)
                                *modify_after_mirror = 1;
                        break;
+               case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+                       decap = actions->conf;
+                       while ((++actions)->type == RTE_FLOW_ACTION_TYPE_VOID)
+                               ;
+                       actions_n++;
+                       if (actions->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
+                               const struct rte_flow_action_raw_encap *encap =
+                                                               actions->conf;
+                               if (decap->size <=
+                                       MLX5_ENCAPSULATION_DECISION_SIZE &&
+                                   encap->size >
+                                       MLX5_ENCAPSULATION_DECISION_SIZE)
+                                       /* L3 encap. */
+                                       break;
+                       }
+                       if (fdb_mirror)
+                               *modify_after_mirror = 1;
+                       break;
                default:
                        break;
                }
@@ -6239,7 +6390,7 @@ flow_list_create(struct rte_eth_dev *dev, enum mlx5_flow_type type,
        int indir_actions_n = MLX5_MAX_INDIRECT_ACTIONS;
        union {
                struct mlx5_flow_expand_rss buf;
-               uint8_t buffer[2048];
+               uint8_t buffer[4096];
        } expand_buffer;
        union {
                struct rte_flow_action actions[MLX5_MAX_SPLIT_ACTIONS];
@@ -6323,14 +6474,14 @@ flow_list_create(struct rte_eth_dev *dev, enum mlx5_flow_type type,
                 * mlx5_flow_hashfields_adjust() in advance.
                 */
                rss_desc->level = rss->level;
-               /* RSS type 0 indicates default RSS type (ETH_RSS_IP). */
-               rss_desc->types = !rss->types ? ETH_RSS_IP : rss->types;
+               /* RSS type 0 indicates default RSS type (RTE_ETH_RSS_IP). */
+               rss_desc->types = !rss->types ? RTE_ETH_RSS_IP : rss->types;
        }
        flow->dev_handles = 0;
        if (rss && rss->types) {
                unsigned int graph_root;
 
-               graph_root = find_graph_root(items, rss->level);
+               graph_root = find_graph_root(rss->level);
                ret = mlx5_flow_expand_rss(buf, sizeof(expand_buffer.buffer),
                                           items, rss->types,
                                           mlx5_support_expansion, graph_root);
@@ -6503,6 +6654,80 @@ mlx5_flow_create_esw_table_zero_flow(struct rte_eth_dev *dev)
                                                   actions, false, &error);
 }
 
+/**
+ * Create a dedicated flow rule on e-switch table 1, matches ESW manager
+ * and sq number, directs all packets to peer vport.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ * @param txq
+ *   Txq index.
+ *
+ * @return
+ *   Flow ID on success, 0 otherwise and rte_errno is set.
+ */
+uint32_t
+mlx5_flow_create_devx_sq_miss_flow(struct rte_eth_dev *dev, uint32_t txq)
+{
+       struct rte_flow_attr attr = {
+               .group = 0,
+               .priority = MLX5_FLOW_LOWEST_PRIO_INDICATOR,
+               .ingress = 1,
+               .egress = 0,
+               .transfer = 1,
+       };
+       struct rte_flow_item_port_id port_spec = {
+               .id = MLX5_PORT_ESW_MGR,
+       };
+       struct mlx5_rte_flow_item_tx_queue txq_spec = {
+               .queue = txq,
+       };
+       struct rte_flow_item pattern[] = {
+               {
+                       .type = RTE_FLOW_ITEM_TYPE_PORT_ID,
+                       .spec = &port_spec,
+               },
+               {
+                       .type = (enum rte_flow_item_type)
+                               MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE,
+                       .spec = &txq_spec,
+               },
+               {
+                       .type = RTE_FLOW_ITEM_TYPE_END,
+               },
+       };
+       struct rte_flow_action_jump jump = {
+               .group = 1,
+       };
+       struct rte_flow_action_port_id port = {
+               .id = dev->data->port_id,
+       };
+       struct rte_flow_action actions[] = {
+               {
+                       .type = RTE_FLOW_ACTION_TYPE_JUMP,
+                       .conf = &jump,
+               },
+               {
+                       .type = RTE_FLOW_ACTION_TYPE_END,
+               },
+       };
+       struct rte_flow_error error;
+
+       /*
+        * Creates group 0, highest priority jump flow.
+        * Matches txq to bypass kernel packets.
+        */
+       if (flow_list_create(dev, MLX5_FLOW_TYPE_CTL, &attr, pattern, actions,
+                            false, &error) == 0)
+               return 0;
+       /* Create group 1, lowest priority redirect flow for txq. */
+       attr.group = 1;
+       actions[0].conf = &port;
+       actions[0].type = RTE_FLOW_ACTION_TYPE_PORT_ID;
+       return flow_list_create(dev, MLX5_FLOW_TYPE_CTL, &attr, pattern,
+                               actions, false, &error);
+}
+
 /**
  * Validate a flow supported by the NIC.
  *
@@ -6948,7 +7173,7 @@ mlx5_ctrl_flow_vlan(struct rte_eth_dev *dev,
        if (!priv->reta_idx_n || !priv->rxqs_n) {
                return 0;
        }
-       if (!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG))
+       if (!(dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG))
                action_rss.types = 0;
        for (i = 0; i != priv->reta_idx_n; ++i)
                queue[i] = (*priv->reta_idx)[i];
@@ -7563,7 +7788,7 @@ mlx5_flow_create_counter_stat_mem_mng(struct mlx5_dev_ctx_shared *sh)
        }
        mem_mng = (struct mlx5_counter_stats_mem_mng *)(mem + size) - 1;
        size = sizeof(*raw_data) * MLX5_COUNTERS_PER_POOL * raws_n;
-       mem_mng->umem = mlx5_os_umem_reg(sh->ctx, mem, size,
+       mem_mng->umem = mlx5_os_umem_reg(sh->cdev->ctx, mem, size,
                                                 IBV_ACCESS_LOCAL_WRITE);
        if (!mem_mng->umem) {
                rte_errno = errno;
@@ -7574,10 +7799,10 @@ mlx5_flow_create_counter_stat_mem_mng(struct mlx5_dev_ctx_shared *sh)
        mkey_attr.addr = (uintptr_t)mem;
        mkey_attr.size = size;
        mkey_attr.umem_id = mlx5_os_get_umem_id(mem_mng->umem);
-       mkey_attr.pd = sh->pdn;
+       mkey_attr.pd = sh->cdev->pdn;
        mkey_attr.relaxed_ordering_write = sh->cmng.relaxed_ordering_write;
        mkey_attr.relaxed_ordering_read = sh->cmng.relaxed_ordering_read;
-       mem_mng->dm = mlx5_devx_cmd_mkey_create(sh->ctx, &mkey_attr);
+       mem_mng->dm = mlx5_devx_cmd_mkey_create(sh->cdev->ctx, &mkey_attr);
        if (!mem_mng->dm) {
                mlx5_os_umem_dereg(mem_mng->umem);
                rte_errno = errno;
@@ -7934,13 +8159,12 @@ int
 mlx5_flow_discover_mreg_c(struct rte_eth_dev *dev)
 {
        struct mlx5_priv *priv = dev->data->dev_private;
-       struct mlx5_dev_config *config = &priv->config;
        enum modify_reg idx;
        int n = 0;
 
        /* reg_c[0] and reg_c[1] are reserved. */
-       config->flow_mreg_c[n++] = REG_C_0;
-       config->flow_mreg_c[n++] = REG_C_1;
+       priv->sh->flow_mreg_c[n++] = REG_C_0;
+       priv->sh->flow_mreg_c[n++] = REG_C_1;
        /* Discover availability of other reg_c's. */
        for (idx = REG_C_2; idx <= REG_C_7; ++idx) {
                struct rte_flow_attr attr = {
@@ -7976,7 +8200,7 @@ mlx5_flow_discover_mreg_c(struct rte_eth_dev *dev)
                struct rte_flow *flow;
                struct rte_flow_error error;
 
-               if (!config->dv_flow_en)
+               if (!priv->config.dv_flow_en)
                        break;
                /* Create internal flow, validation skips copy action. */
                flow_idx = flow_list_create(dev, MLX5_FLOW_TYPE_GEN, &attr,
@@ -7985,17 +8209,18 @@ mlx5_flow_discover_mreg_c(struct rte_eth_dev *dev)
                                      flow_idx);
                if (!flow)
                        continue;
-               config->flow_mreg_c[n++] = idx;
+               priv->sh->flow_mreg_c[n++] = idx;
                flow_list_destroy(dev, MLX5_FLOW_TYPE_GEN, flow_idx);
        }
        for (; n < MLX5_MREG_C_NUM; ++n)
-               config->flow_mreg_c[n] = REG_NON;
+               priv->sh->flow_mreg_c[n] = REG_NON;
+       priv->sh->metadata_regc_check_flag = 1;
        return 0;
 }
 
 int
 save_dump_file(const uint8_t *data, uint32_t size,
-       uint32_t type, uint32_t id, void *arg, FILE *file)
+       uint32_t type, uint64_t id, void *arg, FILE *file)
 {
        char line[BUF_SIZE];
        uint32_t out = 0;
@@ -8007,17 +8232,18 @@ save_dump_file(const uint8_t *data, uint32_t size,
        switch (type) {
        case DR_DUMP_REC_TYPE_PMD_MODIFY_HDR:
                actions_num = *(uint32_t *)(arg);
-               out += snprintf(line + out, BUF_SIZE - out, "%d,0x%x,%d,",
+               out += snprintf(line + out, BUF_SIZE - out, "%d,0x%" PRIx64 ",%d,",
                                type, id, actions_num);
                break;
        case DR_DUMP_REC_TYPE_PMD_PKT_REFORMAT:
-               out += snprintf(line + out, BUF_SIZE - out, "%d,0x%x,",
+               out += snprintf(line + out, BUF_SIZE - out, "%d,0x%" PRIx64 ",",
                                type, id);
                break;
        case DR_DUMP_REC_TYPE_PMD_COUNTER:
                count = (struct rte_flow_query_count *)arg;
-               fprintf(file, "%d,0x%x,%" PRIu64 ",%" PRIu64 "\n", type,
-                               id, count->hits, count->bytes);
+               fprintf(file,
+                       "%d,0x%" PRIx64 ",%" PRIu64 ",%" PRIu64 "\n",
+                       type, id, count->hits, count->bytes);
                return 0;
        default:
                return -1;
@@ -8091,30 +8317,34 @@ mlx5_flow_dev_dump_ipool(struct rte_eth_dev *dev,
        uint32_t actions_num;
        const uint8_t *data;
        size_t size;
-       uint32_t id;
+       uint64_t id;
        uint32_t type;
+       void *action = NULL;
 
        if (!flow) {
                return rte_flow_error_set(error, ENOENT,
-                       RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-                       NULL,
-                       "invalid flow handle");
+                               RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+                               NULL,
+                               "invalid flow handle");
        }
        handle_idx = flow->dev_handles;
        while (handle_idx) {
                dh = mlx5_ipool_get(priv->sh->ipool
-                       [MLX5_IPOOL_MLX5_FLOW], handle_idx);
+                               [MLX5_IPOOL_MLX5_FLOW], handle_idx);
                if (!dh)
                        continue;
                handle_idx = dh->next.next;
-               id = (uint32_t)(uintptr_t)dh->drv_flow;
 
                /* query counter */
                type = DR_DUMP_REC_TYPE_PMD_COUNTER;
-               if (!mlx5_flow_query_counter(dev, flow, &count, error))
-                       save_dump_file(NULL, 0, type,
-                                       id, (void *)&count, file);
-
+               flow_dv_query_count_ptr(dev, flow->counter,
+                                               &action, error);
+               if (action) {
+                       id = (uint64_t)(uintptr_t)action;
+                       if (!mlx5_flow_query_counter(dev, flow, &count, error))
+                               save_dump_file(NULL, 0, type,
+                                               id, (void *)&count, file);
+               }
                /* Get modify_hdr and encap_decap buf from ipools. */
                encap_decap = NULL;
                modify_hdr = dh->dvh.modify_hdr;
@@ -8127,14 +8357,16 @@ mlx5_flow_dev_dump_ipool(struct rte_eth_dev *dev,
                if (modify_hdr) {
                        data = (const uint8_t *)modify_hdr->actions;
                        size = (size_t)(modify_hdr->actions_num) * 8;
+                       id = (uint64_t)(uintptr_t)modify_hdr->action;
                        actions_num = modify_hdr->actions_num;
                        type = DR_DUMP_REC_TYPE_PMD_MODIFY_HDR;
                        save_dump_file(data, size, type, id,
-                                       (void *)(&actions_num), file);
+                                               (void *)(&actions_num), file);
                }
                if (encap_decap) {
                        data = encap_decap->buf;
                        size = encap_decap->size;
+                       id = (uint64_t)(uintptr_t)encap_decap->action;
                        type = DR_DUMP_REC_TYPE_PMD_PKT_REFORMAT;
                        save_dump_file(data, size, type,
                                                id, NULL, file);
@@ -8142,6 +8374,119 @@ mlx5_flow_dev_dump_ipool(struct rte_eth_dev *dev,
        }
        return 0;
 }
+
+/**
+ * Dump all flow's encap_decap/modify_hdr/counter data to file
+ *
+ * @param[in] dev
+ *   The pointer to Ethernet device.
+ * @param[in] file
+ *   A pointer to a file for output.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+static int
+mlx5_flow_dev_dump_sh_all(struct rte_eth_dev *dev,
+       FILE *file, struct rte_flow_error *error)
+{
+       struct mlx5_priv *priv = dev->data->dev_private;
+       struct mlx5_dev_ctx_shared *sh = priv->sh;
+       struct mlx5_hlist *h;
+       struct mlx5_flow_dv_modify_hdr_resource  *modify_hdr;
+       struct mlx5_flow_dv_encap_decap_resource *encap_decap;
+       struct rte_flow_query_count count;
+       uint32_t actions_num;
+       const uint8_t *data;
+       size_t size;
+       uint64_t id;
+       uint32_t type;
+       uint32_t i;
+       uint32_t j;
+       struct mlx5_list_inconst *l_inconst;
+       struct mlx5_list_entry *e;
+       int lcore_index;
+       struct mlx5_flow_counter_mng *cmng = &priv->sh->cmng;
+       uint32_t max;
+       void *action;
+
+       /* encap_decap hlist is lcore_share, get global core cache. */
+       i = MLX5_LIST_GLOBAL;
+       h = sh->encaps_decaps;
+       if (h) {
+               for (j = 0; j <= h->mask; j++) {
+                       l_inconst = &h->buckets[j].l;
+                       if (!l_inconst || !l_inconst->cache[i])
+                               continue;
+
+                       e = LIST_FIRST(&l_inconst->cache[i]->h);
+                       while (e) {
+                               encap_decap =
+                               (struct mlx5_flow_dv_encap_decap_resource *)e;
+                               data = encap_decap->buf;
+                               size = encap_decap->size;
+                               id = (uint64_t)(uintptr_t)encap_decap->action;
+                               type = DR_DUMP_REC_TYPE_PMD_PKT_REFORMAT;
+                               save_dump_file(data, size, type,
+                                       id, NULL, file);
+                               e = LIST_NEXT(e, next);
+                       }
+               }
+       }
+
+       /* get modify_hdr */
+       h = sh->modify_cmds;
+       if (h) {
+               lcore_index = rte_lcore_index(rte_lcore_id());
+               if (unlikely(lcore_index == -1)) {
+                       lcore_index = MLX5_LIST_NLCORE;
+                       rte_spinlock_lock(&h->l_const.lcore_lock);
+               }
+               i = lcore_index;
+
+               for (j = 0; j <= h->mask; j++) {
+                       l_inconst = &h->buckets[j].l;
+                       if (!l_inconst || !l_inconst->cache[i])
+                               continue;
+
+                       e = LIST_FIRST(&l_inconst->cache[i]->h);
+                       while (e) {
+                               modify_hdr =
+                               (struct mlx5_flow_dv_modify_hdr_resource *)e;
+                               data = (const uint8_t *)modify_hdr->actions;
+                               size = (size_t)(modify_hdr->actions_num) * 8;
+                               actions_num = modify_hdr->actions_num;
+                               id = (uint64_t)(uintptr_t)modify_hdr->action;
+                               type = DR_DUMP_REC_TYPE_PMD_MODIFY_HDR;
+                               save_dump_file(data, size, type, id,
+                                               (void *)(&actions_num), file);
+                               e = LIST_NEXT(e, next);
+                       }
+               }
+
+               if (unlikely(lcore_index == MLX5_LIST_NLCORE))
+                       rte_spinlock_unlock(&h->l_const.lcore_lock);
+       }
+
+       /* get counter */
+       MLX5_ASSERT(cmng->n_valid <= cmng->n);
+       max = MLX5_COUNTERS_PER_POOL * cmng->n_valid;
+       for (j = 1; j <= max; j++) {
+               action = NULL;
+               flow_dv_query_count_ptr(dev, j, &action, error);
+               if (action) {
+                       if (!flow_dv_query_count(dev, j, &count, error)) {
+                               type = DR_DUMP_REC_TYPE_PMD_COUNTER;
+                               id = (uint64_t)(uintptr_t)action;
+                               save_dump_file(NULL, 0, type,
+                                               id, (void *)&count, file);
+                       }
+               }
+       }
+       return 0;
+}
 #endif
 
 /**
@@ -8168,9 +8513,6 @@ mlx5_flow_dev_dump(struct rte_eth_dev *dev, struct rte_flow *flow_idx,
        int ret;
        struct mlx5_flow_handle *dh;
        struct rte_flow *flow;
-#ifdef HAVE_IBV_FLOW_DV_SUPPORT
-       uint32_t idx;
-#endif
 
        if (!priv->config.dv_flow_en) {
                if (fputs("device dv flow disabled\n", file) <= 0)
@@ -8181,8 +8523,8 @@ mlx5_flow_dev_dump(struct rte_eth_dev *dev, struct rte_flow *flow_idx,
        /* dump all */
        if (!flow_idx) {
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
-               MLX5_IPOOL_FOREACH(priv->flows[MLX5_FLOW_TYPE_GEN], idx, flow)
-                       mlx5_flow_dev_dump_ipool(dev, flow, file, error);
+               if (mlx5_flow_dev_dump_sh_all(dev, file, error))
+                       return -EINVAL;
 #endif
                return mlx5_devx_cmd_flow_dump(sh->fdb_domain,
                                        sh->rx_domain,
@@ -8192,7 +8534,7 @@ mlx5_flow_dev_dump(struct rte_eth_dev *dev, struct rte_flow *flow_idx,
        flow = mlx5_ipool_get(priv->flows[MLX5_FLOW_TYPE_GEN],
                        (uintptr_t)(void *)flow_idx);
        if (!flow)
-               return -ENOENT;
+               return -EINVAL;
 
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
        mlx5_flow_dev_dump_ipool(dev, flow, file, error);
@@ -8482,6 +8824,116 @@ mlx5_action_handle_flush(struct rte_eth_dev *dev)
        return ret;
 }
 
+/**
+ * Validate existing indirect actions against current device configuration
+ * and attach them to device resources.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_action_handle_attach(struct rte_eth_dev *dev)
+{
+       struct mlx5_priv *priv = dev->data->dev_private;
+       struct mlx5_indexed_pool *ipool =
+                       priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS];
+       struct mlx5_shared_action_rss *shared_rss, *shared_rss_last;
+       int ret = 0;
+       uint32_t idx;
+
+       ILIST_FOREACH(ipool, priv->rss_shared_actions, idx, shared_rss, next) {
+               struct mlx5_ind_table_obj *ind_tbl = shared_rss->ind_tbl;
+               const char *message;
+               uint32_t queue_idx;
+
+               ret = mlx5_validate_rss_queues(dev, ind_tbl->queues,
+                                              ind_tbl->queues_n,
+                                              &message, &queue_idx);
+               if (ret != 0) {
+                       DRV_LOG(ERR, "Port %u cannot use queue %u in RSS: %s",
+                               dev->data->port_id, ind_tbl->queues[queue_idx],
+                               message);
+                       break;
+               }
+       }
+       if (ret != 0)
+               return ret;
+       ILIST_FOREACH(ipool, priv->rss_shared_actions, idx, shared_rss, next) {
+               struct mlx5_ind_table_obj *ind_tbl = shared_rss->ind_tbl;
+
+               ret = mlx5_ind_table_obj_attach(dev, ind_tbl);
+               if (ret != 0) {
+                       DRV_LOG(ERR, "Port %u could not attach "
+                               "indirection table obj %p",
+                               dev->data->port_id, (void *)ind_tbl);
+                       goto error;
+               }
+       }
+       return 0;
+error:
+       shared_rss_last = shared_rss;
+       ILIST_FOREACH(ipool, priv->rss_shared_actions, idx, shared_rss, next) {
+               struct mlx5_ind_table_obj *ind_tbl = shared_rss->ind_tbl;
+
+               if (shared_rss == shared_rss_last)
+                       break;
+               if (mlx5_ind_table_obj_detach(dev, ind_tbl) != 0)
+                       DRV_LOG(CRIT, "Port %u could not detach "
+                               "indirection table obj %p on rollback",
+                               dev->data->port_id, (void *)ind_tbl);
+       }
+       return ret;
+}
+
+/**
+ * Detach indirect actions of the device from its resources.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_action_handle_detach(struct rte_eth_dev *dev)
+{
+       struct mlx5_priv *priv = dev->data->dev_private;
+       struct mlx5_indexed_pool *ipool =
+                       priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS];
+       struct mlx5_shared_action_rss *shared_rss, *shared_rss_last;
+       int ret = 0;
+       uint32_t idx;
+
+       ILIST_FOREACH(ipool, priv->rss_shared_actions, idx, shared_rss, next) {
+               struct mlx5_ind_table_obj *ind_tbl = shared_rss->ind_tbl;
+
+               ret = mlx5_ind_table_obj_detach(dev, ind_tbl);
+               if (ret != 0) {
+                       DRV_LOG(ERR, "Port %u could not detach "
+                               "indirection table obj %p",
+                               dev->data->port_id, (void *)ind_tbl);
+                       goto error;
+               }
+       }
+       return 0;
+error:
+       shared_rss_last = shared_rss;
+       ILIST_FOREACH(ipool, priv->rss_shared_actions, idx, shared_rss, next) {
+               struct mlx5_ind_table_obj *ind_tbl = shared_rss->ind_tbl;
+
+               if (shared_rss == shared_rss_last)
+                       break;
+               if (mlx5_ind_table_obj_attach(dev, ind_tbl) != 0)
+                       DRV_LOG(CRIT, "Port %u could not attach "
+                               "indirection table obj %p on rollback",
+                               dev->data->port_id, (void *)ind_tbl);
+       }
+       return ret;
+}
+
 #ifndef HAVE_MLX5DV_DR
 #define MLX5_DOMAIN_SYNC_FLOW ((1 << 0) | (1 << 1))
 #else
@@ -8616,7 +9068,7 @@ flow_tunnel_add_default_miss(struct rte_eth_dev *dev,
                                (error, EINVAL,
                                RTE_FLOW_ERROR_TYPE_ACTION_CONF,
                                NULL, "invalid port configuration");
-               if (!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG))
+               if (!(dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG))
                        ctx->action_rss.types = 0;
                for (i = 0; i != priv->reta_idx_n; ++i)
                        ctx->queue[i] = (*priv->reta_idx)[i];
@@ -9058,6 +9510,9 @@ mlx5_flow_tunnel_validate(struct rte_eth_dev *dev,
                err_msg = "unsupported tunnel type";
                goto out;
        case RTE_FLOW_ITEM_TYPE_VXLAN:
+       case RTE_FLOW_ITEM_TYPE_GRE:
+       case RTE_FLOW_ITEM_TYPE_NVGRE:
+       case RTE_FLOW_ITEM_TYPE_GENEVE:
                break;
        }
 
@@ -9210,7 +9665,7 @@ mlx5_flow_tunnel_get_restore_info(struct rte_eth_dev *dev,
 {
        uint64_t ol_flags = m->ol_flags;
        const struct mlx5_flow_tbl_data_entry *tble;
-       const uint64_t mask = PKT_RX_FDIR | PKT_RX_FDIR_ID;
+       const uint64_t mask = RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID;
 
        if (!is_tunnel_offload_active(dev)) {
                info->flags = 0;
@@ -9351,3 +9806,143 @@ mlx5_dbg__print_pattern(const struct rte_flow_item *item)
        }
        printf("END\n");
 }
+
+static int
+mlx5_flow_is_std_vxlan_port(const struct rte_flow_item *udp_item)
+{
+       const struct rte_flow_item_udp *spec = udp_item->spec;
+       const struct rte_flow_item_udp *mask = udp_item->mask;
+       uint16_t udp_dport = 0;
+
+       if (spec != NULL) {
+               if (!mask)
+                       mask = &rte_flow_item_udp_mask;
+               udp_dport = rte_be_to_cpu_16(spec->hdr.dst_port &
+                               mask->hdr.dst_port);
+       }
+       return (!udp_dport || udp_dport == MLX5_UDP_PORT_VXLAN);
+}
+
+static const struct mlx5_flow_expand_node *
+mlx5_flow_expand_rss_adjust_node(const struct rte_flow_item *pattern,
+               unsigned int item_idx,
+               const struct mlx5_flow_expand_node graph[],
+               const struct mlx5_flow_expand_node *node)
+{
+       const struct rte_flow_item *item = pattern + item_idx, *prev_item;
+
+       if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN &&
+                       node != NULL &&
+                       node->type == RTE_FLOW_ITEM_TYPE_VXLAN) {
+               /*
+                * The expansion node is VXLAN and it is also the last
+                * expandable item in the pattern, so need to continue
+                * expansion of the inner tunnel.
+                */
+               MLX5_ASSERT(item_idx > 0);
+               prev_item = pattern + item_idx - 1;
+               MLX5_ASSERT(prev_item->type == RTE_FLOW_ITEM_TYPE_UDP);
+               if (mlx5_flow_is_std_vxlan_port(prev_item))
+                       return &graph[MLX5_EXPANSION_STD_VXLAN];
+               return &graph[MLX5_EXPANSION_L3_VXLAN];
+       }
+       return node;
+}
+
+/* Map of Verbs to Flow priority with 8 Verbs priorities. */
+static const uint32_t priority_map_3[][MLX5_PRIORITY_MAP_MAX] = {
+       { 0, 1, 2 }, { 2, 3, 4 }, { 5, 6, 7 },
+};
+
+/* Map of Verbs to Flow priority with 16 Verbs priorities. */
+static const uint32_t priority_map_5[][MLX5_PRIORITY_MAP_MAX] = {
+       { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 },
+       { 9, 10, 11 }, { 12, 13, 14 },
+};
+
+/**
+ * Discover the number of available flow priorities.
+ *
+ * @param dev
+ *   Ethernet device.
+ *
+ * @return
+ *   On success, number of available flow priorities.
+ *   On failure, a negative errno-style code and rte_errno is set.
+ */
+int
+mlx5_flow_discover_priorities(struct rte_eth_dev *dev)
+{
+       static const uint16_t vprio[] = {8, 16};
+       const struct mlx5_priv *priv = dev->data->dev_private;
+       const struct mlx5_flow_driver_ops *fops;
+       enum mlx5_flow_drv_type type;
+       int ret;
+
+       type = mlx5_flow_os_get_type();
+       if (type == MLX5_FLOW_TYPE_MAX) {
+               type = MLX5_FLOW_TYPE_VERBS;
+               if (priv->sh->devx && priv->config.dv_flow_en)
+                       type = MLX5_FLOW_TYPE_DV;
+       }
+       fops = flow_get_drv_ops(type);
+       if (fops->discover_priorities == NULL) {
+               DRV_LOG(ERR, "Priority discovery not supported");
+               rte_errno = ENOTSUP;
+               return -rte_errno;
+       }
+       ret = fops->discover_priorities(dev, vprio, RTE_DIM(vprio));
+       if (ret < 0)
+               return ret;
+       switch (ret) {
+       case 8:
+               ret = RTE_DIM(priority_map_3);
+               break;
+       case 16:
+               ret = RTE_DIM(priority_map_5);
+               break;
+       default:
+               rte_errno = ENOTSUP;
+               DRV_LOG(ERR,
+                       "port %u maximum priority: %d expected 8/16",
+                       dev->data->port_id, ret);
+               return -rte_errno;
+       }
+       DRV_LOG(INFO, "port %u supported flow priorities:"
+               " 0-%d for ingress or egress root table,"
+               " 0-%d for non-root table or transfer root table.",
+               dev->data->port_id, ret - 2,
+               MLX5_NON_ROOT_FLOW_MAX_PRIO - 1);
+       return ret;
+}
+
+/**
+ * Adjust flow priority based on the highest layer and the request priority.
+ *
+ * @param[in] dev
+ *   Pointer to the Ethernet device structure.
+ * @param[in] priority
+ *   The rule base priority.
+ * @param[in] subpriority
+ *   The priority based on the items.
+ *
+ * @return
+ *   The new priority.
+ */
+uint32_t
+mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
+                         uint32_t subpriority)
+{
+       uint32_t res = 0;
+       struct mlx5_priv *priv = dev->data->dev_private;
+
+       switch (priv->sh->flow_max_priority) {
+       case RTE_DIM(priority_map_3):
+               res = priority_map_3[priority][subpriority];
+               break;
+       case RTE_DIM(priority_map_5):
+               res = priority_map_5[priority][subpriority];
+               break;
+       }
+       return  res;
+}