ethdev: move egress metadata to dynamic field
[dpdk.git] / drivers / net / mlx5 / mlx5_flow_dv.c
index 73459a0..42c265f 100644 (file)
@@ -26,6 +26,7 @@
 #include <rte_malloc.h>
 #include <rte_ip.h>
 #include <rte_gre.h>
+#include <rte_vxlan.h>
 
 #include "mlx5.h"
 #include "mlx5_defs.h"
@@ -115,6 +116,12 @@ struct field_modify_info modify_eth[] = {
        {0, 0, 0},
 };
 
+struct field_modify_info modify_vlan_out_first_vid[] = {
+       /* Size in bits !!! */
+       {12, 0, MLX5_MODI_OUT_FIRST_VID},
+       {0, 0, 0},
+};
+
 struct field_modify_info modify_ipv4[] = {
        {1,  8, MLX5_MODI_OUT_IPV4_TTL},
        {4, 12, MLX5_MODI_OUT_SIPV4},
@@ -205,6 +212,33 @@ flow_d_shared_unlock(struct rte_eth_dev *dev)
        }
 }
 
+/* Update VLAN's VID/PCP based on input rte_flow_action.
+ *
+ * @param[in] action
+ *   Pointer to struct rte_flow_action.
+ * @param[out] vlan
+ *   Pointer to struct rte_vlan_hdr.
+ */
+static void
+mlx5_update_vlan_vid_pcp(const struct rte_flow_action *action,
+                        struct rte_vlan_hdr *vlan)
+{
+       uint16_t vlan_tci;
+       if (action->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP) {
+               vlan_tci =
+                   ((const struct rte_flow_action_of_set_vlan_pcp *)
+                                              action->conf)->vlan_pcp;
+               vlan_tci = vlan_tci << MLX5DV_FLOW_VLAN_PCP_SHIFT;
+               vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_PCP_MASK;
+               vlan->vlan_tci |= vlan_tci;
+       } else if (action->type == RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID) {
+               vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_VID_MASK;
+               vlan->vlan_tci |= rte_be_to_cpu_16
+                   (((const struct rte_flow_action_of_set_vlan_vid *)
+                                            action->conf)->vlan_vid);
+       }
+}
+
 /**
  * Convert modify-header action to DV specification.
  *
@@ -396,6 +430,46 @@ flow_dv_convert_action_modify_mac
                                             MLX5_MODIFICATION_TYPE_SET, error);
 }
 
+/**
+ * Convert modify-header set VLAN VID action to DV specification.
+ *
+ * @param[in,out] resource
+ *   Pointer to the modify-header resource.
+ * @param[in] action
+ *   Pointer to action specification.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_convert_action_modify_vlan_vid
+                       (struct mlx5_flow_dv_modify_hdr_resource *resource,
+                        const struct rte_flow_action *action,
+                        struct rte_flow_error *error)
+{
+       const struct rte_flow_action_of_set_vlan_vid *conf =
+               (const struct rte_flow_action_of_set_vlan_vid *)(action->conf);
+       int i = resource->actions_num;
+       struct mlx5_modification_cmd *actions = &resource->actions[i];
+       struct field_modify_info *field = modify_vlan_out_first_vid;
+
+       if (i >= MLX5_MODIFY_NUM)
+               return rte_flow_error_set(error, EINVAL,
+                        RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+                        "too many items to modify");
+       actions[i].action_type = MLX5_MODIFICATION_TYPE_SET;
+       actions[i].field = field->id;
+       actions[i].length = field->size;
+       actions[i].offset = field->offset;
+       actions[i].data0 = rte_cpu_to_be_32(actions[i].data0);
+       actions[i].data1 = conf->vlan_vid;
+       actions[i].data1 = actions[i].data1 << 16;
+       resource->actions_num = ++i;
+       return 0;
+}
+
 /**
  * Convert modify-header set TP action to DV specification.
  *
@@ -677,6 +751,59 @@ flow_dv_convert_action_modify_tcp_ack
                                             MLX5_MODIFICATION_TYPE_ADD, error);
 }
 
+static enum mlx5_modification_field reg_to_field[] = {
+       [REG_A] = MLX5_MODI_META_DATA_REG_A,
+       [REG_B] = MLX5_MODI_META_DATA_REG_B,
+       [REG_C_0] = MLX5_MODI_META_REG_C_0,
+       [REG_C_1] = MLX5_MODI_META_REG_C_1,
+       [REG_C_2] = MLX5_MODI_META_REG_C_2,
+       [REG_C_3] = MLX5_MODI_META_REG_C_3,
+       [REG_C_4] = MLX5_MODI_META_REG_C_4,
+       [REG_C_5] = MLX5_MODI_META_REG_C_5,
+       [REG_C_6] = MLX5_MODI_META_REG_C_6,
+       [REG_C_7] = MLX5_MODI_META_REG_C_7,
+};
+
+/**
+ * Convert register set to DV specification.
+ *
+ * @param[in,out] resource
+ *   Pointer to the modify-header resource.
+ * @param[in] action
+ *   Pointer to action specification.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_convert_action_set_reg
+                       (struct mlx5_flow_dv_modify_hdr_resource *resource,
+                        const struct rte_flow_action *action,
+                        struct rte_flow_error *error)
+{
+       const struct mlx5_rte_flow_action_set_tag *conf = (action->conf);
+       struct mlx5_modification_cmd *actions = resource->actions;
+       uint32_t i = resource->actions_num;
+
+       if (i >= MLX5_MODIFY_NUM)
+               return rte_flow_error_set(error, EINVAL,
+                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+                                         "too many items to modify");
+       actions[i].action_type = MLX5_MODIFICATION_TYPE_SET;
+       actions[i].field = reg_to_field[conf->id];
+       actions[i].data0 = rte_cpu_to_be_32(actions[i].data0);
+       actions[i].data1 = conf->data;
+       ++i;
+       resource->actions_num = i;
+       if (!resource->actions_num)
+               return rte_flow_error_set(error, EINVAL,
+                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+                                         "invalid modification flow item");
+       return 0;
+}
+
 /**
  * Validate META item.
  *
@@ -693,7 +820,7 @@ flow_dv_convert_action_modify_tcp_ack
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-flow_dv_validate_item_meta(struct rte_eth_dev *dev,
+flow_dv_validate_item_meta(struct rte_eth_dev *dev __rte_unused,
                           const struct rte_flow_item *item,
                           const struct rte_flow_attr *attr,
                           struct rte_flow_error *error)
@@ -701,17 +828,10 @@ flow_dv_validate_item_meta(struct rte_eth_dev *dev,
        const struct rte_flow_item_meta *spec = item->spec;
        const struct rte_flow_item_meta *mask = item->mask;
        const struct rte_flow_item_meta nic_mask = {
-               .data = RTE_BE32(UINT32_MAX)
+               .data = UINT32_MAX
        };
        int ret;
-       uint64_t offloads = dev->data->dev_conf.txmode.offloads;
 
-       if (!(offloads & DEV_TX_OFFLOAD_MATCH_METADATA))
-               return rte_flow_error_set(error, EPERM,
-                                         RTE_FLOW_ERROR_TYPE_ITEM,
-                                         NULL,
-                                         "match on metadata offload "
-                                         "configuration is off for this port");
        if (!spec)
                return rte_flow_error_set(error, EINVAL,
                                          RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
@@ -767,8 +887,8 @@ flow_dv_validate_item_port_id(struct rte_eth_dev *dev,
        const struct rte_flow_item_port_id switch_mask = {
                        .id = 0xffffffff,
        };
-       uint16_t esw_domain_id;
-       uint16_t item_port_esw_domain_id;
+       struct mlx5_priv *esw_priv;
+       struct mlx5_priv *dev_priv;
        int ret;
 
        if (!attr->transfer)
@@ -799,22 +919,20 @@ flow_dv_validate_item_port_id(struct rte_eth_dev *dev,
                return ret;
        if (!spec)
                return 0;
-       ret = mlx5_port_to_eswitch_info(spec->id, &item_port_esw_domain_id,
-                                       NULL);
-       if (ret)
-               return rte_flow_error_set(error, -ret,
+       esw_priv = mlx5_port_to_eswitch_info(spec->id);
+       if (!esw_priv)
+               return rte_flow_error_set(error, rte_errno,
                                          RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
                                          "failed to obtain E-Switch info for"
                                          " port");
-       ret = mlx5_port_to_eswitch_info(dev->data->port_id,
-                                       &esw_domain_id, NULL);
-       if (ret < 0)
-               return rte_flow_error_set(error, -ret,
+       dev_priv = mlx5_dev_to_eswitch_info(dev);
+       if (!dev_priv)
+               return rte_flow_error_set(error, rte_errno,
                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
                                          NULL,
                                          "failed to obtain E-Switch info");
-       if (item_port_esw_domain_id != esw_domain_id)
-               return rte_flow_error_set(error, -ret,
+       if (esw_priv->domain_id != dev_priv->domain_id)
+               return rte_flow_error_set(error, EINVAL,
                                          RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
                                          "cannot match on a port from a"
                                          " different E-Switch");
@@ -875,6 +993,11 @@ flow_dv_validate_action_pop_vlan(struct rte_eth_dev *dev,
                                          NULL,
                                          "cannot pop vlan without a "
                                          "match on (outer) vlan in the flow");
+       if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
+               return rte_flow_error_set(error, EINVAL,
+                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
+                                         "wrong action order, port_id should "
+                                         "be after pop VLAN action");
        return 0;
 }
 
@@ -952,6 +1075,7 @@ flow_dev_get_vlan_info_from_items(const struct rte_flow_item *items,
  */
 static int
 flow_dv_validate_action_push_vlan(uint64_t action_flags,
+                                 uint64_t item_flags,
                                  const struct rte_flow_action *action,
                                  const struct rte_flow_attr *attr,
                                  struct rte_flow_error *error)
@@ -969,6 +1093,19 @@ flow_dv_validate_action_push_vlan(uint64_t action_flags,
                                          RTE_FLOW_ERROR_TYPE_ACTION, action,
                                          "no support for multiple VLAN "
                                          "actions");
+       if (!mlx5_flow_find_action
+                       (action + 1, RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID) &&
+           !(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN))
+               return rte_flow_error_set(error, ENOTSUP,
+                               RTE_FLOW_ERROR_TYPE_ACTION, action,
+                               "push VLAN needs to match on VLAN in order to "
+                               "get VLAN VID information because there is "
+                               "no followed set VLAN VID action");
+       if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
+               return rte_flow_error_set(error, EINVAL,
+                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
+                                         "wrong action order, port_id should "
+                                         "be after push VLAN");
        (void)attr;
        return 0;
 }
@@ -1000,17 +1137,84 @@ flow_dv_validate_action_set_vlan_pcp(uint64_t action_flags,
                return rte_flow_error_set(error, EINVAL,
                                          RTE_FLOW_ERROR_TYPE_ACTION, action,
                                          "VLAN PCP value is too big");
-       if (mlx5_flow_find_action(actions,
-                                 RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN) == NULL)
+       if (!(action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN))
                return rte_flow_error_set(error, ENOTSUP,
                                          RTE_FLOW_ERROR_TYPE_ACTION, action,
-                                         "set VLAN PCP can only be used "
-                                         "with push VLAN action");
-       if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN)
+                                         "set VLAN PCP action must follow "
+                                         "the push VLAN action");
+       if (action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_PCP)
                return rte_flow_error_set(error, ENOTSUP,
                                          RTE_FLOW_ERROR_TYPE_ACTION, action,
-                                         "set VLAN PCP action must precede "
-                                         "the push VLAN action");
+                                         "Multiple VLAN PCP modification are "
+                                         "not supported");
+       if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
+               return rte_flow_error_set(error, EINVAL,
+                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
+                                         "wrong action order, port_id should "
+                                         "be after set VLAN PCP");
+       return 0;
+}
+
+/**
+ * Validate the set VLAN VID.
+ *
+ * @param[in] item_flags
+ *   Holds the items detected in this rule.
+ * @param[in] actions
+ *   Pointer to the list of actions remaining in the flow rule.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_set_vlan_vid(uint64_t item_flags,
+                                    uint64_t action_flags,
+                                    const struct rte_flow_action actions[],
+                                    struct rte_flow_error *error)
+{
+       const struct rte_flow_action *action = actions;
+       const struct rte_flow_action_of_set_vlan_vid *conf = action->conf;
+
+       if (conf->vlan_vid > RTE_BE16(0xFFE))
+               return rte_flow_error_set(error, EINVAL,
+                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
+                                         "VLAN VID value is too big");
+       /* there is an of_push_vlan action before us */
+       if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) {
+               if (mlx5_flow_find_action(actions + 1,
+                                         RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID))
+                       return rte_flow_error_set(error, ENOTSUP,
+                                       RTE_FLOW_ERROR_TYPE_ACTION, action,
+                                       "Multiple VLAN VID modifications are "
+                                       "not supported");
+               else
+                       return 0;
+       }
+
+       /*
+        * Action is on an existing VLAN header:
+        *    Need to verify this is a single modify CID action.
+        *   Rule mast include a match on outer VLAN.
+        */
+       if (action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_VID)
+               return rte_flow_error_set(error, ENOTSUP,
+                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
+                                         "Multiple VLAN VID modifications are "
+                                         "not supported");
+       if (!(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN))
+               return rte_flow_error_set(error, EINVAL,
+                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
+                                         "match on VLAN is required in order "
+                                         "to set VLAN VID");
+       if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
+               return rte_flow_error_set(error, EINVAL,
+                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
+                                         "wrong action order, port_id should "
+                                         "be after set VLAN VID");
        return 0;
 }
 
@@ -2269,8 +2473,10 @@ flow_dv_validate_action_modify_ttl(const uint64_t action_flags,
  *   Pointer to the jump action.
  * @param[in] action_flags
  *   Holds the actions detected until now.
- * @param[in] group
- *   The group of the current flow.
+ * @param[in] attributes
+ *   Pointer to flow attributes
+ * @param[in] external
+ *   Action belongs to flow rule created by request external to PMD.
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -2280,9 +2486,14 @@ flow_dv_validate_action_modify_ttl(const uint64_t action_flags,
 static int
 flow_dv_validate_action_jump(const struct rte_flow_action *action,
                             uint64_t action_flags,
-                            uint32_t group,
-                            struct rte_flow_error *error)
+                            const struct rte_flow_attr *attributes,
+                            bool external, struct rte_flow_error *error)
 {
+       uint32_t max_group = attributes->transfer ? MLX5_MAX_TABLES_FDB :
+                                                   MLX5_MAX_TABLES;
+       uint32_t target_group, table;
+       int ret = 0;
+
        if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
                            MLX5_FLOW_FATE_ESWITCH_ACTIONS))
                return rte_flow_error_set(error, EINVAL,
@@ -2293,10 +2504,20 @@ flow_dv_validate_action_jump(const struct rte_flow_action *action,
                return rte_flow_error_set(error, EINVAL,
                                          RTE_FLOW_ERROR_TYPE_ACTION_CONF,
                                          NULL, "action configuration not set");
-       if (group >= ((const struct rte_flow_action_jump *)action->conf)->group)
+       target_group =
+               ((const struct rte_flow_action_jump *)action->conf)->group;
+       ret = mlx5_flow_group_to_table(attributes, external, target_group,
+                                      &table, error);
+       if (ret)
+               return ret;
+       if (table >= max_group)
+               return rte_flow_error_set(error, EINVAL,
+                                         RTE_FLOW_ERROR_TYPE_ATTR_GROUP, NULL,
+                                         "target group index out of range");
+       if (attributes->group >= target_group)
                return rte_flow_error_set(error, EINVAL,
                                          RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-                                         "target group must be higher then"
+                                         "target group must be higher than"
                                          " the current flow group");
        return 0;
 }
@@ -2326,10 +2547,9 @@ flow_dv_validate_action_port_id(struct rte_eth_dev *dev,
                                struct rte_flow_error *error)
 {
        const struct rte_flow_action_port_id *port_id;
+       struct mlx5_priv *act_priv;
+       struct mlx5_priv *dev_priv;
        uint16_t port;
-       uint16_t esw_domain_id;
-       uint16_t act_port_domain_id;
-       int ret;
 
        if (!attr->transfer)
                return rte_flow_error_set(error, ENOTSUP,
@@ -2349,24 +2569,23 @@ flow_dv_validate_action_port_id(struct rte_eth_dev *dev,
                                          RTE_FLOW_ERROR_TYPE_ACTION, NULL,
                                          "can have only one fate actions in"
                                          " a flow");
-       ret = mlx5_port_to_eswitch_info(dev->data->port_id,
-                                       &esw_domain_id, NULL);
-       if (ret < 0)
-               return rte_flow_error_set(error, -ret,
+       dev_priv = mlx5_dev_to_eswitch_info(dev);
+       if (!dev_priv)
+               return rte_flow_error_set(error, rte_errno,
                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
                                          NULL,
                                          "failed to obtain E-Switch info");
        port_id = action->conf;
        port = port_id->original ? dev->data->port_id : port_id->id;
-       ret = mlx5_port_to_eswitch_info(port, &act_port_domain_id, NULL);
-       if (ret)
+       act_priv = mlx5_port_to_eswitch_info(port);
+       if (!act_priv)
                return rte_flow_error_set
-                               (error, -ret,
+                               (error, rte_errno,
                                 RTE_FLOW_ERROR_TYPE_ACTION_CONF, port_id,
                                 "failed to obtain E-Switch port id for port");
-       if (act_port_domain_id != esw_domain_id)
+       if (act_priv->domain_id != dev_priv->domain_id)
                return rte_flow_error_set
-                               (error, -ret,
+                               (error, EINVAL,
                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
                                 "port does not belong to"
                                 " E-Switch being configured");
@@ -3077,6 +3296,8 @@ flow_dv_counter_release(struct rte_eth_dev *dev,
  *   Pointer to dev struct.
  * @param[in] attributes
  *   Pointer to flow attributes
+ * @param[in] external
+ *   This flow rule is created by request external to PMD.
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -3086,6 +3307,7 @@ flow_dv_counter_release(struct rte_eth_dev *dev,
 static int
 flow_dv_validate_attributes(struct rte_eth_dev *dev,
                            const struct rte_flow_attr *attributes,
+                           bool external __rte_unused,
                            struct rte_flow_error *error)
 {
        struct mlx5_priv *priv = dev->data->dev_private;
@@ -3096,7 +3318,22 @@ flow_dv_validate_attributes(struct rte_eth_dev *dev,
                return rte_flow_error_set(error, ENOTSUP,
                                          RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
                                          NULL,
-                                         "groups is not supported");
+                                         "groups are not supported");
+#else
+       uint32_t max_group = attributes->transfer ? MLX5_MAX_TABLES_FDB :
+                                                   MLX5_MAX_TABLES;
+       uint32_t table;
+       int ret;
+
+       ret = mlx5_flow_group_to_table(attributes, external,
+                                      attributes->group,
+                                      &table, error);
+       if (ret)
+               return ret;
+       if (table >= max_group)
+               return rte_flow_error_set(error, EINVAL,
+                                         RTE_FLOW_ERROR_TYPE_ATTR_GROUP, NULL,
+                                         "group index out of range");
 #endif
        if (attributes->priority != MLX5_FLOW_PRIO_RSVD &&
            attributes->priority >= priority_max)
@@ -3120,12 +3357,6 @@ flow_dv_validate_attributes(struct rte_eth_dev *dev,
                                (error, ENOTSUP,
                                 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, attributes,
                                 "egress is not supported");
-               if (attributes->group >= MLX5_MAX_TABLES_FDB)
-                       return rte_flow_error_set
-                               (error, EINVAL,
-                                RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
-                                NULL, "group must be smaller than "
-                                RTE_STR(MLX5_MAX_TABLES_FDB));
        }
        if (!(attributes->egress ^ attributes->ingress))
                return rte_flow_error_set(error, ENOTSUP,
@@ -3146,6 +3377,8 @@ flow_dv_validate_attributes(struct rte_eth_dev *dev,
  *   Pointer to the list of items.
  * @param[in] actions
  *   Pointer to the list of actions.
+ * @param[in] external
+ *   This flow rule is created by request external to PMD.
  * @param[out] error
  *   Pointer to the error structure.
  *
@@ -3156,7 +3389,7 @@ static int
 flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
                 const struct rte_flow_item items[],
                 const struct rte_flow_action actions[],
-                struct rte_flow_error *error)
+                bool external, struct rte_flow_error *error)
 {
        int ret;
        uint64_t action_flags = 0;
@@ -3175,12 +3408,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 
        if (items == NULL)
                return -1;
-       ret = flow_dv_validate_attributes(dev, attr, error);
+       ret = flow_dv_validate_attributes(dev, attr, external, error);
        if (ret < 0)
                return ret;
        for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
                int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
-               switch (items->type) {
+               int type = items->type;
+
+               switch (type) {
                case RTE_FLOW_ITEM_TYPE_VOID:
                        break;
                case RTE_FLOW_ITEM_TYPE_PORT_ID:
@@ -3310,6 +3545,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
                                return ret;
                        last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
                        break;
+               case RTE_FLOW_ITEM_TYPE_GENEVE:
+                       ret = mlx5_flow_validate_item_geneve(items,
+                                                            item_flags, dev,
+                                                            error);
+                       if (ret < 0)
+                               return ret;
+                       last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
+                       break;
                case RTE_FLOW_ITEM_TYPE_MPLS:
                        ret = mlx5_flow_validate_item_mpls(dev, items,
                                                           item_flags,
@@ -3341,6 +3584,9 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
                                return ret;
                        last_item = MLX5_FLOW_LAYER_ICMP6;
                        break;
+               case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
+               case MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE:
+                       break;
                default:
                        return rte_flow_error_set(error, ENOTSUP,
                                                  RTE_FLOW_ERROR_TYPE_ITEM,
@@ -3349,11 +3595,12 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
                item_flags |= last_item;
        }
        for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+               int type = actions->type;
                if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS)
                        return rte_flow_error_set(error, ENOTSUP,
                                                  RTE_FLOW_ERROR_TYPE_ACTION,
                                                  actions, "too many actions");
-               switch (actions->type) {
+               switch (type) {
                case RTE_FLOW_ACTION_TYPE_VOID:
                        break;
                case RTE_FLOW_ACTION_TYPE_PORT_ID:
@@ -3430,6 +3677,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
                        break;
                case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
                        ret = flow_dv_validate_action_push_vlan(action_flags,
+                                                               item_flags,
                                                                actions, attr,
                                                                error);
                        if (ret < 0)
@@ -3443,6 +3691,16 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
                        if (ret < 0)
                                return ret;
                        /* Count PCP with push_vlan command. */
+                       action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_PCP;
+                       break;
+               case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
+                       ret = flow_dv_validate_action_set_vlan_vid
+                                               (item_flags, action_flags,
+                                                actions, error);
+                       if (ret < 0)
+                               return ret;
+                       /* Count VID with push_vlan command. */
+                       action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
                        break;
                case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
                case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
@@ -3571,7 +3829,8 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
                case RTE_FLOW_ACTION_TYPE_JUMP:
                        ret = flow_dv_validate_action_jump(actions,
                                                           action_flags,
-                                                          attr->group, error);
+                                                          attr, external,
+                                                          error);
                        if (ret)
                                return ret;
                        ++actions_n;
@@ -3611,6 +3870,8 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
                                                MLX5_FLOW_ACTION_INC_TCP_ACK :
                                                MLX5_FLOW_ACTION_DEC_TCP_ACK;
                        break;
+               case MLX5_RTE_FLOW_ACTION_TYPE_TAG:
+                       break;
                default:
                        return rte_flow_error_set(error, ENOTSUP,
                                                  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -4359,6 +4620,77 @@ flow_dv_translate_item_vxlan(void *matcher, void *key,
                vni_v[i] = vni_m[i] & vxlan_v->vni[i];
 }
 
+/**
+ * Add Geneve item to matcher and to the value.
+ *
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] item
+ *   Flow pattern to translate.
+ * @param[in] inner
+ *   Item is inner pattern.
+ */
+
+static void
+flow_dv_translate_item_geneve(void *matcher, void *key,
+                             const struct rte_flow_item *item, int inner)
+{
+       const struct rte_flow_item_geneve *geneve_m = item->mask;
+       const struct rte_flow_item_geneve *geneve_v = item->spec;
+       void *headers_m;
+       void *headers_v;
+       void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+       void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+       uint16_t dport;
+       uint16_t gbhdr_m;
+       uint16_t gbhdr_v;
+       char *vni_m;
+       char *vni_v;
+       size_t size, i;
+
+       if (inner) {
+               headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+                                        inner_headers);
+               headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
+       } else {
+               headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+                                        outer_headers);
+               headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
+       }
+       dport = MLX5_UDP_PORT_GENEVE;
+       if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
+               MLX5_SET(fte_match_set_lyr_2_4, headers_m, udp_dport, 0xFFFF);
+               MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, dport);
+       }
+       if (!geneve_v)
+               return;
+       if (!geneve_m)
+               geneve_m = &rte_flow_item_geneve_mask;
+       size = sizeof(geneve_m->vni);
+       vni_m = MLX5_ADDR_OF(fte_match_set_misc, misc_m, geneve_vni);
+       vni_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, geneve_vni);
+       memcpy(vni_m, geneve_m->vni, size);
+       for (i = 0; i < size; ++i)
+               vni_v[i] = vni_m[i] & geneve_v->vni[i];
+       MLX5_SET(fte_match_set_misc, misc_m, geneve_protocol_type,
+                rte_be_to_cpu_16(geneve_m->protocol));
+       MLX5_SET(fte_match_set_misc, misc_v, geneve_protocol_type,
+                rte_be_to_cpu_16(geneve_v->protocol & geneve_m->protocol));
+       gbhdr_m = rte_be_to_cpu_16(geneve_m->ver_opt_len_o_c_rsvd0);
+       gbhdr_v = rte_be_to_cpu_16(geneve_v->ver_opt_len_o_c_rsvd0);
+       MLX5_SET(fte_match_set_misc, misc_m, geneve_oam,
+                MLX5_GENEVE_OAMF_VAL(gbhdr_m));
+       MLX5_SET(fte_match_set_misc, misc_v, geneve_oam,
+                MLX5_GENEVE_OAMF_VAL(gbhdr_v) & MLX5_GENEVE_OAMF_VAL(gbhdr_m));
+       MLX5_SET(fte_match_set_misc, misc_m, geneve_opt_len,
+                MLX5_GENEVE_OPTLEN_VAL(gbhdr_m));
+       MLX5_SET(fte_match_set_misc, misc_v, geneve_opt_len,
+                MLX5_GENEVE_OPTLEN_VAL(gbhdr_v) &
+                MLX5_GENEVE_OPTLEN_VAL(gbhdr_m));
+}
+
 /**
  * Add MPLS item to matcher and to the value.
  *
@@ -4477,10 +4809,121 @@ flow_dv_translate_item_meta(void *matcher, void *key,
                meta_m = &rte_flow_item_meta_mask;
        meta_v = (const void *)item->spec;
        if (meta_v) {
+               MLX5_SET(fte_match_set_misc2, misc2_m,
+                        metadata_reg_a, meta_m->data);
+               MLX5_SET(fte_match_set_misc2, misc2_v,
+                        metadata_reg_a, meta_v->data & meta_m->data);
+       }
+}
+
+/**
+ * Add vport metadata Reg C0 item to matcher
+ *
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] reg
+ *   Flow pattern to translate.
+ */
+static void
+flow_dv_translate_item_meta_vport(void *matcher, void *key,
+                                 uint32_t value, uint32_t mask)
+{
+       void *misc2_m =
+               MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters_2);
+       void *misc2_v =
+               MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2);
+
+       MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_0, mask);
+       MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_0, value);
+}
+
+/**
+ * Add tag item to matcher
+ *
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] item
+ *   Flow pattern to translate.
+ */
+static void
+flow_dv_translate_item_tag(void *matcher, void *key,
+                          const struct rte_flow_item *item)
+{
+       void *misc2_m =
+               MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters_2);
+       void *misc2_v =
+               MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2);
+       const struct mlx5_rte_flow_item_tag *tag_v = item->spec;
+       const struct mlx5_rte_flow_item_tag *tag_m = item->mask;
+       enum modify_reg reg = tag_v->id;
+       rte_be32_t value = tag_v->data;
+       rte_be32_t mask = tag_m->data;
+
+       switch (reg) {
+       case REG_A:
                MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_a,
-                        rte_be_to_cpu_32(meta_m->data));
+                               rte_be_to_cpu_32(mask));
                MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_a,
-                        rte_be_to_cpu_32(meta_v->data & meta_m->data));
+                               rte_be_to_cpu_32(value));
+               break;
+       case REG_B:
+               MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_b,
+                                rte_be_to_cpu_32(mask));
+               MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_b,
+                               rte_be_to_cpu_32(value));
+               break;
+       case REG_C_0:
+               MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_0,
+                                rte_be_to_cpu_32(mask));
+               MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_0,
+                               rte_be_to_cpu_32(value));
+               break;
+       case REG_C_1:
+               MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_1,
+                                rte_be_to_cpu_32(mask));
+               MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_1,
+                               rte_be_to_cpu_32(value));
+               break;
+       case REG_C_2:
+               MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_2,
+                                rte_be_to_cpu_32(mask));
+               MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_2,
+                               rte_be_to_cpu_32(value));
+               break;
+       case REG_C_3:
+               MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_3,
+                                rte_be_to_cpu_32(mask));
+               MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_3,
+                               rte_be_to_cpu_32(value));
+               break;
+       case REG_C_4:
+               MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_4,
+                                rte_be_to_cpu_32(mask));
+               MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_4,
+                               rte_be_to_cpu_32(value));
+               break;
+       case REG_C_5:
+               MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_5,
+                                rte_be_to_cpu_32(mask));
+               MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_5,
+                               rte_be_to_cpu_32(value));
+               break;
+       case REG_C_6:
+               MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_6,
+                                rte_be_to_cpu_32(mask));
+               MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_6,
+                               rte_be_to_cpu_32(value));
+               break;
+       case REG_C_7:
+               MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_7,
+                                rte_be_to_cpu_32(mask));
+               MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_7,
+                               rte_be_to_cpu_32(value));
+               break;
        }
 }
 
@@ -4528,15 +4971,22 @@ flow_dv_translate_item_port_id(struct rte_eth_dev *dev, void *matcher,
 {
        const struct rte_flow_item_port_id *pid_m = item ? item->mask : NULL;
        const struct rte_flow_item_port_id *pid_v = item ? item->spec : NULL;
-       uint16_t mask, val, id;
-       int ret;
+       struct mlx5_priv *priv;
+       uint16_t mask, id;
 
        mask = pid_m ? pid_m->id : 0xffff;
        id = pid_v ? pid_v->id : dev->data->port_id;
-       ret = mlx5_port_to_eswitch_info(id, NULL, &val);
-       if (ret)
-               return ret;
-       flow_dv_translate_item_source_vport(matcher, key, val, mask);
+       priv = mlx5_port_to_eswitch_info(id);
+       if (!priv)
+               return -rte_errno;
+       /* Translate to vport field or to metadata, depending on mode. */
+       if (priv->vport_meta_mask)
+               flow_dv_translate_item_meta_vport(matcher, key,
+                                                 priv->vport_meta_tag,
+                                                 priv->vport_meta_mask);
+       else
+               flow_dv_translate_item_source_vport(matcher, key,
+                                                   priv->vport_id, mask);
        return 0;
 }
 
@@ -4969,22 +5419,69 @@ flow_dv_translate_action_port_id(struct rte_eth_dev *dev,
                                 struct rte_flow_error *error)
 {
        uint32_t port;
-       uint16_t port_id;
-       int ret;
+       struct mlx5_priv *priv;
        const struct rte_flow_action_port_id *conf =
                        (const struct rte_flow_action_port_id *)action->conf;
 
        port = conf->original ? dev->data->port_id : conf->id;
-       ret = mlx5_port_to_eswitch_info(port, NULL, &port_id);
-       if (ret)
-               return rte_flow_error_set(error, -ret,
+       priv = mlx5_port_to_eswitch_info(port);
+       if (!priv)
+               return rte_flow_error_set(error, -rte_errno,
                                          RTE_FLOW_ERROR_TYPE_ACTION,
                                          NULL,
                                          "No eswitch info was found for port");
-       *dst_port_id = port_id;
+       if (priv->vport_meta_mask)
+               *dst_port_id = priv->vport_meta_tag;
+       else
+               *dst_port_id = priv->vport_id;
        return 0;
 }
 
+/**
+ * Add Tx queue matcher
+ *
+ * @param[in] dev
+ *   Pointer to the dev struct.
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] item
+ *   Flow pattern to translate.
+ * @param[in] inner
+ *   Item is inner pattern.
+ */
+static void
+flow_dv_translate_item_tx_queue(struct rte_eth_dev *dev,
+                               void *matcher, void *key,
+                               const struct rte_flow_item *item)
+{
+       const struct mlx5_rte_flow_item_tx_queue *queue_m;
+       const struct mlx5_rte_flow_item_tx_queue *queue_v;
+       void *misc_m =
+               MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+       void *misc_v =
+               MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+       struct mlx5_txq_ctrl *txq;
+       uint32_t queue;
+
+
+       queue_m = (const void *)item->mask;
+       if (!queue_m)
+               return;
+       queue_v = (const void *)item->spec;
+       if (!queue_v)
+               return;
+       txq = mlx5_txq_get(dev, queue_v->queue);
+       if (!txq)
+               return;
+       queue = txq->obj->sq->id;
+       MLX5_SET(fte_match_set_misc, misc_m, source_sqn, queue_m->queue);
+       MLX5_SET(fte_match_set_misc, misc_v, source_sqn,
+                queue & queue_m->queue);
+       mlx5_txq_release(dev, queue_v->queue);
+}
+
 /**
  * Fill the flow with DV spec.
  *
@@ -5036,10 +5533,14 @@ flow_dv_translate(struct rte_eth_dev *dev,
        void *match_value = dev_flow->dv.value.buf;
        uint8_t next_protocol = 0xff;
        struct rte_vlan_hdr vlan = { 0 };
-       bool vlan_inherited = false;
-       uint16_t vlan_tci;
+       uint32_t table;
+       int ret = 0;
 
-       flow->group = attr->group;
+       ret = mlx5_flow_group_to_table(attr, dev_flow->external, attr->group,
+                                      &table, error);
+       if (ret)
+               return ret;
+       flow->group = table;
        if (attr->transfer)
                res.ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
        if (priority == MLX5_FLOW_PRIO_RSVD)
@@ -5055,8 +5556,10 @@ flow_dv_translate(struct rte_eth_dev *dev,
                struct mlx5_flow_tbl_resource *tbl;
                uint32_t port_id = 0;
                struct mlx5_flow_dv_port_id_action_resource port_id_resource;
+               int action_type = actions->type;
+               const struct rte_flow_action *found_action = NULL;
 
-               switch (actions->type) {
+               switch (action_type) {
                case RTE_FLOW_ACTION_TYPE_VOID:
                        break;
                case RTE_FLOW_ACTION_TYPE_PORT_ID:
@@ -5125,7 +5628,7 @@ flow_dv_translate(struct rte_eth_dev *dev,
                        flow->counter = flow_dv_counter_alloc(dev,
                                                              count->shared,
                                                              count->id,
-                                                             attr->group);
+                                                             flow->group);
                        if (flow->counter == NULL)
                                goto cnt_err;
                        dev_flow->dv.actions[actions_n++] =
@@ -5153,13 +5656,20 @@ cnt_err:
                        action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;
                        break;
                case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
-                       if (!vlan_inherited) {
-                               flow_dev_get_vlan_info_from_items(items, &vlan);
-                               vlan_inherited = true;
-                       }
+                       flow_dev_get_vlan_info_from_items(items, &vlan);
                        vlan.eth_proto = rte_be_to_cpu_16
                             ((((const struct rte_flow_action_of_push_vlan *)
                                                   actions->conf)->ethertype));
+                       found_action = mlx5_flow_find_action
+                                       (actions + 1,
+                                        RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID);
+                       if (found_action)
+                               mlx5_update_vlan_vid_pcp(found_action, &vlan);
+                       found_action = mlx5_flow_find_action
+                                       (actions + 1,
+                                        RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP);
+                       if (found_action)
+                               mlx5_update_vlan_vid_pcp(found_action, &vlan);
                        if (flow_dv_create_action_push_vlan
                                            (dev, attr, &vlan, dev_flow, error))
                                return -rte_errno;
@@ -5168,17 +5678,19 @@ cnt_err:
                        action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;
                        break;
                case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
-                       if (!vlan_inherited) {
-                               flow_dev_get_vlan_info_from_items(items, &vlan);
-                               vlan_inherited = true;
-                       }
-                       vlan_tci =
-                           ((const struct rte_flow_action_of_set_vlan_pcp *)
-                                                      actions->conf)->vlan_pcp;
-                       vlan_tci = vlan_tci << MLX5DV_FLOW_VLAN_PCP_SHIFT;
-                       vlan.vlan_tci &= ~MLX5DV_FLOW_VLAN_PCP_MASK;
-                       vlan.vlan_tci |= vlan_tci;
-                       /* Push VLAN command will use this value */
+                       /* of_vlan_push action handled this action */
+                       assert(action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN);
+                       break;
+               case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
+                       if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN)
+                               break;
+                       flow_dev_get_vlan_info_from_items(items, &vlan);
+                       mlx5_update_vlan_vid_pcp(actions, &vlan);
+                       /* If no VLAN push - this is a modify header action */
+                       if (flow_dv_convert_action_modify_vlan_vid
+                                                       (&res, actions, error))
+                               return -rte_errno;
+                       action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
                        break;
                case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
                case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
@@ -5245,7 +5757,12 @@ cnt_err:
                        break;
                case RTE_FLOW_ACTION_TYPE_JUMP:
                        jump_data = action->conf;
-                       tbl = flow_dv_tbl_resource_get(dev, jump_data->group,
+                       ret = mlx5_flow_group_to_table(attr, dev_flow->external,
+                                                      jump_data->group, &table,
+                                                      error);
+                       if (ret)
+                               return ret;
+                       tbl = flow_dv_tbl_resource_get(dev, table,
                                                       attr->egress,
                                                       attr->transfer, error);
                        if (!tbl)
@@ -5344,6 +5861,12 @@ cnt_err:
                                        MLX5_FLOW_ACTION_INC_TCP_ACK :
                                        MLX5_FLOW_ACTION_DEC_TCP_ACK;
                        break;
+               case MLX5_RTE_FLOW_ACTION_TYPE_TAG:
+                       if (flow_dv_convert_action_set_reg(&res, actions,
+                                                          error))
+                               return -rte_errno;
+                       action_flags |= MLX5_FLOW_ACTION_SET_TAG;
+                       break;
                case RTE_FLOW_ACTION_TYPE_END:
                        actions_end = true;
                        if (action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS) {
@@ -5365,11 +5888,12 @@ cnt_err:
                        modify_action_position = actions_n++;
        }
        dev_flow->dv.actions_n = actions_n;
-       flow->actions = action_flags;
+       dev_flow->actions = action_flags;
        for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
                int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
+               int item_type = items->type;
 
-               switch (items->type) {
+               switch (item_type) {
                case RTE_FLOW_ITEM_TYPE_PORT_ID:
                        flow_dv_translate_item_port_id(dev, match_mask,
                                                       match_value, items);
@@ -5396,7 +5920,7 @@ cnt_err:
                        mlx5_flow_tunnel_ip_check(items, next_protocol,
                                                  &item_flags, &tunnel);
                        flow_dv_translate_item_ipv4(match_mask, match_value,
-                                                   items, tunnel, attr->group);
+                                                   items, tunnel, flow->group);
                        matcher.priority = MLX5_PRIORITY_MAP_L3;
                        dev_flow->dv.hash_fields |=
                                mlx5_flow_hashfields_adjust
@@ -5423,7 +5947,7 @@ cnt_err:
                        mlx5_flow_tunnel_ip_check(items, next_protocol,
                                                  &item_flags, &tunnel);
                        flow_dv_translate_item_ipv6(match_mask, match_value,
-                                                   items, tunnel, attr->group);
+                                                   items, tunnel, flow->group);
                        matcher.priority = MLX5_PRIORITY_MAP_L3;
                        dev_flow->dv.hash_fields |=
                                mlx5_flow_hashfields_adjust
@@ -5495,6 +6019,11 @@ cnt_err:
                                                     items, tunnel);
                        last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
                        break;
+               case RTE_FLOW_ITEM_TYPE_GENEVE:
+                       flow_dv_translate_item_geneve(match_mask, match_value,
+                                                     items, tunnel);
+                       last_item = MLX5_FLOW_LAYER_GENEVE;
+                       break;
                case RTE_FLOW_ITEM_TYPE_MPLS:
                        flow_dv_translate_item_mpls(match_mask, match_value,
                                                    items, last_item, tunnel);
@@ -5515,6 +6044,17 @@ cnt_err:
                                                      items, tunnel);
                        last_item = MLX5_FLOW_LAYER_ICMP6;
                        break;
+               case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
+                       flow_dv_translate_item_tag(match_mask, match_value,
+                                                  items);
+                       last_item = MLX5_FLOW_ITEM_TAG;
+                       break;
+               case MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE:
+                       flow_dv_translate_item_tx_queue(dev, match_mask,
+                                                       match_value,
+                                                       items);
+                       last_item = MLX5_FLOW_ITEM_TX_QUEUE;
+                       break;
                default:
                        break;
                }
@@ -5542,7 +6082,7 @@ cnt_err:
        matcher.priority = mlx5_flow_adjust_priority(dev, priority,
                                                     matcher.priority);
        matcher.egress = attr->egress;
-       matcher.group = attr->group;
+       matcher.group = flow->group;
        matcher.transfer = attr->transfer;
        if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
                return -rte_errno;
@@ -5575,7 +6115,7 @@ flow_dv_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
        LIST_FOREACH(dev_flow, &flow->dev_flows, next) {
                dv = &dev_flow->dv;
                n = dv->actions_n;
-               if (flow->actions & MLX5_FLOW_ACTION_DROP) {
+               if (dev_flow->actions & MLX5_FLOW_ACTION_DROP) {
                        if (flow->transfer) {
                                dv->actions[n++] = priv->sh->esw_drop_action;
                        } else {
@@ -5590,7 +6130,7 @@ flow_dv_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
                                }
                                dv->actions[n++] = dv->hrxq->action;
                        }
-               } else if (flow->actions &
+               } else if (dev_flow->actions &
                           (MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)) {
                        struct mlx5_hrxq *hrxq;
 
@@ -5646,7 +6186,7 @@ error:
        LIST_FOREACH(dev_flow, &flow->dev_flows, next) {
                struct mlx5_flow_dv *dv = &dev_flow->dv;
                if (dv->hrxq) {
-                       if (flow->actions & MLX5_FLOW_ACTION_DROP)
+                       if (dev_flow->actions & MLX5_FLOW_ACTION_DROP)
                                mlx5_hrxq_drop_release(dev);
                        else
                                mlx5_hrxq_release(dev, dv->hrxq);
@@ -5880,7 +6420,7 @@ flow_dv_remove(struct rte_eth_dev *dev, struct rte_flow *flow)
                        dv->flow = NULL;
                }
                if (dv->hrxq) {
-                       if (flow->actions & MLX5_FLOW_ACTION_DROP)
+                       if (dev_flow->actions & MLX5_FLOW_ACTION_DROP)
                                mlx5_hrxq_drop_release(dev);
                        else
                                mlx5_hrxq_release(dev, dv->hrxq);