net/mlx5: fix crash in tunnel offload setup
[dpdk.git] / drivers / net / mlx5 / mlx5_flow_dv.c
index 62d9ca9..5e230a3 100644 (file)
@@ -3935,7 +3935,7 @@ flow_dv_validate_action_jump(struct rte_eth_dev *dev,
        target_group =
                ((const struct rte_flow_action_jump *)action->conf)->group;
        ret = mlx5_flow_group_to_table(dev, tunnel, target_group, &table,
-                                      grp_info, error);
+                                      &grp_info, error);
        if (ret)
                return ret;
        if (attributes->group == target_group &&
@@ -5103,7 +5103,7 @@ static int
 flow_dv_validate_attributes(struct rte_eth_dev *dev,
                            const struct mlx5_flow_tunnel *tunnel,
                            const struct rte_flow_attr *attributes,
-                           struct flow_grp_info grp_info,
+                           const struct flow_grp_info *grp_info,
                            struct rte_flow_error *error)
 {
        struct mlx5_priv *priv = dev->data->dev_private;
@@ -5258,7 +5258,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
        }
        grp_info.std_tbl_fix = tunnel_use_standard_attr_group_translate
                                (dev, tunnel, attr, items, actions);
-       ret = flow_dv_validate_attributes(dev, tunnel, attr, grp_info, error);
+       ret = flow_dv_validate_attributes(dev, tunnel, attr, &grp_info, error);
        if (ret < 0)
                return ret;
        is_root = (uint64_t)ret;
@@ -8042,6 +8042,8 @@ flow_dv_tbl_resource_get(struct rte_eth_dev *dev,
                                   "cannot get table");
                return NULL;
        }
+       DRV_LOG(DEBUG, "Table_id %u tunnel %u group %u registered.",
+               table_id, tunnel ? tunnel->tunnel_id : 0, group_id);
        tbl_data = container_of(entry, struct mlx5_flow_tbl_data_entry, entry);
        return &tbl_data->tbl;
 }
@@ -8080,7 +8082,7 @@ flow_dv_tbl_remove_cb(struct mlx5_hlist *list,
                if (he)
                        mlx5_hlist_unregister(tunnel_grp_hash, he);
                DRV_LOG(DEBUG,
-                       "Table_id %#x tunnel %u group %u released.",
+                       "Table_id %u tunnel %u group %u released.",
                        table_id,
                        tbl_data->tunnel ?
                        tbl_data->tunnel->tunnel_id : 0,
@@ -8192,6 +8194,8 @@ flow_dv_matcher_register(struct rte_eth_dev *dev,
                         struct mlx5_flow_dv_matcher *ref,
                         union mlx5_flow_tbl_key *key,
                         struct mlx5_flow *dev_flow,
+                        const struct mlx5_flow_tunnel *tunnel,
+                        uint32_t group_id,
                         struct rte_flow_error *error)
 {
        struct mlx5_cache_entry *entry;
@@ -8203,8 +8207,14 @@ flow_dv_matcher_register(struct rte_eth_dev *dev,
                .data = ref,
        };
 
-       tbl = flow_dv_tbl_resource_get(dev, key->table_id, key->direction,
-                                      key->domain, false, NULL, 0, 0, error);
+       /**
+        * tunnel offload API requires this registration for cases when
+        * tunnel match rule was inserted before tunnel set rule.
+        */
+       tbl = flow_dv_tbl_resource_get(dev, key->table_id,
+                                      key->direction, key->domain,
+                                      dev_flow->external, tunnel,
+                                      group_id, 0, error);
        if (!tbl)
                return -rte_errno;      /* No need to refill the error info */
        tbl_data = container_of(tbl, struct mlx5_flow_tbl_data_entry, tbl);
@@ -9597,7 +9607,7 @@ flow_dv_translate(struct rte_eth_dev *dev,
        grp_info.std_tbl_fix = tunnel_use_standard_attr_group_translate
                                (dev, tunnel, attr, items, actions);
        ret = mlx5_flow_group_to_table(dev, tunnel, attr->group, &table,
-                                      grp_info, error);
+                                      &grp_info, error);
        if (ret)
                return ret;
        dev_flow->dv.group = table;
@@ -9611,10 +9621,14 @@ flow_dv_translate(struct rte_eth_dev *dev,
                /*
                 * do not add decap action if match rule drops packet
                 * HW rejects rules with decap & drop
+                *
+                * if tunnel match rule was inserted before matching tunnel set
+                * rule flow table used in the match rule must be registered.
+                * current implementation handles that in the
+                * flow_dv_match_register() at the function end.
                 */
                bool add_decap = true;
                const struct rte_flow_action *ptr = actions;
-               struct mlx5_flow_tbl_resource *tbl;
 
                for (; ptr->type != RTE_FLOW_ACTION_TYPE_END; ptr++) {
                        if (ptr->type == RTE_FLOW_ACTION_TYPE_DROP) {
@@ -9631,20 +9645,6 @@ flow_dv_translate(struct rte_eth_dev *dev,
                                        dev_flow->dv.encap_decap->action;
                        action_flags |= MLX5_FLOW_ACTION_DECAP;
                }
-               /*
-                * bind table_id with <group, table> for tunnel match rule.
-                * Tunnel set rule establishes that bind in JUMP action handler.
-                * Required for scenario when application creates tunnel match
-                * rule before tunnel set rule.
-                */
-               tbl = flow_dv_tbl_resource_get(dev, table, attr->egress,
-                                              attr->transfer,
-                                              !!dev_flow->external, tunnel,
-                                              attr->group, 0, error);
-               if (!tbl)
-                       return rte_flow_error_set
-                              (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
-                              actions, "cannot register tunnel group");
        }
        for (; !actions_end ; actions++) {
                const struct rte_flow_action_queue *queue;
@@ -9944,7 +9944,7 @@ flow_dv_translate(struct rte_eth_dev *dev,
                        ret = mlx5_flow_group_to_table(dev, tunnel,
                                                       jump_group,
                                                       &table,
-                                                      grp_info, error);
+                                                      &grp_info, error);
                        if (ret)
                                return ret;
                        tbl = flow_dv_tbl_resource_get(dev, table, attr->egress,
@@ -10474,7 +10474,8 @@ flow_dv_translate(struct rte_eth_dev *dev,
        tbl_key.domain = attr->transfer;
        tbl_key.direction = attr->egress;
        tbl_key.table_id = dev_flow->dv.group;
-       if (flow_dv_matcher_register(dev, &matcher, &tbl_key, dev_flow, error))
+       if (flow_dv_matcher_register(dev, &matcher, &tbl_key, dev_flow,
+                                    tunnel, attr->group, error))
                return -rte_errno;
        return 0;
 }