X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_flow_meter.c;h=06ab7c4a882bfcac7aca9b50921014ef4bbc452e;hb=80f872ee0222e3936856e43a693168425b1c78ae;hp=2d91a6fcf04d0a985db0ed6582e4a79953e0913e;hpb=33a7493c8df8cd7dc72df31b503e439810f34042;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c index 2d91a6fcf0..06ab7c4a88 100644 --- a/drivers/net/mlx5/mlx5_flow_meter.c +++ b/drivers/net/mlx5/mlx5_flow_meter.c @@ -130,6 +130,11 @@ mlx5_flow_meter_profile_validate(struct rte_eth_dev *dev, { struct mlx5_priv *priv = dev->data->dev_private; struct mlx5_flow_meter_profile *fmp; + uint32_t ls_factor; + int ret; + uint64_t cir, cbs; + uint64_t eir, ebs; + uint64_t pir, pbs; /* Profile must not be NULL. */ if (profile == NULL) @@ -148,50 +153,83 @@ mlx5_flow_meter_profile_validate(struct rte_eth_dev *dev, RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, NULL, "Meter profile already exists."); - if (profile->alg == RTE_MTR_SRTCM_RFC2697) { - if (priv->config.hca_attr.qos.flow_meter_old) { - /* Verify support for flow meter parameters. */ - 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, - NULL, - 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; + if (!priv->sh->meter_aso_en) { + /* Old version is even not supported. */ + if (!priv->sh->cdev->config.hca_attr.qos.flow_meter_old) 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."); + RTE_MTR_ERROR_TYPE_METER_PROFILE, + NULL, "Metering is not supported."); + /* Old FW metering only supports srTCM. */ + if (profile->alg != RTE_MTR_SRTCM_RFC2697) { + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_METER_PROFILE, + NULL, "Metering algorithm is not supported."); + } else if (profile->srtcm_rfc2697.ebs) { + /* EBS is not supported for old metering. */ + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_METER_PROFILE, + NULL, "EBS is not supported."); } + if (profile->packet_mode) + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "Metering algorithm packet mode is not supported."); } - return -rte_mtr_error_set(error, ENOTSUP, - RTE_MTR_ERROR_TYPE_METER_PROFILE, - NULL, "Metering algorithm not supported."); + ls_factor = profile->packet_mode ? MLX5_MTRS_PPS_MAP_BPS_SHIFT : 0; + switch (profile->alg) { + case RTE_MTR_SRTCM_RFC2697: + cir = profile->srtcm_rfc2697.cir << ls_factor; + cbs = profile->srtcm_rfc2697.cbs << ls_factor; + ebs = profile->srtcm_rfc2697.ebs << ls_factor; + /* EBS could be zero for old metering. */ + if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX && + cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX && + ebs <= MLX5_SRTCM_XBS_MAX) { + ret = 0; + } else { + ret = -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "Profile values out of range."); + } + break; + case RTE_MTR_TRTCM_RFC2698: + cir = profile->trtcm_rfc2698.cir << ls_factor; + cbs = profile->trtcm_rfc2698.cbs << ls_factor; + pir = profile->trtcm_rfc2698.pir << ls_factor; + pbs = profile->trtcm_rfc2698.pbs << ls_factor; + if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX && + cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX && + pir >= cir && pir <= (MLX5_SRTCM_XIR_MAX * 2) && + pbs >= cbs && pbs <= (MLX5_SRTCM_XBS_MAX * 2)) { + ret = 0; + } else { + ret = -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "Profile values out of range."); + } + break; + case RTE_MTR_TRTCM_RFC4115: + cir = profile->trtcm_rfc4115.cir << ls_factor; + cbs = profile->trtcm_rfc4115.cbs << ls_factor; + eir = profile->trtcm_rfc4115.eir << ls_factor; + ebs = profile->trtcm_rfc4115.ebs << ls_factor; + if (cir > 0 && cir <= MLX5_SRTCM_XIR_MAX && + cbs > 0 && cbs <= MLX5_SRTCM_XBS_MAX && + eir <= MLX5_SRTCM_XIR_MAX && ebs <= MLX5_SRTCM_XBS_MAX) { + ret = 0; + } else { + ret = -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "Profile values out of range."); + } + break; + default: + ret = -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "Unknown metering algorithm."); + break; + } + return ret; } /* @@ -207,17 +245,23 @@ mlx5_flow_meter_profile_validate(struct rte_eth_dev *dev, static inline void mlx5_flow_meter_xir_man_exp_calc(int64_t xir, uint8_t *man, uint8_t *exp) { - int64_t _cir; + int64_t _xir; int64_t delta = INT64_MAX; uint8_t _man = 0; uint8_t _exp = 0; uint64_t m, e; + /* Special case xir == 0 ? both exp and mantissa are 0. */ + if (xir == 0) { + *man = 0; + *exp = 0; + return; + } for (m = 0; m <= 0xFF; m++) { /* man width 8 bit */ for (e = 0; e <= 0x1F; e++) { /* exp width 5bit */ - _cir = (1000000000ULL * m) >> e; - if (llabs(xir - _cir) <= delta) { - delta = llabs(xir - _cir); + _xir = (1000000000ULL * m) >> e; + if (llabs(xir - _xir) <= delta) { + delta = llabs(xir - _xir); _man = m; _exp = e; } @@ -243,7 +287,7 @@ mlx5_flow_meter_xbs_man_exp_calc(uint64_t xbs, uint8_t *man, uint8_t *exp) int _exp; double _man; - /* Special case xbs == 0 ? both exp and matissa are 0. */ + /* Special case xbs == 0 ? both exp and mantissa are 0. */ if (xbs == 0) { *man = 0; *exp = 0; @@ -251,8 +295,10 @@ mlx5_flow_meter_xbs_man_exp_calc(uint64_t xbs, uint8_t *man, uint8_t *exp) } /* xbs = xbs_mantissa * 2^xbs_exponent */ _man = frexp(xbs, &_exp); - _man = _man * pow(2, MLX5_MAN_WIDTH); - _exp = _exp - MLX5_MAN_WIDTH; + if (_exp >= MLX5_MAN_WIDTH) { + _man = _man * pow(2, MLX5_MAN_WIDTH); + _exp = _exp - MLX5_MAN_WIDTH; + } *man = (uint8_t)ceil(_man); *exp = _exp; } @@ -261,7 +307,7 @@ mlx5_flow_meter_xbs_man_exp_calc(uint64_t xbs, uint8_t *man, uint8_t *exp) * Fill the prm meter parameter. * * @param[in,out] fmp - * Pointer to meter profie to be converted. + * Pointer to meter profile to be converted. * @param[out] error * Pointer to the error structure. * @@ -270,7 +316,7 @@ 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 mlx5_priv *priv, struct rte_mtr_error *error) + struct rte_mtr_error *error) { struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = &fmp->srtcm_prm; uint8_t man, exp; @@ -278,17 +324,6 @@ mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp, uint32_t eir_exp, eir_man, ebs_exp, ebs_man; uint64_t cir, cbs, eir, ebs; - if (!priv->sh->meter_aso_en) { - /* Legacy FW metering will only support srTCM. */ - if (fmp->profile.alg != RTE_MTR_SRTCM_RFC2697) - return -rte_mtr_error_set(error, ENOTSUP, - RTE_MTR_ERROR_TYPE_METER_PROFILE, - NULL, "Metering algorithm is not supported."); - if (fmp->profile.packet_mode) - return -rte_mtr_error_set(error, ENOTSUP, - RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, - "Metering algorithm packet mode is not supported."); - } switch (fmp->profile.alg) { case RTE_MTR_SRTCM_RFC2697: cir = fmp->profile.srtcm_rfc2697.cir; @@ -393,7 +428,7 @@ mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev, struct rte_mtr_error *error __rte_unused) { struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_hca_qos_attr *qattr = &priv->config.hca_attr.qos; + struct mlx5_hca_qos_attr *qattr = &priv->sh->cdev->config.hca_attr.qos; if (!priv->mtr_en) return -rte_mtr_error_set(error, ENOTSUP, @@ -404,11 +439,14 @@ mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev, /* 2 meters per one ASO cache line. */ cap->n_max = 1 << (qattr->log_max_num_meter_aso + 1); cap->srtcm_rfc2697_packet_mode_supported = 1; + cap->trtcm_rfc2698_packet_mode_supported = 1; + cap->trtcm_rfc4115_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->trtcm_rfc2698_byte_mode_supported = 1; + cap->trtcm_rfc4115_byte_mode_supported = 1; cap->n_shared_max = cap->n_max; cap->identical = 1; cap->shared_identical = 1; @@ -416,7 +454,10 @@ mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev, /* 2M flows can share the same meter. */ cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */ cap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap->n_max : 0; + cap->meter_trtcm_rfc2698_n_max = qattr->flow_meter_old ? cap->n_max : 0; + cap->meter_trtcm_rfc4115_n_max = qattr->flow_meter_old ? cap->n_max : 0; cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */ + cap->meter_policy_n_max = cap->n_max; cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED | RTE_MTR_STATS_N_PKTS_DROPPED; return 0; @@ -469,7 +510,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, priv, error); + ret = mlx5_flow_meter_param_fill(fmp, error); if (ret) goto error; data.ptr = fmp; @@ -617,8 +658,8 @@ mlx5_flow_meter_policy_validate(struct rte_eth_dev *dev, struct rte_mtr_error *error) { struct mlx5_priv *priv = dev->data->dev_private; - struct rte_flow_attr attr = { .transfer = - priv->config.dv_esw_en ? 1 : 0}; + struct rte_flow_attr attr = { .transfer = priv->sh->config.dv_esw_en ? + 1 : 0 }; bool is_rss = false; uint8_t policy_mode; uint8_t domain_bitmap; @@ -705,8 +746,8 @@ mlx5_flow_meter_policy_add(struct rte_eth_dev *dev, struct rte_mtr_error *error) { struct mlx5_priv *priv = dev->data->dev_private; - struct rte_flow_attr attr = { .transfer = - priv->config.dv_esw_en ? 1 : 0}; + struct rte_flow_attr attr = { .transfer = priv->sh->config.dv_esw_en ? + 1 : 0 }; uint32_t sub_policy_idx = 0; uint32_t policy_idx = 0; struct mlx5_flow_meter_policy *mtr_policy = NULL; @@ -1068,7 +1109,7 @@ mlx5_flow_meter_action_modify(struct mlx5_priv *priv, if (ret) return ret; } - /* Update succeedded modify meter parameters. */ + /* Update succeeded modify meter parameters. */ if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE) fm->active_state = !!active_state; } @@ -1134,7 +1175,8 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id, struct mlx5_legacy_flow_meters *fms = &priv->flow_meters; struct mlx5_flow_meter_profile *fmp; struct mlx5_flow_meter_info *fm; - struct mlx5_legacy_flow_meter *legacy_fm; + /* GCC fails to infer legacy_fm is set when !priv->sh->meter_aso_en. */ + struct mlx5_legacy_flow_meter *legacy_fm = NULL; struct mlx5_flow_meter_policy *mtr_policy = NULL; struct mlx5_indexed_pool_config flow_ipool_cfg = { .size = 0, @@ -1171,7 +1213,7 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id, (&priv->sh->mtrmng->def_policy_ref_cnt, 1, __ATOMIC_RELAXED); domain_bitmap = MLX5_MTR_ALL_DOMAIN_BIT; - if (!priv->config.dv_esw_en) + if (!priv->sh->config.dv_esw_en) domain_bitmap &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT; } else { if (!priv->sh->meter_aso_en) @@ -1210,6 +1252,10 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id, aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx); fm = &aso_mtr->fm; } else { + if (fmp->y_support) + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Unsupported profile with yellow."); legacy_fm = mlx5_ipool_zmalloc (priv->sh->ipool[MLX5_IPOOL_MTR], &mtr_idx); if (legacy_fm == NULL) @@ -1236,8 +1282,10 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id, if (mlx5_flow_create_mtr_tbls(dev, fm, mtr_idx, domain_bitmap)) goto error; /* Add to the flow meter list. */ - if (!priv->sh->meter_aso_en) + if (!priv->sh->meter_aso_en) { + MLX5_ASSERT(legacy_fm != NULL); TAILQ_INSERT_TAIL(fms, legacy_fm, next); + } /* Add to the flow meter list. */ fm->active_state = 1; /* Config meter starts as active. */ fm->is_enable = 1; @@ -1578,7 +1626,7 @@ mlx5_flow_meter_profile_update(struct rte_eth_dev *dev, return -rte_mtr_error_set(error, -ret, RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, "Failed to update meter" - " parmeters in hardware."); + " parameters in hardware."); } old_fmp->ref_cnt--; fmp->ref_cnt++; @@ -1678,7 +1726,7 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev, memset(stats, 0, sizeof(*stats)); if (fm->drop_cnt) { ret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts, - &bytes); + &bytes, NULL); if (ret) goto error; /* If need to read the packets, set it. */ @@ -1752,24 +1800,21 @@ mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id, struct mlx5_aso_mtr_pools_mng *pools_mng = &priv->sh->mtrmng->pools_mng; union mlx5_l3t_data data; + uint16_t n_valid; if (priv->sh->meter_aso_en) { - rte_spinlock_lock(&pools_mng->mtrsl); - if (!pools_mng->n_valid || !priv->mtr_idx_tbl) { - rte_spinlock_unlock(&pools_mng->mtrsl); + rte_rwlock_read_lock(&pools_mng->resize_mtrwl); + n_valid = pools_mng->n_valid; + rte_rwlock_read_unlock(&pools_mng->resize_mtrwl); + if (!n_valid || !priv->mtr_idx_tbl || + (mlx5_l3t_get_entry(priv->mtr_idx_tbl, meter_id, &data) || + !data.dword)) return NULL; - } - if (mlx5_l3t_get_entry(priv->mtr_idx_tbl, meter_id, &data) || - !data.dword) { - rte_spinlock_unlock(&pools_mng->mtrsl); - return NULL; - } if (mtr_idx) *mtr_idx = data.dword; aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword); /* Remove reference taken by the mlx5_l3t_get_entry. */ mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id); - rte_spinlock_unlock(&pools_mng->mtrsl); if (!aso_mtr || aso_mtr->state == ASO_METER_FREE) return NULL; return &aso_mtr->fm; @@ -2131,7 +2176,7 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error) priv->mtr_idx_tbl = NULL; } } else { - TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) { + RTE_TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) { fm = &legacy_fm->fm; if (mlx5_flow_meter_params_flush(dev, fm, 0)) return -rte_mtr_error_set(error, EINVAL,