Currently meter algorithms only supports bytes per second(BPS).
Such as Single Rate Three Color Marker (srTCM rfc2697)
Add packet_mode flag to support rate is packet per second.
So that it can meter traffic by packet per second (PPS).

Signed-off-by: Li Zhang <l...@nvidia.com>
Acked-by: Matan Azrad <ma...@nvidia.com>
---
 doc/guides/nics/mlx5.rst           |  1 +
 drivers/net/mlx5/mlx5_flow_aso.c   | 17 ++++---
 drivers/net/mlx5/mlx5_flow_meter.c | 74 +++++++++++++++++++++++-------
 3 files changed, 69 insertions(+), 23 deletions(-)

diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 9d36d27fa9..cf81ad5c09 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -416,6 +416,7 @@ Limitations
      - green: QUEUE, RSS, PORT_ID, JUMP, MARK and SET_TAG.
      - yellow: must be empty.
      - RED: must be DROP.
+  - meter profile packet mode is supported.
 
 Statistics
 ----------
diff --git a/drivers/net/mlx5/mlx5_flow_aso.c b/drivers/net/mlx5/mlx5_flow_aso.c
index 20cd4fe18c..da513a600c 100644
--- a/drivers/net/mlx5/mlx5_flow_aso.c
+++ b/drivers/net/mlx5/mlx5_flow_aso.c
@@ -191,7 +191,6 @@ mlx5_aso_mtr_init_sq(struct mlx5_aso_sq *sq)
        volatile struct mlx5_aso_wqe *restrict wqe;
        int i;
        int size = 1 << sq->log_desc_n;
-       uint32_t idx;
 
        /* All the next fields state should stay constant. */
        for (i = 0, wqe = &sq->sq_obj.aso_wqes[0]; i < size; ++i, ++wqe) {
@@ -204,11 +203,6 @@ mlx5_aso_mtr_init_sq(struct mlx5_aso_sq *sq)
                         (BYTEWISE_64BYTE << ASO_CSEG_DATA_MASK_MODE_OFFSET));
                wqe->general_cseg.flags = RTE_BE32(MLX5_COMP_ALWAYS <<
                                                         MLX5_COMP_MODE_OFFSET);
-               for (idx = 0; idx < MLX5_ASO_METERS_PER_WQE;
-                       idx++)
-                       wqe->aso_dseg.mtrs[idx].v_bo_sc_bbog_mm =
-                               RTE_BE32((1 << ASO_DSEG_VALID_OFFSET) |
-                               (MLX5_FLOW_COLOR_GREEN << ASO_DSEG_SC_OFFSET));
        }
 }
 
@@ -664,6 +658,7 @@ mlx5_aso_mtr_sq_enqueue_single(struct mlx5_aso_sq *sq,
 {
        volatile struct mlx5_aso_wqe *wqe = NULL;
        struct mlx5_flow_meter_info *fm = NULL;
+       struct mlx5_flow_meter_profile *fmp;
        uint16_t size = 1 << sq->log_desc_n;
        uint16_t mask = size - 1;
        uint16_t res;
@@ -704,6 +699,16 @@ mlx5_aso_mtr_sq_enqueue_single(struct mlx5_aso_sq *sq,
                        RTE_BE32(MLX5_IFC_FLOW_METER_DISABLE_CBS_CIR_VAL);
                wqe->aso_dseg.mtrs[dseg_idx].ebs_eir = 0;
        }
+       fmp = fm->profile;
+       if (fmp->profile.packet_mode)
+               wqe->aso_dseg.mtrs[dseg_idx].v_bo_sc_bbog_mm =
+                               RTE_BE32((1 << ASO_DSEG_VALID_OFFSET) |
+                               (MLX5_FLOW_COLOR_GREEN << ASO_DSEG_SC_OFFSET) |
+                               (MLX5_METER_MODE_PKT << ASO_DSEG_MTR_MODE));
+       else
+               wqe->aso_dseg.mtrs[dseg_idx].v_bo_sc_bbog_mm =
+                               RTE_BE32((1 << ASO_DSEG_VALID_OFFSET) |
+                               (MLX5_FLOW_COLOR_GREEN << ASO_DSEG_SC_OFFSET));
        sq->head++;
        sq->pi += 2;/* Each WQE contains 2 WQEBB's. */
        rte_io_wmb();
diff --git a/drivers/net/mlx5/mlx5_flow_meter.c 
b/drivers/net/mlx5/mlx5_flow_meter.c
index b8fcc6e658..7b77cb5202 100644
--- a/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/drivers/net/mlx5/mlx5_flow_meter.c
@@ -144,13 +144,19 @@ mlx5_flow_meter_profile_validate(struct rte_eth_dev *dev,
        if (profile->alg == RTE_MTR_SRTCM_RFC2697) {
                if (priv->config.hca_attr.qos.flow_meter_old) {
                        /* Verify support for flow meter parameters. */
-                       if (profile->srtcm_rfc2697.cir > 0 &&
-                           profile->srtcm_rfc2697.cir <= MLX5_SRTCM_CIR_MAX &&
-                           profile->srtcm_rfc2697.cbs > 0 &&
-                           profile->srtcm_rfc2697.cbs <= MLX5_SRTCM_CBS_MAX &&
-                           profile->srtcm_rfc2697.ebs <= MLX5_SRTCM_EBS_MAX)
-                               return 0;
-                       else
+                       if (priv->sh->meter_aso_en && profile->packet_mode) {
+                               if (profile->srtcm_rfc2697.cir > 0 &&
+                                       (profile->srtcm_rfc2697.cir <<
+                                       MLX5_MTRS_PPS_MAP_BPS_SHIFT)
+                                       <= MLX5_SRTCM_CIR_MAX &&
+                                       profile->srtcm_rfc2697.cbs > 0 &&
+                                       (profile->srtcm_rfc2697.cbs <<
+                                       MLX5_MTRS_PPS_MAP_BPS_SHIFT)
+                                       <= MLX5_SRTCM_CBS_MAX &&
+                                       (profile->srtcm_rfc2697.ebs <<
+                                       MLX5_MTRS_PPS_MAP_BPS_SHIFT)
+                                       <= MLX5_SRTCM_EBS_MAX)
+                                       return 0;
                                return -rte_mtr_error_set
                                             (error, ENOTSUP,
                                              RTE_MTR_ERROR_TYPE_MTR_PARAMS,
@@ -158,6 +164,22 @@ mlx5_flow_meter_profile_validate(struct rte_eth_dev *dev,
                                              profile->srtcm_rfc2697.ebs ?
                                              "Metering value ebs must be 0." :
                                              "Invalid metering parameters.");
+                       }
+                       if (profile->srtcm_rfc2697.cir > 0 &&
+                               profile->srtcm_rfc2697.cir <=
+                                               MLX5_SRTCM_CIR_MAX &&
+                               profile->srtcm_rfc2697.cbs > 0 &&
+                               profile->srtcm_rfc2697.cbs <=
+                                               MLX5_SRTCM_CBS_MAX &&
+                               profile->srtcm_rfc2697.ebs <=
+                                               MLX5_SRTCM_EBS_MAX)
+                               return 0;
+                       return -rte_mtr_error_set(error, ENOTSUP,
+                                       RTE_MTR_ERROR_TYPE_MTR_PARAMS,
+                                       NULL,
+                                       profile->srtcm_rfc2697.ebs ?
+                                       "Metering value ebs must be 0." :
+                                       "Invalid metering parameters.");
                }
        }
        return -rte_mtr_error_set(error, ENOTSUP,
@@ -241,20 +263,36 @@ mlx5_flow_meter_xbs_man_exp_calc(uint64_t xbs, uint8_t 
*man, uint8_t *exp)
  */
 static int
 mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp,
-                         struct rte_mtr_error *error)
+                       struct mlx5_priv *priv, struct rte_mtr_error *error)
 {
        struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = &fmp->srtcm_prm;
        uint8_t man, exp;
        uint32_t cbs_exp, cbs_man, cir_exp, cir_man;
        uint32_t ebs_exp, ebs_man;
+       uint64_t cir, cbs, ebs;
 
        if (fmp->profile.alg != RTE_MTR_SRTCM_RFC2697)
                return -rte_mtr_error_set(error, ENOTSUP,
                                RTE_MTR_ERROR_TYPE_METER_PROFILE,
                                NULL, "Metering algorithm not supported.");
+       if (!priv->sh->meter_aso_en && fmp->profile.packet_mode)
+               return -rte_mtr_error_set(error, ENOTSUP,
+                       RTE_MTR_ERROR_TYPE_METER_PROFILE,
+                       NULL, "Metering algorithm packet mode not supported.");
+       if (priv->sh->meter_aso_en && fmp->profile.packet_mode) {
+               cir = fmp->profile.srtcm_rfc2697.cir <<
+                               MLX5_MTRS_PPS_MAP_BPS_SHIFT;
+               cbs = fmp->profile.srtcm_rfc2697.cbs <<
+                               MLX5_MTRS_PPS_MAP_BPS_SHIFT;
+               ebs = fmp->profile.srtcm_rfc2697.ebs <<
+                               MLX5_MTRS_PPS_MAP_BPS_SHIFT;
+       } else {
+               cir = fmp->profile.srtcm_rfc2697.cir;
+               cbs = fmp->profile.srtcm_rfc2697.cbs;
+               ebs = fmp->profile.srtcm_rfc2697.ebs;
+       }
        /* cir = 8G * cir_mantissa * 1/(2^cir_exponent)) Bytes/Sec */
-       mlx5_flow_meter_cir_man_exp_calc(fmp->profile.srtcm_rfc2697.cir,
-                                   &man, &exp);
+       mlx5_flow_meter_cir_man_exp_calc(cir, &man, &exp);
        /* Check if cir mantissa is too large. */
        if (exp > ASO_DSEG_CIR_EXP_MASK)
                return -rte_mtr_error_set(error, ENOTSUP,
@@ -264,8 +302,7 @@ mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile 
*fmp,
        cir_man = man;
        cir_exp = exp;
         /* cbs = cbs_mantissa * 2^cbs_exponent */
-       mlx5_flow_meter_xbs_man_exp_calc(fmp->profile.srtcm_rfc2697.cbs,
-                                   &man, &exp);
+       mlx5_flow_meter_xbs_man_exp_calc(cbs, &man, &exp);
        /* Check if cbs mantissa is too large. */
        if (exp > ASO_DSEG_EXP_MASK)
                return -rte_mtr_error_set(error, ENOTSUP,
@@ -278,8 +315,7 @@ mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile 
*fmp,
                                cbs_man << ASO_DSEG_CBS_MAN_OFFSET |
                                cir_exp << ASO_DSEG_CIR_EXP_OFFSET |
                                cir_man);
-       mlx5_flow_meter_xbs_man_exp_calc(fmp->profile.srtcm_rfc2697.ebs,
-                                   &man, &exp);
+       mlx5_flow_meter_xbs_man_exp_calc(ebs, &man, &exp);
        /* Check if ebs mantissa is too large. */
        if (exp > ASO_DSEG_EXP_MASK)
                return -rte_mtr_error_set(error, ENOTSUP,
@@ -319,11 +355,15 @@ mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
                                          RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
                                          "Meter is not supported");
        memset(cap, 0, sizeof(*cap));
-       if (priv->sh->meter_aso_en)
+       if (priv->sh->meter_aso_en) {
                /* 2 meters per one ASO cache line. */
                cap->n_max = 1 << (qattr->log_max_num_meter_aso + 1);
-       else
+               cap->srtcm_rfc2697_packet_mode_supported = 1;
+       } else {
                cap->n_max = 1 << qattr->log_max_flow_meter;
+               cap->srtcm_rfc2697_packet_mode_supported = 0;
+       }
+       cap->srtcm_rfc2697_byte_mode_supported = 1;
        cap->n_shared_max = cap->n_max;
        cap->identical = 1;
        cap->shared_identical = 1;
@@ -384,7 +424,7 @@ mlx5_flow_meter_profile_add(struct rte_eth_dev *dev,
        fmp->id = meter_profile_id;
        fmp->profile = *profile;
        /* Fill the flow meter parameters for the PRM. */
-       ret = mlx5_flow_meter_param_fill(fmp, error);
+       ret = mlx5_flow_meter_param_fill(fmp, priv, error);
        if (ret)
                goto error;
        /* Add to list. */
-- 
2.21.0

Reply via email to