net/mlx5: add count action to meter
authorSuanming Mou <suanmingm@mellanox.com>
Fri, 8 Nov 2019 03:49:19 +0000 (05:49 +0200)
committerFerruh Yigit <ferruh.yigit@intel.com>
Mon, 11 Nov 2019 13:23:02 +0000 (14:23 +0100)
Add count action to meter for metering packet statistics. All the
packets be colored and dropped will be recorded.

Signed-off-by: Suanming Mou <suanmingm@mellanox.com>
Acked-by: Matan Azrad <matan@mellanox.com>
drivers/net/mlx5/mlx5_flow.c
drivers/net/mlx5/mlx5_flow.h
drivers/net/mlx5/mlx5_flow_dv.c
drivers/net/mlx5/mlx5_flow_meter.c

index 750e58e..ee964b0 100644 (file)
@@ -4916,17 +4916,20 @@ mlx5_dev_filter_ctrl(struct rte_eth_dev *dev,
  *
  * @param[in] dev
  *   Pointer to Ethernet device.
+ * @param[in] fm
+ *   Pointer to the flow meter.
  *
  * @return
  *   Pointer to table set on success, NULL otherwise.
  */
 struct mlx5_meter_domains_infos *
-mlx5_flow_create_mtr_tbls(struct rte_eth_dev *dev)
+mlx5_flow_create_mtr_tbls(struct rte_eth_dev *dev,
+                         const struct mlx5_flow_meter *fm)
 {
        const struct mlx5_flow_driver_ops *fops;
 
        fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
-       return fops->create_mtr_tbls(dev);
+       return fops->create_mtr_tbls(dev, fm);
 }
 
 /**
index 0326330..cdcca7a 100644 (file)
@@ -531,6 +531,14 @@ struct mlx5_flow {
 /* Modify this value if enum rte_mtr_color changes. */
 #define RTE_MTR_DROPPED RTE_COLORS
 
+/* Meter policer statistics */
+struct mlx5_flow_policer_stats {
+       struct mlx5_flow_counter *cnt[RTE_COLORS + 1];
+       /**< Color counter, extra for drop. */
+       uint64_t stats_mask;
+       /**< Statistics mask for the colors. */
+};
+
 /* Meter table structure. */
 struct mlx5_meter_domain_info {
        struct mlx5_flow_tbl_resource *tbl;
@@ -557,6 +565,8 @@ struct mlx5_meter_domains_infos {
        /**< FDB meter table. */
        void *drop_actn;
        /**< Drop action as not matched. */
+       void *count_actns[RTE_MTR_DROPPED + 1];
+       /**< Counters for match and unmatched statistics. */
        uint32_t fmp[MLX5_ST_SZ_DW(flow_meter_parameters)];
        /**< Flow meter parameter. */
        size_t fmp_size;
@@ -577,6 +587,8 @@ struct mlx5_flow_meter {
        /**< Meter profile parameters. */
        struct mlx5_meter_domains_infos *mfts;
        /**< Flow table created for this meter. */
+       struct mlx5_flow_policer_stats policer_stats;
+       /**< Meter policer statistics. */
        uint32_t ref_cnt;
        /**< Use count. */
        uint32_t active_state:1;
@@ -653,7 +665,8 @@ typedef int (*mlx5_flow_query_t)(struct rte_eth_dev *dev,
                                 void *data,
                                 struct rte_flow_error *error);
 typedef struct mlx5_meter_domains_infos *(*mlx5_flow_create_mtr_tbls_t)
-                                           (struct rte_eth_dev *dev);
+                                           (struct rte_eth_dev *dev,
+                                            const struct mlx5_flow_meter *fm);
 typedef int (*mlx5_flow_destroy_mtr_tbls_t)(struct rte_eth_dev *dev,
                                        struct mlx5_meter_domains_infos *tbls);
 typedef int (*mlx5_flow_create_policer_rules_t)
@@ -814,7 +827,8 @@ int mlx5_flow_validate_item_geneve(const struct rte_flow_item *item,
                                   struct rte_eth_dev *dev,
                                   struct rte_flow_error *error);
 struct mlx5_meter_domains_infos *mlx5_flow_create_mtr_tbls
-                                       (struct rte_eth_dev *dev);
+                                       (struct rte_eth_dev *dev,
+                                        const struct mlx5_flow_meter *fm);
 int mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,
                               struct mlx5_meter_domains_infos *tbl);
 int mlx5_flow_create_policer_rules(struct rte_eth_dev *dev,
index b273b6c..c03950e 100644 (file)
@@ -7756,6 +7756,8 @@ flow_dv_prepare_mtr_tables(struct rte_eth_dev *dev,
                DRV_LOG(ERR, "Failed to create meter policer color matcher.");
                goto error_exit;
        }
+       if (mtb->count_actns[RTE_MTR_DROPPED])
+               actions[i++] = mtb->count_actns[RTE_MTR_DROPPED];
        actions[i++] = mtb->drop_actn;
        /* Default rule: lowest priority, match any, actions: drop. */
        dtb->policer_rules[RTE_MTR_DROPPED] =
@@ -7776,16 +7778,20 @@ error_exit:
  *
  * @param[in] dev
  *   Pointer to Ethernet device.
+ * @param[in] fm
+ *   Pointer to the flow meter.
  *
  * @return
  *   Pointer to table set on success, NULL otherwise and rte_errno is set.
  */
 static struct mlx5_meter_domains_infos *
-flow_dv_create_mtr_tbl(struct rte_eth_dev *dev)
+flow_dv_create_mtr_tbl(struct rte_eth_dev *dev,
+                      const struct mlx5_flow_meter *fm)
 {
        struct mlx5_priv *priv = dev->data->dev_private;
        struct mlx5_meter_domains_infos *mtb;
        int ret;
+       int i;
 
        if (!priv->mtr_en) {
                rte_errno = ENOTSUP;
@@ -7796,6 +7802,12 @@ flow_dv_create_mtr_tbl(struct rte_eth_dev *dev)
                DRV_LOG(ERR, "Failed to allocate memory for meter.");
                return NULL;
        }
+       /* Create meter count actions */
+       for (i = 0; i <= RTE_MTR_DROPPED; i++) {
+               if (!fm->policer_stats.cnt[i])
+                       continue;
+               mtb->count_actns[i] = fm->policer_stats.cnt[i]->action;
+       }
        /* Create drop action. */
        mtb->drop_actn = mlx5_glue->dr_create_flow_action_drop();
        if (!mtb->drop_actn) {
@@ -7931,6 +7943,8 @@ flow_dv_create_policer_forward_rule(struct mlx5_flow_meter *fm,
 
                flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_reg_c,
                                       rte_col_2_mlx5_col(i), UINT32_MAX);
+               if (mtb->count_actns[i])
+                       actions[j++] = mtb->count_actns[i];
                if (fm->params.action[i] == MTR_POLICER_ACTION_DROP)
                        actions[j++] = mtb->drop_actn;
                else
index 7f64924..7645d92 100644 (file)
@@ -571,6 +571,7 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
                                .transfer = priv->config.dv_esw_en ? 1 : 0,
                        };
        int ret;
+       unsigned int i;
 
        if (!priv->mtr_en)
                return -rte_mtr_error_set(error, ENOTSUP,
@@ -597,7 +598,13 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
        fm->meter_id = meter_id;
        fm->profile = fmp;
        fm->params = *params;
-       fm->mfts = mlx5_flow_create_mtr_tbls(dev);
+       /* Alloc policer counters. */
+       for (i = 0; i < RTE_DIM(fm->policer_stats.cnt); i++) {
+               fm->policer_stats.cnt[i] = mlx5_counter_alloc(dev);
+               if (!fm->policer_stats.cnt[i])
+                       goto error;
+       }
+       fm->mfts = mlx5_flow_create_mtr_tbls(dev, fm);
        if (!fm->mfts)
                goto error;
        ret = mlx5_flow_create_policer_rules(dev, fm, &attr);
@@ -612,6 +619,10 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
 error:
        mlx5_flow_destroy_policer_rules(dev, fm, &attr);
        mlx5_flow_destroy_mtr_tbls(dev, fm->mfts);
+       /* Free policer counters. */
+       for (i = 0; i < RTE_DIM(fm->policer_stats.cnt); i++)
+               if (fm->policer_stats.cnt[i])
+                       mlx5_counter_free(dev, fm->policer_stats.cnt[i]);
        rte_free(fm);
        return -rte_mtr_error_set(error, -ret,
                                  RTE_MTR_ERROR_TYPE_UNSPECIFIED,
@@ -644,6 +655,7 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
                                .egress = 1,
                                .transfer = priv->config.dv_esw_en ? 1 : 0,
                        };
+       unsigned int i;
 
        if (!priv->mtr_en)
                return -rte_mtr_error_set(error, ENOTSUP,
@@ -667,6 +679,10 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
        fmp->ref_cnt--;
        /* Remove from the flow meter list. */
        TAILQ_REMOVE(fms, fm, next);
+       /* Free policer counters. */
+       for (i = 0; i < RTE_DIM(fm->policer_stats.cnt); i++)
+               if (fm->policer_stats.cnt[i])
+                       mlx5_counter_free(dev, fm->policer_stats.cnt[i]);
        /* Free meter flow table */
        mlx5_flow_destroy_policer_rules(dev, fm, &attr);
        mlx5_flow_destroy_mtr_tbls(dev, fm->mfts);