net/mlx5: optimize meter profile lookup
authorShun Hao <shunh@nvidia.com>
Fri, 2 Jul 2021 09:14:43 +0000 (12:14 +0300)
committerRaslan Darawsheh <rasland@nvidia.com>
Thu, 8 Jul 2021 20:09:24 +0000 (22:09 +0200)
Currently a list is used to save all meter profile ids, which is
not efficient when looking up profile from huge amount of profiles.

This changes to use an l3 table instead to save meter profile ids,
so as to improve the lookup performance.

Signed-off-by: Shun Hao <shunh@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
drivers/net/mlx5/linux/mlx5_os.c
drivers/net/mlx5/mlx5.h
drivers/net/mlx5/mlx5_flow_meter.c
drivers/net/mlx5/windows/mlx5_os.c

index 302a881..21b6214 100644 (file)
@@ -1578,7 +1578,9 @@ err_secondary:
        priv->ctrl_flows = 0;
        rte_spinlock_init(&priv->flow_list_lock);
        TAILQ_INIT(&priv->flow_meters);
-       TAILQ_INIT(&priv->flow_meter_profiles);
+       priv->mtr_profile_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_PTR);
+       if (!priv->mtr_profile_tbl)
+               goto error;
        /* Hint libmlx5 to use PMD allocator for data plane resources */
        mlx5_glue->dv_set_context_attr(sh->ctx,
                        MLX5DV_CTX_ATTR_BUF_ALLOCATORS,
@@ -1721,6 +1723,8 @@ error:
                        mlx5_vlan_vmwa_exit(priv->vmwa_context);
                if (eth_dev && priv->drop_queue.hrxq)
                        mlx5_drop_action_destroy(eth_dev);
+               if (priv->mtr_profile_tbl)
+                       mlx5_l3t_destroy(priv->mtr_profile_tbl);
                if (own_domain_id)
                        claim_zero(rte_eth_switch_domain_free(priv->domain_id));
                mlx5_cache_list_destroy(&priv->hrxqs);
index 1b2dc8f..0226327 100644 (file)
@@ -1373,8 +1373,8 @@ struct mlx5_priv {
        /* Hash table of Rx metadata register copy table. */
        uint8_t mtr_sfx_reg; /* Meter prefix-suffix flow match REG_C. */
        uint8_t mtr_color_reg; /* Meter color match REG_C. */
-       struct mlx5_mtr_profiles flow_meter_profiles; /* MTR profile list. */
        struct mlx5_legacy_flow_meters flow_meters; /* MTR list. */
+       struct mlx5_l3t_tbl *mtr_profile_tbl; /* Meter index lookup table. */
        struct mlx5_l3t_tbl *mtr_idx_tbl; /* Meter index lookup table. */
        uint8_t skip_default_rss_reta; /* Skip configuration of default reta. */
        uint8_t fdb_def_rule; /* Whether fdb jump to table 1 is configured. */
index d7ce5cd..87c5782 100644 (file)
@@ -91,13 +91,20 @@ mlx5_flow_meter_action_create(struct mlx5_priv *priv,
 static struct mlx5_flow_meter_profile *
 mlx5_flow_meter_profile_find(struct mlx5_priv *priv, uint32_t meter_profile_id)
 {
-       struct mlx5_mtr_profiles *fmps = &priv->flow_meter_profiles;
        struct mlx5_flow_meter_profile *fmp;
+       union mlx5_l3t_data data;
+       int32_t ret;
 
-       TAILQ_FOREACH(fmp, fmps, next)
-               if (meter_profile_id == fmp->id)
-                       return fmp;
-       return NULL;
+       if (mlx5_l3t_get_entry(priv->mtr_profile_tbl,
+                              meter_profile_id, &data) || !data.ptr)
+               return NULL;
+       fmp = data.ptr;
+       /* Remove reference taken by the mlx5_l3t_get_entry. */
+       ret = mlx5_l3t_clear_entry(priv->mtr_profile_tbl,
+                                  meter_profile_id);
+       if (!ret || ret == -1)
+               return NULL;
+       return fmp;
 }
 
 /**
@@ -399,8 +406,8 @@ mlx5_flow_meter_profile_add(struct rte_eth_dev *dev,
                       struct rte_mtr_error *error)
 {
        struct mlx5_priv *priv = dev->data->dev_private;
-       struct mlx5_mtr_profiles *fmps = &priv->flow_meter_profiles;
        struct mlx5_flow_meter_profile *fmp;
+       union mlx5_l3t_data data;
        int ret;
 
        if (!priv->mtr_en)
@@ -427,8 +434,13 @@ mlx5_flow_meter_profile_add(struct rte_eth_dev *dev,
        ret = mlx5_flow_meter_param_fill(fmp, priv, error);
        if (ret)
                goto error;
-       /* Add to list. */
-       TAILQ_INSERT_TAIL(fmps, fmp, next);
+       data.ptr = fmp;
+       ret = mlx5_l3t_set_entry(priv->mtr_profile_tbl,
+                                meter_profile_id, &data);
+       if (ret)
+               return -rte_mtr_error_set(error, ENOTSUP,
+                                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+                                         NULL, "Meter profile insert fail.");
        return 0;
 error:
        mlx5_free(fmp);
@@ -472,8 +484,10 @@ mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,
                return -rte_mtr_error_set(error, EBUSY,
                                          RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
                                          NULL, "Meter profile is in use.");
-       /* Remove from list. */
-       TAILQ_REMOVE(&priv->flow_meter_profiles, fmp, next);
+       if (mlx5_l3t_clear_entry(priv->mtr_profile_tbl, meter_profile_id))
+               return -rte_mtr_error_set(error, EBUSY,
+                                         RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+                                         NULL, "Meter profile remove fail.");
        mlx5_free(fmp);
        return 0;
 }
@@ -1859,7 +1873,6 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
 {
        struct mlx5_priv *priv = dev->data->dev_private;
        struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
-       struct mlx5_mtr_profiles *fmps = &priv->flow_meter_profiles;
        struct mlx5_flow_meter_profile *fmp;
        struct mlx5_legacy_flow_meter *legacy_fm;
        struct mlx5_flow_meter_info *fm;
@@ -1921,12 +1934,18 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
                mlx5_l3t_destroy(priv->sh->mtrmng->policy_idx_tbl);
                priv->sh->mtrmng->policy_idx_tbl = NULL;
        }
-       TAILQ_FOREACH_SAFE(fmp, fmps, next, tmp) {
-               /* Check unused. */
-               MLX5_ASSERT(!fmp->ref_cnt);
-               /* Remove from list. */
-               TAILQ_REMOVE(&priv->flow_meter_profiles, fmp, next);
-               mlx5_free(fmp);
+       if (priv->mtr_profile_tbl) {
+               MLX5_L3T_FOREACH(priv->mtr_profile_tbl, i, entry) {
+                       fmp = entry;
+                       if (mlx5_flow_meter_profile_delete(dev, fmp->id,
+                                                          error))
+                               return -rte_mtr_error_set(error, EINVAL,
+                                       RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+                                               NULL, "Fail to destroy "
+                                               "meter profile.");
+               }
+               mlx5_l3t_destroy(priv->mtr_profile_tbl);
+               priv->mtr_profile_tbl = NULL;
        }
        /* Delete default policy table. */
        mlx5_flow_destroy_def_policy(dev);
index 3fe3f55..e30b682 100644 (file)
@@ -566,7 +566,9 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
        priv->flows = 0;
        priv->ctrl_flows = 0;
        TAILQ_INIT(&priv->flow_meters);
-       TAILQ_INIT(&priv->flow_meter_profiles);
+       priv->mtr_profile_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_PTR);
+       if (!priv->mtr_profile_tbl)
+               goto error;
        /* Bring Ethernet device up. */
        DRV_LOG(DEBUG, "port %u forcing Ethernet interface up.",
                eth_dev->data->port_id);
@@ -644,6 +646,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
        return eth_dev;
 error:
        if (priv) {
+               if (priv->mtr_profile_tbl)
+                       mlx5_l3t_destroy(priv->mtr_profile_tbl);
                if (own_domain_id)
                        claim_zero(rte_eth_switch_domain_free(priv->domain_id));
                mlx5_free(priv);