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> --- 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 6e9a68baf5..1eb6d3d5da 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -415,6 +415,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 879252faa1..f34fc54fa6 100644 --- a/drivers/net/mlx5/mlx5_flow_aso.c +++ b/drivers/net/mlx5/mlx5_flow_aso.c @@ -174,7 +174,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) { @@ -187,11 +186,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)); } } @@ -642,6 +636,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; @@ -682,6 +677,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 2c08359107..4aa87fd53c 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