net/mlx5: fix indexed pools allocation on Windows
[dpdk.git] / drivers / net / mlx5 / mlx5_flow.c
index 2bbb5f5..549b305 100644 (file)
@@ -132,6 +132,9 @@ mlx5_flow_is_rss_expandable_item(const struct rte_flow_item *item)
        case RTE_FLOW_ITEM_TYPE_GRE:
        case RTE_FLOW_ITEM_TYPE_GENEVE:
        case RTE_FLOW_ITEM_TYPE_MPLS:
+       case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+       case RTE_FLOW_ITEM_TYPE_GRE_KEY:
+       case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT:
                return true;
        default:
                break;
@@ -451,6 +454,7 @@ enum mlx5_expansion {
        MLX5_EXPANSION_IPV6,
        MLX5_EXPANSION_IPV6_UDP,
        MLX5_EXPANSION_IPV6_TCP,
+       MLX5_EXPANSION_IPV6_FRAG_EXT,
 };
 
 /** Supported expansion of items. */
@@ -605,7 +609,8 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
        },
        [MLX5_EXPANSION_IPV6] = {
                .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV6_UDP,
-                                                 MLX5_EXPANSION_IPV6_TCP),
+                                                 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,
@@ -618,6 +623,9 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
                .type = RTE_FLOW_ITEM_TYPE_TCP,
                .rss_types = ETH_RSS_NONFRAG_IPV6_TCP,
        },
+       [MLX5_EXPANSION_IPV6_FRAG_EXT] = {
+               .type = RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT,
+       },
 };
 
 static struct rte_flow_action_handle *
@@ -4056,28 +4064,27 @@ flow_list_destroy(struct rte_eth_dev *dev, enum mlx5_flow_type type,
                  uint32_t flow_idx);
 
 int
-flow_dv_mreg_match_cb(struct mlx5_hlist *list __rte_unused,
-                     struct mlx5_hlist_entry *entry,
-                     uint64_t key, void *cb_ctx __rte_unused)
+flow_dv_mreg_match_cb(void *tool_ctx __rte_unused,
+                     struct mlx5_list_entry *entry, void *cb_ctx)
 {
+       struct mlx5_flow_cb_ctx *ctx = cb_ctx;
        struct mlx5_flow_mreg_copy_resource *mcp_res =
-               container_of(entry, typeof(*mcp_res), hlist_ent);
+                              container_of(entry, typeof(*mcp_res), hlist_ent);
 
-       return mcp_res->mark_id != key;
+       return mcp_res->mark_id != *(uint32_t *)(ctx->data);
 }
 
-struct mlx5_hlist_entry *
-flow_dv_mreg_create_cb(struct mlx5_hlist *list, uint64_t key,
-                      void *cb_ctx)
+struct mlx5_list_entry *
+flow_dv_mreg_create_cb(void *tool_ctx, void *cb_ctx)
 {
-       struct rte_eth_dev *dev = list->ctx;
+       struct rte_eth_dev *dev = tool_ctx;
        struct mlx5_priv *priv = dev->data->dev_private;
        struct mlx5_flow_cb_ctx *ctx = cb_ctx;
        struct mlx5_flow_mreg_copy_resource *mcp_res;
        struct rte_flow_error *error = ctx->error;
        uint32_t idx = 0;
        int ret;
-       uint32_t mark_id = key;
+       uint32_t mark_id = *(uint32_t *)(ctx->data);
        struct rte_flow_attr attr = {
                .group = MLX5_FLOW_MREG_CP_TABLE_GROUP,
                .ingress = 1,
@@ -4183,6 +4190,36 @@ flow_dv_mreg_create_cb(struct mlx5_hlist *list, uint64_t key,
        return &mcp_res->hlist_ent;
 }
 
+struct mlx5_list_entry *
+flow_dv_mreg_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
+                     void *cb_ctx __rte_unused)
+{
+       struct rte_eth_dev *dev = tool_ctx;
+       struct mlx5_priv *priv = dev->data->dev_private;
+       struct mlx5_flow_mreg_copy_resource *mcp_res;
+       uint32_t idx = 0;
+
+       mcp_res = mlx5_ipool_malloc(priv->sh->ipool[MLX5_IPOOL_MCP], &idx);
+       if (!mcp_res) {
+               rte_errno = ENOMEM;
+               return NULL;
+       }
+       memcpy(mcp_res, oentry, sizeof(*mcp_res));
+       mcp_res->idx = idx;
+       return &mcp_res->hlist_ent;
+}
+
+void
+flow_dv_mreg_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
+{
+       struct mlx5_flow_mreg_copy_resource *mcp_res =
+                              container_of(entry, typeof(*mcp_res), hlist_ent);
+       struct rte_eth_dev *dev = tool_ctx;
+       struct mlx5_priv *priv = dev->data->dev_private;
+
+       mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], mcp_res->idx);
+}
+
 /**
  * Add a flow of copying flow metadata registers in RX_CP_TBL.
  *
@@ -4213,10 +4250,11 @@ flow_mreg_add_copy_action(struct rte_eth_dev *dev, uint32_t mark_id,
                          struct rte_flow_error *error)
 {
        struct mlx5_priv *priv = dev->data->dev_private;
-       struct mlx5_hlist_entry *entry;
+       struct mlx5_list_entry *entry;
        struct mlx5_flow_cb_ctx ctx = {
                .dev = dev,
                .error = error,
+               .data = &mark_id,
        };
 
        /* Check if already registered. */
@@ -4229,11 +4267,11 @@ flow_mreg_add_copy_action(struct rte_eth_dev *dev, uint32_t mark_id,
 }
 
 void
-flow_dv_mreg_remove_cb(struct mlx5_hlist *list, struct mlx5_hlist_entry *entry)
+flow_dv_mreg_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
 {
        struct mlx5_flow_mreg_copy_resource *mcp_res =
-               container_of(entry, typeof(*mcp_res), hlist_ent);
-       struct rte_eth_dev *dev = list->ctx;
+                              container_of(entry, typeof(*mcp_res), hlist_ent);
+       struct rte_eth_dev *dev = tool_ctx;
        struct mlx5_priv *priv = dev->data->dev_private;
 
        MLX5_ASSERT(mcp_res->rix_flow);
@@ -4279,14 +4317,17 @@ flow_mreg_del_copy_action(struct rte_eth_dev *dev,
 static void
 flow_mreg_del_default_copy_action(struct rte_eth_dev *dev)
 {
-       struct mlx5_hlist_entry *entry;
+       struct mlx5_list_entry *entry;
        struct mlx5_priv *priv = dev->data->dev_private;
+       struct mlx5_flow_cb_ctx ctx;
+       uint32_t mark_id;
 
        /* Check if default flow is registered. */
        if (!priv->mreg_cp_tbl)
                return;
-       entry = mlx5_hlist_lookup(priv->mreg_cp_tbl,
-                                 MLX5_DEFAULT_COPY_ID, NULL);
+       mark_id = MLX5_DEFAULT_COPY_ID;
+       ctx.data = &mark_id;
+       entry = mlx5_hlist_lookup(priv->mreg_cp_tbl, mark_id, &ctx);
        if (!entry)
                return;
        mlx5_hlist_unregister(priv->mreg_cp_tbl, entry);
@@ -4312,6 +4353,8 @@ flow_mreg_add_default_copy_action(struct rte_eth_dev *dev,
 {
        struct mlx5_priv *priv = dev->data->dev_private;
        struct mlx5_flow_mreg_copy_resource *mcp_res;
+       struct mlx5_flow_cb_ctx ctx;
+       uint32_t mark_id;
 
        /* Check whether extensive metadata feature is engaged. */
        if (!priv->config.dv_flow_en ||
@@ -4323,9 +4366,11 @@ flow_mreg_add_default_copy_action(struct rte_eth_dev *dev,
         * Add default mreg copy flow may be called multiple time, but
         * only be called once in stop. Avoid register it twice.
         */
-       if (mlx5_hlist_lookup(priv->mreg_cp_tbl, MLX5_DEFAULT_COPY_ID, NULL))
+       mark_id = MLX5_DEFAULT_COPY_ID;
+       ctx.data = &mark_id;
+       if (mlx5_hlist_lookup(priv->mreg_cp_tbl, mark_id, &ctx))
                return 0;
-       mcp_res = flow_mreg_add_copy_action(dev, MLX5_DEFAULT_COPY_ID, error);
+       mcp_res = flow_mreg_add_copy_action(dev, mark_id, error);
        if (!mcp_res)
                return -rte_errno;
        return 0;
@@ -4642,7 +4687,7 @@ get_meter_sub_policy(struct rte_eth_dev *dev,
                struct mlx5_flow_rss_desc *rss_desc[MLX5_MTR_RTE_COLORS] = {0};
                uint32_t i;
 
-               /**
+               /*
                 * This is a tmp dev_flow,
                 * no need to register any matcher for it in translate.
                 */
@@ -4650,18 +4695,19 @@ get_meter_sub_policy(struct rte_eth_dev *dev,
                for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) {
                        struct mlx5_flow dev_flow = {0};
                        struct mlx5_flow_handle dev_handle = { {0} };
+                       uint8_t fate = final_policy->act_cnt[i].fate_action;
 
-                       if (final_policy->is_rss) {
+                       if (fate == MLX5_FLOW_FATE_SHARED_RSS) {
                                const void *rss_act =
                                        final_policy->act_cnt[i].rss->conf;
                                struct rte_flow_action rss_actions[2] = {
                                        [0] = {
                                        .type = RTE_FLOW_ACTION_TYPE_RSS,
-                                       .conf = rss_act
+                                       .conf = rss_act,
                                        },
                                        [1] = {
                                        .type = RTE_FLOW_ACTION_TYPE_END,
-                                       .conf = NULL
+                                       .conf = NULL,
                                        }
                                };
 
@@ -4686,9 +4732,10 @@ get_meter_sub_policy(struct rte_eth_dev *dev,
                                                rss_desc_v[i].hash_fields ?
                                                rss_desc_v[i].queue_num : 1;
                                rss_desc_v[i].tunnel =
-                                       !!(dev_flow.handle->layers &
-                                       MLX5_FLOW_LAYER_TUNNEL);
-                       } else {
+                                               !!(dev_flow.handle->layers &
+                                                  MLX5_FLOW_LAYER_TUNNEL);
+                               rss_desc[i] = &rss_desc_v[i];
+                       } else if (fate == MLX5_FLOW_FATE_QUEUE) {
                                /* This is queue action. */
                                rss_desc_v[i] = wks->rss_desc;
                                rss_desc_v[i].key_len = 0;
@@ -4696,24 +4743,24 @@ get_meter_sub_policy(struct rte_eth_dev *dev,
                                rss_desc_v[i].queue =
                                        &final_policy->act_cnt[i].queue;
                                rss_desc_v[i].queue_num = 1;
+                               rss_desc[i] = &rss_desc_v[i];
+                       } else {
+                               rss_desc[i] = NULL;
                        }
-                       rss_desc[i] = &rss_desc_v[i];
                }
                sub_policy = flow_drv_meter_sub_policy_rss_prepare(dev,
                                                flow, policy, rss_desc);
        } else {
                enum mlx5_meter_domain mtr_domain =
                        attr->transfer ? MLX5_MTR_DOMAIN_TRANSFER :
-                               attr->egress ? MLX5_MTR_DOMAIN_EGRESS :
-                                       MLX5_MTR_DOMAIN_INGRESS;
+                               (attr->egress ? MLX5_MTR_DOMAIN_EGRESS :
+                                               MLX5_MTR_DOMAIN_INGRESS);
                sub_policy = policy->sub_policys[mtr_domain][0];
        }
-       if (!sub_policy) {
+       if (!sub_policy)
                rte_flow_error_set(error, EINVAL,
-                       RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
-                       "Failed to get meter sub-policy.");
-               goto exit;
-       }
+                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+                                  "Failed to get meter sub-policy.");
 exit:
        return sub_policy;
 }
@@ -4911,8 +4958,8 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
                } else {
                        enum mlx5_meter_domain mtr_domain =
                        attr->transfer ? MLX5_MTR_DOMAIN_TRANSFER :
-                               attr->egress ? MLX5_MTR_DOMAIN_EGRESS :
-                                       MLX5_MTR_DOMAIN_INGRESS;
+                               (attr->egress ? MLX5_MTR_DOMAIN_EGRESS :
+                                               MLX5_MTR_DOMAIN_INGRESS);
 
                        sub_policy =
                        &priv->sh->mtrmng->def_policy[mtr_domain]->sub_policy;
@@ -4928,8 +4975,8 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
        actions_pre++;
        if (!tag_action)
                return rte_flow_error_set(error, ENOMEM,
-                                       RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
-                                       "No tag action space.");
+                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+                                         NULL, "No tag action space.");
        if (!mtr_flow_id) {
                tag_action->type = RTE_FLOW_ACTION_TYPE_VOID;
                goto exit;
@@ -7152,14 +7199,14 @@ mlx5_flow_validate_mtr_acts(struct rte_eth_dev *dev,
                        struct rte_flow_attr *attr,
                        bool *is_rss,
                        uint8_t *domain_bitmap,
-                       bool *is_def_policy,
+                       uint8_t *policy_mode,
                        struct rte_mtr_error *error)
 {
        const struct mlx5_flow_driver_ops *fops;
 
        fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
-       return fops->validate_mtr_acts(dev, actions, attr,
-                       is_rss, domain_bitmap, is_def_policy, error);
+       return fops->validate_mtr_acts(dev, actions, attr, is_rss,
+                                      domain_bitmap, policy_mode, error);
 }
 
 /**
@@ -8622,7 +8669,7 @@ tunnel_mark_decode(struct rte_eth_dev *dev, uint32_t mark)
 {
        struct mlx5_priv *priv = dev->data->dev_private;
        struct mlx5_dev_ctx_shared *sh = priv->sh;
-       struct mlx5_hlist_entry *he;
+       struct mlx5_list_entry *he;
        union tunnel_offload_mark mbits = { .val = mark };
        union mlx5_flow_tbl_key table_key = {
                {
@@ -8634,16 +8681,20 @@ tunnel_mark_decode(struct rte_eth_dev *dev, uint32_t mark)
                        .is_egress = 0,
                }
        };
-       he = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64, NULL);
+       struct mlx5_flow_cb_ctx ctx = {
+               .data = &table_key.v64,
+       };
+
+       he = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64, &ctx);
        return he ?
               container_of(he, struct mlx5_flow_tbl_data_entry, entry) : NULL;
 }
 
 static void
-mlx5_flow_tunnel_grp2tbl_remove_cb(struct mlx5_hlist *list,
-                                  struct mlx5_hlist_entry *entry)
+mlx5_flow_tunnel_grp2tbl_remove_cb(void *tool_ctx,
+                                  struct mlx5_list_entry *entry)
 {
-       struct mlx5_dev_ctx_shared *sh = list->ctx;
+       struct mlx5_dev_ctx_shared *sh = tool_ctx;
        struct tunnel_tbl_entry *tte = container_of(entry, typeof(*tte), hash);
 
        mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TNL_TBL_ID],
@@ -8652,26 +8703,26 @@ mlx5_flow_tunnel_grp2tbl_remove_cb(struct mlx5_hlist *list,
 }
 
 static int
-mlx5_flow_tunnel_grp2tbl_match_cb(struct mlx5_hlist *list __rte_unused,
-                                 struct mlx5_hlist_entry *entry,
-                                 uint64_t key, void *cb_ctx __rte_unused)
+mlx5_flow_tunnel_grp2tbl_match_cb(void *tool_ctx __rte_unused,
+                                 struct mlx5_list_entry *entry, void *cb_ctx)
 {
+       struct mlx5_flow_cb_ctx *ctx = cb_ctx;
        union tunnel_tbl_key tbl = {
-               .val = key,
+               .val = *(uint64_t *)(ctx->data),
        };
        struct tunnel_tbl_entry *tte = container_of(entry, typeof(*tte), hash);
 
        return tbl.tunnel_id != tte->tunnel_id || tbl.group != tte->group;
 }
 
-static struct mlx5_hlist_entry *
-mlx5_flow_tunnel_grp2tbl_create_cb(struct mlx5_hlist *list, uint64_t key,
-                                  void *ctx __rte_unused)
+static struct mlx5_list_entry *
+mlx5_flow_tunnel_grp2tbl_create_cb(void *tool_ctx, void *cb_ctx)
 {
-       struct mlx5_dev_ctx_shared *sh = list->ctx;
+       struct mlx5_dev_ctx_shared *sh = tool_ctx;
+       struct mlx5_flow_cb_ctx *ctx = cb_ctx;
        struct tunnel_tbl_entry *tte;
        union tunnel_tbl_key tbl = {
-               .val = key,
+               .val = *(uint64_t *)(ctx->data),
        };
 
        tte = mlx5_malloc(MLX5_MEM_SYS | MLX5_MEM_ZERO,
@@ -8700,13 +8751,36 @@ err:
        return NULL;
 }
 
+static struct mlx5_list_entry *
+mlx5_flow_tunnel_grp2tbl_clone_cb(void *tool_ctx __rte_unused,
+                                 struct mlx5_list_entry *oentry,
+                                 void *cb_ctx __rte_unused)
+{
+       struct tunnel_tbl_entry *tte = mlx5_malloc(MLX5_MEM_SYS, sizeof(*tte),
+                                                  0, SOCKET_ID_ANY);
+
+       if (!tte)
+               return NULL;
+       memcpy(tte, oentry, sizeof(*tte));
+       return &tte->hash;
+}
+
+static void
+mlx5_flow_tunnel_grp2tbl_clone_free_cb(void *tool_ctx __rte_unused,
+                                      struct mlx5_list_entry *entry)
+{
+       struct tunnel_tbl_entry *tte = container_of(entry, typeof(*tte), hash);
+
+       mlx5_free(tte);
+}
+
 static uint32_t
 tunnel_flow_group_to_flow_table(struct rte_eth_dev *dev,
                                const struct mlx5_flow_tunnel *tunnel,
                                uint32_t group, uint32_t *table,
                                struct rte_flow_error *error)
 {
-       struct mlx5_hlist_entry *he;
+       struct mlx5_list_entry *he;
        struct tunnel_tbl_entry *tte;
        union tunnel_tbl_key key = {
                .tunnel_id = tunnel ? tunnel->tunnel_id : 0,
@@ -8714,9 +8788,12 @@ tunnel_flow_group_to_flow_table(struct rte_eth_dev *dev,
        };
        struct mlx5_flow_tunnel_hub *thub = mlx5_tunnel_hub(dev);
        struct mlx5_hlist *group_hash;
+       struct mlx5_flow_cb_ctx ctx = {
+               .data = &key.val,
+       };
 
        group_hash = tunnel ? tunnel->groups : thub->groups;
-       he = mlx5_hlist_register(group_hash, key.val, NULL);
+       he = mlx5_hlist_register(group_hash, key.val, &ctx);
        if (!he)
                return rte_flow_error_set(error, EINVAL,
                                          RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
@@ -8830,15 +8907,17 @@ mlx5_flow_tunnel_allocate(struct rte_eth_dev *dev,
                DRV_LOG(ERR, "Tunnel ID %d exceed max limit.", id);
                return NULL;
        }
-       tunnel->groups = mlx5_hlist_create("tunnel groups", 1024, 0, 0,
+       tunnel->groups = mlx5_hlist_create("tunnel groups", 64, false, true,
+                                          priv->sh,
                                           mlx5_flow_tunnel_grp2tbl_create_cb,
                                           mlx5_flow_tunnel_grp2tbl_match_cb,
-                                          mlx5_flow_tunnel_grp2tbl_remove_cb);
+                                          mlx5_flow_tunnel_grp2tbl_remove_cb,
+                                          mlx5_flow_tunnel_grp2tbl_clone_cb,
+                                       mlx5_flow_tunnel_grp2tbl_clone_free_cb);
        if (!tunnel->groups) {
                mlx5_ipool_free(ipool, id);
                return NULL;
        }
-       tunnel->groups->ctx = priv->sh;
        /* initiate new PMD tunnel */
        memcpy(&tunnel->app_tunnel, app_tunnel, sizeof(*app_tunnel));
        tunnel->tunnel_id = id;
@@ -8937,16 +9016,17 @@ int mlx5_alloc_tunnel_hub(struct mlx5_dev_ctx_shared *sh)
                return -ENOMEM;
        LIST_INIT(&thub->tunnels);
        rte_spinlock_init(&thub->sl);
-       thub->groups = mlx5_hlist_create("flow groups",
-                                        rte_align32pow2(MLX5_MAX_TABLES), 0,
-                                        0, mlx5_flow_tunnel_grp2tbl_create_cb,
+       thub->groups = mlx5_hlist_create("flow groups", 64,
+                                        false, true, sh,
+                                        mlx5_flow_tunnel_grp2tbl_create_cb,
                                         mlx5_flow_tunnel_grp2tbl_match_cb,
-                                        mlx5_flow_tunnel_grp2tbl_remove_cb);
+                                        mlx5_flow_tunnel_grp2tbl_remove_cb,
+                                        mlx5_flow_tunnel_grp2tbl_clone_cb,
+                                       mlx5_flow_tunnel_grp2tbl_clone_free_cb);
        if (!thub->groups) {
                err = -rte_errno;
                goto err;
        }
-       thub->groups->ctx = sh;
        sh->tunnel_hub = thub;
 
        return 0;