1 // SPDX-License-Identifier: BSD-3-Clause 2 /* 3 * Copyright 2018 Mellanox Technologies, Ltd 4 */ 5 #include <math.h> 6 7 #include <rte_tailq.h> 8 #include <rte_malloc.h> 9 #include <rte_mtr.h> 10 #include <rte_mtr_driver.h> 11 12 #include <mlx5_devx_cmds.h> 13 14 #include "mlx5.h" 15 #include "mlx5_flow.h" 16 17 /** 18 * Create the meter action. 19 * 20 * @param priv 21 * Pointer to mlx5_priv. 22 * @param[in] fm 23 * Pointer to flow meter to be converted. 24 * 25 * @return 26 * Pointer to the meter action on success, NULL otherwise. 27 */ 28 static void * 29 mlx5_flow_meter_action_create(struct mlx5_priv *priv, 30 struct mlx5_flow_meter *fm) 31 { 32 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER 33 struct mlx5dv_dr_flow_meter_attr mtr_init; 34 void *attr = fm->mfts->fmp; 35 struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = 36 &fm->profile->srtcm_prm; 37 38 fm->mfts->fmp_size = MLX5_ST_SZ_BYTES(flow_meter_parameters); 39 memset(attr, 0, fm->mfts->fmp_size); 40 MLX5_SET(flow_meter_parameters, attr, valid, 1); 41 MLX5_SET(flow_meter_parameters, attr, bucket_overflow, 1); 42 MLX5_SET(flow_meter_parameters, attr, 43 start_color, MLX5_FLOW_COLOR_GREEN); 44 MLX5_SET(flow_meter_parameters, attr, both_buckets_on_green, 0); 45 MLX5_SET(flow_meter_parameters, 46 attr, cbs_exponent, srtcm->cbs_exponent); 47 MLX5_SET(flow_meter_parameters, 48 attr, cbs_mantissa, srtcm->cbs_mantissa); 49 MLX5_SET(flow_meter_parameters, 50 attr, cir_exponent, srtcm->cir_exponent); 51 MLX5_SET(flow_meter_parameters, 52 attr, cir_mantissa, srtcm->cir_mantissa); 53 MLX5_SET(flow_meter_parameters, 54 attr, ebs_exponent, srtcm->ebs_exponent); 55 MLX5_SET(flow_meter_parameters, 56 attr, ebs_mantissa, srtcm->ebs_mantissa); 57 mtr_init.next_table = 58 fm->attr.transfer ? fm->mfts->transfer.tbl->obj : 59 fm->attr.egress ? fm->mfts->egress.tbl->obj : 60 fm->mfts->ingress.tbl->obj; 61 mtr_init.reg_c_index = priv->mtr_color_reg - REG_C_0; 62 mtr_init.flow_meter_parameter = fm->mfts->fmp; 63 mtr_init.flow_meter_parameter_sz = fm->mfts->fmp_size; 64 mtr_init.active = fm->active_state; 65 return mlx5_glue->dv_create_flow_action_meter(&mtr_init); 66 #else 67 (void)priv; 68 (void)fm; 69 return NULL; 70 #endif 71 } 72 73 /** 74 * Find meter profile by id. 75 * 76 * @param priv 77 * Pointer to mlx5_priv. 78 * @param meter_profile_id 79 * Meter profile id. 80 * 81 * @return 82 * Pointer to the profile found on success, NULL otherwise. 83 */ 84 static struct mlx5_flow_meter_profile * 85 mlx5_flow_meter_profile_find(struct mlx5_priv *priv, uint32_t meter_profile_id) 86 { 87 struct mlx5_mtr_profiles *fmps = &priv->flow_meter_profiles; 88 struct mlx5_flow_meter_profile *fmp; 89 90 TAILQ_FOREACH(fmp, fmps, next) 91 if (meter_profile_id == fmp->meter_profile_id) 92 return fmp; 93 return NULL; 94 } 95 96 /** 97 * Validate the MTR profile. 98 * 99 * @param[in] dev 100 * Pointer to Ethernet device. 101 * @param[in] meter_profile_id 102 * Meter profile id. 103 * @param[in] profile 104 * Pointer to meter profile detail. 105 * @param[out] error 106 * Pointer to the error structure. 107 * 108 * @return 109 * 0 on success, a negative errno value otherwise and rte_errno is set. 110 */ 111 static int 112 mlx5_flow_meter_profile_validate(struct rte_eth_dev *dev, 113 uint32_t meter_profile_id, 114 struct rte_mtr_meter_profile *profile, 115 struct rte_mtr_error *error) 116 { 117 struct mlx5_priv *priv = dev->data->dev_private; 118 struct mlx5_flow_meter_profile *fmp; 119 120 /* Profile must not be NULL. */ 121 if (profile == NULL) 122 return -rte_mtr_error_set(error, EINVAL, 123 RTE_MTR_ERROR_TYPE_METER_PROFILE, 124 NULL, "Meter profile is null."); 125 /* Meter profile ID must be valid. */ 126 if (meter_profile_id == UINT32_MAX) 127 return -rte_mtr_error_set(error, EINVAL, 128 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 129 NULL, "Meter profile id not valid."); 130 /* Meter profile must not exist. */ 131 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id); 132 if (fmp) 133 return -rte_mtr_error_set(error, EEXIST, 134 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 135 NULL, 136 "Meter profile already exists."); 137 if (profile->alg == RTE_MTR_SRTCM_RFC2697) { 138 if (priv->config.hca_attr.qos.srtcm_sup) { 139 /* Verify support for flow meter parameters. */ 140 if (profile->srtcm_rfc2697.cir > 0 && 141 profile->srtcm_rfc2697.cir <= MLX5_SRTCM_CIR_MAX && 142 profile->srtcm_rfc2697.cbs > 0 && 143 profile->srtcm_rfc2697.cbs <= MLX5_SRTCM_CBS_MAX && 144 profile->srtcm_rfc2697.ebs <= MLX5_SRTCM_EBS_MAX) 145 return 0; 146 else 147 return -rte_mtr_error_set 148 (error, ENOTSUP, 149 RTE_MTR_ERROR_TYPE_MTR_PARAMS, 150 NULL, 151 profile->srtcm_rfc2697.ebs ? 152 "Metering value ebs must be 0." : 153 "Invalid metering parameters."); 154 } 155 } 156 return -rte_mtr_error_set(error, ENOTSUP, 157 RTE_MTR_ERROR_TYPE_METER_PROFILE, 158 NULL, "Metering algorithm not supported."); 159 } 160 161 /** 162 * Calculate mantissa and exponent for cir. 163 * 164 * @param[in] cir 165 * Value to be calculated. 166 * @param[out] man 167 * Pointer to the mantissa. 168 * @param[out] exp 169 * Pointer to the exp. 170 */ 171 static void 172 mlx5_flow_meter_cir_man_exp_calc(int64_t cir, uint8_t *man, uint8_t *exp) 173 { 174 int64_t _cir; 175 int64_t delta = INT64_MAX; 176 uint8_t _man = 0; 177 uint8_t _exp = 0; 178 uint64_t m, e; 179 180 for (m = 0; m <= 0xFF; m++) { /* man width 8 bit */ 181 for (e = 0; e <= 0x1F; e++) { /* exp width 5bit */ 182 _cir = (1000000000ULL * m) >> e; 183 if (llabs(cir - _cir) <= delta) { 184 delta = llabs(cir - _cir); 185 _man = m; 186 _exp = e; 187 } 188 } 189 } 190 *man = _man; 191 *exp = _exp; 192 } 193 194 /** 195 * Calculate mantissa and exponent for xbs. 196 * 197 * @param[in] xbs 198 * Value to be calculated. 199 * @param[out] man 200 * Pointer to the mantissa. 201 * @param[out] exp 202 * Pointer to the exp. 203 */ 204 static void 205 mlx5_flow_meter_xbs_man_exp_calc(uint64_t xbs, uint8_t *man, uint8_t *exp) 206 { 207 int _exp; 208 double _man; 209 210 /* Special case xbs == 0 ? both exp and matissa are 0. */ 211 if (xbs == 0) { 212 *man = 0; 213 *exp = 0; 214 return; 215 } 216 /* xbs = xbs_mantissa * 2^xbs_exponent */ 217 _man = frexp(xbs, &_exp); 218 _man = _man * pow(2, MLX5_MAN_WIDTH); 219 _exp = _exp - MLX5_MAN_WIDTH; 220 *man = (uint8_t)ceil(_man); 221 *exp = _exp; 222 } 223 224 /** 225 * Fill the prm meter parameter. 226 * 227 * @param[in,out] fmp 228 * Pointer to meter profie to be converted. 229 * @param[out] error 230 * Pointer to the error structure. 231 * 232 * @return 233 * 0 on success, a negative errno value otherwise and rte_errno is set. 234 */ 235 static int 236 mlx5_flow_meter_param_fill(struct mlx5_flow_meter_profile *fmp, 237 struct rte_mtr_error *error) 238 { 239 struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm = &fmp->srtcm_prm; 240 uint8_t man, exp; 241 242 if (fmp->profile.alg != RTE_MTR_SRTCM_RFC2697) 243 return -rte_mtr_error_set(error, ENOTSUP, 244 RTE_MTR_ERROR_TYPE_METER_PROFILE, 245 NULL, "Metering algorithm not supported."); 246 /* cbs = cbs_mantissa * 2^cbs_exponent */ 247 mlx5_flow_meter_xbs_man_exp_calc(fmp->profile.srtcm_rfc2697.cbs, 248 &man, &exp); 249 srtcm->cbs_mantissa = man; 250 srtcm->cbs_exponent = exp; 251 /* Check if cbs mantissa is too large. */ 252 if (srtcm->cbs_exponent != exp) 253 return -rte_mtr_error_set(error, EINVAL, 254 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 255 "Metering profile parameter cbs is" 256 " invalid."); 257 /* ebs = ebs_mantissa * 2^ebs_exponent */ 258 mlx5_flow_meter_xbs_man_exp_calc(fmp->profile.srtcm_rfc2697.ebs, 259 &man, &exp); 260 srtcm->ebs_mantissa = man; 261 srtcm->ebs_exponent = exp; 262 /* Check if ebs mantissa is too large. */ 263 if (srtcm->ebs_exponent != exp) 264 return -rte_mtr_error_set(error, EINVAL, 265 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 266 "Metering profile parameter ebs is" 267 " invalid."); 268 /* cir = 8G * cir_mantissa * 1/(2^cir_exponent)) Bytes/Sec */ 269 mlx5_flow_meter_cir_man_exp_calc(fmp->profile.srtcm_rfc2697.cir, 270 &man, &exp); 271 srtcm->cir_mantissa = man; 272 srtcm->cir_exponent = exp; 273 /* Check if cir mantissa is too large. */ 274 if (srtcm->cir_exponent != exp) 275 return -rte_mtr_error_set(error, EINVAL, 276 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 277 "Metering profile parameter cir is" 278 " invalid."); 279 return 0; 280 } 281 282 /** 283 * Callback to get MTR capabilities. 284 * 285 * @param[in] dev 286 * Pointer to Ethernet device. 287 * @param[out] cap 288 * Pointer to save MTR capabilities. 289 * @param[out] error 290 * Pointer to the error structure. 291 * 292 * @return 293 * 0 on success, a negative errno value otherwise and rte_errno is set. 294 */ 295 static int 296 mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev, 297 struct rte_mtr_capabilities *cap, 298 struct rte_mtr_error *error __rte_unused) 299 { 300 struct mlx5_priv *priv = dev->data->dev_private; 301 struct mlx5_hca_qos_attr *qattr = &priv->config.hca_attr.qos; 302 303 if (!priv->mtr_en) 304 return -rte_mtr_error_set(error, ENOTSUP, 305 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 306 "Meter is not support"); 307 memset(cap, 0, sizeof(*cap)); 308 cap->n_max = 1 << qattr->log_max_flow_meter; 309 cap->n_shared_max = cap->n_max; 310 cap->identical = 1; 311 cap->shared_identical = 1; 312 cap->shared_n_flows_per_mtr_max = 4 << 20; 313 /* 2M flows can share the same meter. */ 314 cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */ 315 cap->meter_srtcm_rfc2697_n_max = qattr->srtcm_sup ? cap->n_max : 0; 316 cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */ 317 cap->policer_action_drop_supported = 1; 318 cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED | 319 RTE_MTR_STATS_N_PKTS_DROPPED; 320 return 0; 321 } 322 323 /** 324 * Callback to add MTR profile. 325 * 326 * @param[in] dev 327 * Pointer to Ethernet device. 328 * @param[in] meter_profile_id 329 * Meter profile id. 330 * @param[in] profile 331 * Pointer to meter profile detail. 332 * @param[out] error 333 * Pointer to the error structure. 334 * 335 * @return 336 * 0 on success, a negative errno value otherwise and rte_errno is set. 337 */ 338 static int 339 mlx5_flow_meter_profile_add(struct rte_eth_dev *dev, 340 uint32_t meter_profile_id, 341 struct rte_mtr_meter_profile *profile, 342 struct rte_mtr_error *error) 343 { 344 struct mlx5_priv *priv = dev->data->dev_private; 345 struct mlx5_mtr_profiles *fmps = &priv->flow_meter_profiles; 346 struct mlx5_flow_meter_profile *fmp; 347 int ret; 348 349 if (!priv->mtr_en) 350 return -rte_mtr_error_set(error, ENOTSUP, 351 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 352 "Meter is not support"); 353 /* Check input params. */ 354 ret = mlx5_flow_meter_profile_validate(dev, meter_profile_id, 355 profile, error); 356 if (ret) 357 return ret; 358 /* Meter profile memory allocation. */ 359 fmp = rte_calloc(__func__, 1, sizeof(struct mlx5_flow_meter_profile), 360 RTE_CACHE_LINE_SIZE); 361 if (fmp == NULL) 362 return -rte_mtr_error_set(error, ENOMEM, 363 RTE_MTR_ERROR_TYPE_UNSPECIFIED, 364 NULL, "Meter profile memory " 365 "alloc failed."); 366 /* Fill profile info. */ 367 fmp->meter_profile_id = meter_profile_id; 368 fmp->profile = *profile; 369 /* Fill the flow meter parameters for the PRM. */ 370 ret = mlx5_flow_meter_param_fill(fmp, error); 371 if (ret) 372 goto error; 373 /* Add to list. */ 374 TAILQ_INSERT_TAIL(fmps, fmp, next); 375 return 0; 376 error: 377 rte_free(fmp); 378 return ret; 379 } 380 381 /** 382 * Callback to delete MTR profile. 383 * 384 * @param[in] dev 385 * Pointer to Ethernet device. 386 * @param[in] meter_profile_id 387 * Meter profile id. 388 * @param[out] error 389 * Pointer to the error structure. 390 * 391 * @return 392 * 0 on success, a negative errno value otherwise and rte_errno is set. 393 */ 394 static int 395 mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev, 396 uint32_t meter_profile_id, 397 struct rte_mtr_error *error) 398 { 399 struct mlx5_priv *priv = dev->data->dev_private; 400 struct mlx5_flow_meter_profile *fmp; 401 402 if (!priv->mtr_en) 403 return -rte_mtr_error_set(error, ENOTSUP, 404 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 405 "Meter is not support"); 406 /* Meter profile must exist. */ 407 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id); 408 if (fmp == NULL) 409 return -rte_mtr_error_set(error, ENOENT, 410 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 411 &meter_profile_id, 412 "Meter profile id invalid."); 413 /* Check profile is unused. */ 414 if (fmp->ref_cnt) 415 return -rte_mtr_error_set(error, EBUSY, 416 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 417 NULL, "Meter profile in use."); 418 /* Remove from list. */ 419 TAILQ_REMOVE(&priv->flow_meter_profiles, fmp, next); 420 rte_free(fmp); 421 return 0; 422 } 423 424 /** 425 * Convert wrong color setting action to verbose error. 426 * 427 * @param[in] action 428 * Policy color action. 429 * 430 * @return 431 * Verbose meter color error type. 432 */ 433 static inline enum rte_mtr_error_type 434 action2error(enum rte_mtr_policer_action action) 435 { 436 switch (action) { 437 case MTR_POLICER_ACTION_COLOR_GREEN: 438 return RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN; 439 case MTR_POLICER_ACTION_COLOR_YELLOW: 440 return RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW; 441 case MTR_POLICER_ACTION_COLOR_RED: 442 return RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED; 443 default: 444 break; 445 } 446 return RTE_MTR_ERROR_TYPE_UNSPECIFIED; 447 } 448 449 /** 450 * Check meter validation. 451 * 452 * @param[in] priv 453 * Pointer to mlx5 private data structure. 454 * @param[in] meter_id 455 * Meter id. 456 * @param[in] params 457 * Pointer to rte meter parameters. 458 * @param[out] error 459 * Pointer to rte meter error structure. 460 * 461 * @return 462 * 0 on success, a negative errno value otherwise and rte_errno is set. 463 */ 464 static int 465 mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id, 466 struct rte_mtr_params *params, 467 struct rte_mtr_error *error) 468 { 469 static enum rte_mtr_policer_action 470 valid_recol_action[RTE_COLORS] = { 471 MTR_POLICER_ACTION_COLOR_GREEN, 472 MTR_POLICER_ACTION_COLOR_YELLOW, 473 MTR_POLICER_ACTION_COLOR_RED }; 474 int i; 475 476 /* Meter params must not be NULL. */ 477 if (params == NULL) 478 return -rte_mtr_error_set(error, EINVAL, 479 RTE_MTR_ERROR_TYPE_MTR_PARAMS, 480 NULL, "Meter object params null."); 481 /* Previous meter color is not supported. */ 482 if (params->use_prev_mtr_color) 483 return -rte_mtr_error_set(error, ENOTSUP, 484 RTE_MTR_ERROR_TYPE_MTR_PARAMS, 485 NULL, 486 "Previous meter color " 487 "not supported."); 488 /* Validate policer settings. */ 489 for (i = 0; i < RTE_COLORS; i++) 490 if (params->action[i] != valid_recol_action[i] && 491 params->action[i] != MTR_POLICER_ACTION_DROP) 492 return -rte_mtr_error_set 493 (error, ENOTSUP, 494 action2error(params->action[i]), NULL, 495 "Recolor action not supported."); 496 /* Validate meter id. */ 497 if (mlx5_flow_meter_find(priv, meter_id)) 498 return -rte_mtr_error_set(error, EEXIST, 499 RTE_MTR_ERROR_TYPE_MTR_ID, NULL, 500 "Meter object already exists."); 501 return 0; 502 } 503 504 /** 505 * Modify the flow meter action. 506 * 507 * @param[in] priv 508 * Pointer to mlx5 private data structure. 509 * @param[in] fm 510 * Pointer to flow meter to be modified. 511 * @param[in] srtcm 512 * Pointer to meter srtcm description parameter. 513 * @param[in] modify_bits 514 * The bit in srtcm to be updated. 515 * @param[in] active_state 516 * The state to be updated. 517 * @return 518 * 0 on success, o negative value otherwise. 519 */ 520 static int 521 mlx5_flow_meter_action_modify(struct mlx5_priv *priv, 522 struct mlx5_flow_meter *fm, 523 const struct mlx5_flow_meter_srtcm_rfc2697_prm *srtcm, 524 uint64_t modify_bits, uint32_t active_state) 525 { 526 #ifdef HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER 527 uint32_t in[MLX5_ST_SZ_DW(flow_meter_parameters)] = { 0 }; 528 uint32_t *attr; 529 struct mlx5dv_dr_flow_meter_attr mod_attr = { 0 }; 530 int ret; 531 532 /* Fill command parameters. */ 533 mod_attr.reg_c_index = priv->mtr_color_reg - REG_C_0; 534 mod_attr.flow_meter_parameter = in; 535 mod_attr.flow_meter_parameter_sz = fm->mfts->fmp_size; 536 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE) 537 mod_attr.active = !!active_state; 538 else 539 mod_attr.active = 0; 540 attr = in; 541 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS) { 542 MLX5_SET(flow_meter_parameters, 543 attr, cbs_exponent, srtcm->cbs_exponent); 544 MLX5_SET(flow_meter_parameters, 545 attr, cbs_mantissa, srtcm->cbs_mantissa); 546 } 547 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR) { 548 MLX5_SET(flow_meter_parameters, 549 attr, cir_exponent, srtcm->cir_exponent); 550 MLX5_SET(flow_meter_parameters, 551 attr, cir_mantissa, srtcm->cir_mantissa); 552 } 553 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_EBS) { 554 MLX5_SET(flow_meter_parameters, 555 attr, ebs_exponent, srtcm->ebs_exponent); 556 MLX5_SET(flow_meter_parameters, 557 attr, ebs_mantissa, srtcm->ebs_mantissa); 558 } 559 /* Apply modifications to meter only if it was created. */ 560 if (fm->mfts->meter_action) { 561 ret = mlx5_glue->dv_modify_flow_action_meter 562 (fm->mfts->meter_action, &mod_attr, 563 rte_cpu_to_be_64(modify_bits)); 564 if (ret) 565 return ret; 566 } 567 /* Update succeedded modify meter parameters. */ 568 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_ACTIVE) 569 fm->active_state = !!active_state; 570 attr = fm->mfts->fmp; 571 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS) { 572 MLX5_SET(flow_meter_parameters, 573 attr, cbs_exponent, srtcm->cbs_exponent); 574 MLX5_SET(flow_meter_parameters, 575 attr, cbs_mantissa, srtcm->cbs_mantissa); 576 } 577 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR) { 578 MLX5_SET(flow_meter_parameters, 579 attr, cir_exponent, srtcm->cir_exponent); 580 MLX5_SET(flow_meter_parameters, 581 attr, cir_mantissa, srtcm->cir_mantissa); 582 } 583 if (modify_bits & MLX5_FLOW_METER_OBJ_MODIFY_FIELD_EBS) { 584 MLX5_SET(flow_meter_parameters, 585 attr, ebs_exponent, srtcm->ebs_exponent); 586 MLX5_SET(flow_meter_parameters, 587 attr, ebs_mantissa, srtcm->ebs_mantissa); 588 } 589 590 return 0; 591 #else 592 (void)priv; 593 (void)fm; 594 (void)srtcm; 595 (void)modify_bits; 596 (void)active_state; 597 return -ENOTSUP; 598 #endif 599 } 600 601 /** 602 * Create meter rules. 603 * 604 * @param[in] dev 605 * Pointer to Ethernet device. 606 * @param[in] meter_id 607 * Meter id. 608 * @param[in] params 609 * Pointer to rte meter parameters. 610 * @param[in] shared 611 * Meter shared with other flow or not. 612 * @param[out] error 613 * Pointer to rte meter error structure. 614 * 615 * @return 616 * 0 on success, a negative errno value otherwise and rte_errno is set. 617 */ 618 static int 619 mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id, 620 struct rte_mtr_params *params, int shared, 621 struct rte_mtr_error *error) 622 { 623 struct mlx5_priv *priv = dev->data->dev_private; 624 struct mlx5_flow_meters *fms = &priv->flow_meters; 625 struct mlx5_flow_meter_profile *fmp; 626 struct mlx5_flow_meter *fm; 627 const struct rte_flow_attr attr = { 628 .ingress = 1, 629 .egress = 1, 630 .transfer = priv->config.dv_esw_en ? 1 : 0, 631 }; 632 int ret; 633 unsigned int i; 634 635 if (!priv->mtr_en) 636 return -rte_mtr_error_set(error, ENOTSUP, 637 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 638 "Meter is not support"); 639 /* Validate the parameters. */ 640 ret = mlx5_flow_meter_validate(priv, meter_id, params, error); 641 if (ret) 642 return ret; 643 /* Meter profile must exist. */ 644 fmp = mlx5_flow_meter_profile_find(priv, params->meter_profile_id); 645 if (fmp == NULL) 646 return -rte_mtr_error_set(error, ENOENT, 647 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 648 NULL, "Meter profile id not valid."); 649 /* Allocate the flow meter memory. */ 650 fm = rte_calloc(__func__, 1, 651 sizeof(struct mlx5_flow_meter), RTE_CACHE_LINE_SIZE); 652 if (fm == NULL) 653 return -rte_mtr_error_set(error, ENOMEM, 654 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 655 "Memory alloc failed for meter."); 656 /* Fill the flow meter parameters. */ 657 fm->meter_id = meter_id; 658 fm->profile = fmp; 659 fm->params = *params; 660 /* Alloc policer counters. */ 661 for (i = 0; i < RTE_DIM(fm->policer_stats.cnt); i++) { 662 fm->policer_stats.cnt[i] = mlx5_counter_alloc(dev); 663 if (!fm->policer_stats.cnt[i]) 664 goto error; 665 } 666 fm->mfts = mlx5_flow_create_mtr_tbls(dev, fm); 667 if (!fm->mfts) 668 goto error; 669 ret = mlx5_flow_create_policer_rules(dev, fm, &attr); 670 if (ret) 671 goto error; 672 /* Add to the flow meter list. */ 673 TAILQ_INSERT_TAIL(fms, fm, next); 674 fm->active_state = 1; /* Config meter starts as active. */ 675 fm->shared = !!shared; 676 fm->policer_stats.stats_mask = params->stats_mask; 677 fm->profile->ref_cnt++; 678 return 0; 679 error: 680 mlx5_flow_destroy_policer_rules(dev, fm, &attr); 681 mlx5_flow_destroy_mtr_tbls(dev, fm->mfts); 682 /* Free policer counters. */ 683 for (i = 0; i < RTE_DIM(fm->policer_stats.cnt); i++) 684 if (fm->policer_stats.cnt[i]) 685 mlx5_counter_free(dev, fm->policer_stats.cnt[i]); 686 rte_free(fm); 687 return -rte_mtr_error_set(error, -ret, 688 RTE_MTR_ERROR_TYPE_UNSPECIFIED, 689 NULL, "Failed to create devx meter."); 690 } 691 692 /** 693 * Destroy meter rules. 694 * 695 * @param[in] dev 696 * Pointer to Ethernet device. 697 * @param[in] meter_id 698 * Meter id. 699 * @param[out] error 700 * Pointer to rte meter error structure. 701 * 702 * @return 703 * 0 on success, a negative errno value otherwise and rte_errno is set. 704 */ 705 static int 706 mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id, 707 struct rte_mtr_error *error) 708 { 709 struct mlx5_priv *priv = dev->data->dev_private; 710 struct mlx5_flow_meters *fms = &priv->flow_meters; 711 struct mlx5_flow_meter_profile *fmp; 712 struct mlx5_flow_meter *fm; 713 const struct rte_flow_attr attr = { 714 .ingress = 1, 715 .egress = 1, 716 .transfer = priv->config.dv_esw_en ? 1 : 0, 717 }; 718 unsigned int i; 719 720 if (!priv->mtr_en) 721 return -rte_mtr_error_set(error, ENOTSUP, 722 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 723 "Meter is not support"); 724 /* Meter object must exist. */ 725 fm = mlx5_flow_meter_find(priv, meter_id); 726 if (fm == NULL) 727 return -rte_mtr_error_set(error, ENOENT, 728 RTE_MTR_ERROR_TYPE_MTR_ID, 729 NULL, "Meter object id not valid."); 730 /* Meter object must not have any owner. */ 731 if (fm->ref_cnt > 0) 732 return -rte_mtr_error_set(error, EBUSY, 733 RTE_MTR_ERROR_TYPE_UNSPECIFIED, 734 NULL, "Meter object is being used."); 735 /* Get the meter profile. */ 736 fmp = fm->profile; 737 MLX5_ASSERT(fmp); 738 /* Update dependencies. */ 739 fmp->ref_cnt--; 740 /* Remove from the flow meter list. */ 741 TAILQ_REMOVE(fms, fm, next); 742 /* Free policer counters. */ 743 for (i = 0; i < RTE_DIM(fm->policer_stats.cnt); i++) 744 if (fm->policer_stats.cnt[i]) 745 mlx5_counter_free(dev, fm->policer_stats.cnt[i]); 746 /* Free meter flow table */ 747 mlx5_flow_destroy_policer_rules(dev, fm, &attr); 748 mlx5_flow_destroy_mtr_tbls(dev, fm->mfts); 749 rte_free(fm); 750 return 0; 751 } 752 753 /** 754 * Modify meter state. 755 * 756 * @param[in] priv 757 * Pointer to mlx5 private data structure. 758 * @param[in] fm 759 * Pointer to flow meter. 760 * @param[in] new_state 761 * New state to update. 762 * @param[out] error 763 * Pointer to rte meter error structure. 764 * 765 * @return 766 * 0 on success, a negative errno value otherwise and rte_errno is set. 767 */ 768 static int 769 mlx5_flow_meter_modify_state(struct mlx5_priv *priv, 770 struct mlx5_flow_meter *fm, 771 uint32_t new_state, 772 struct rte_mtr_error *error) 773 { 774 static const struct mlx5_flow_meter_srtcm_rfc2697_prm srtcm = { 775 .cbs_exponent = 20, 776 .cbs_mantissa = 191, 777 .cir_exponent = 0, 778 .cir_mantissa = 200, 779 .ebs_exponent = 0, 780 .ebs_mantissa = 0, 781 }; 782 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS | 783 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR; 784 int ret; 785 786 if (new_state == MLX5_FLOW_METER_DISABLE) 787 ret = mlx5_flow_meter_action_modify(priv, fm, &srtcm, 788 modify_bits, 0); 789 else 790 ret = mlx5_flow_meter_action_modify(priv, fm, 791 &fm->profile->srtcm_prm, 792 modify_bits, 0); 793 if (ret) 794 return -rte_mtr_error_set(error, -ret, 795 RTE_MTR_ERROR_TYPE_MTR_PARAMS, 796 NULL, 797 new_state ? 798 "Failed to enable meter." : 799 "Failed to disable meter."); 800 return 0; 801 } 802 803 /** 804 * Callback to enable flow meter. 805 * 806 * @param[in] dev 807 * Pointer to Ethernet device. 808 * @param[in] meter_id 809 * Meter id. 810 * @param[out] error 811 * Pointer to rte meter error structure. 812 * 813 * @return 814 * 0 on success, a negative errno value otherwise and rte_errno is set. 815 */ 816 static int 817 mlx5_flow_meter_enable(struct rte_eth_dev *dev, 818 uint32_t meter_id, 819 struct rte_mtr_error *error) 820 { 821 struct mlx5_priv *priv = dev->data->dev_private; 822 struct mlx5_flow_meter *fm; 823 int ret; 824 825 if (!priv->mtr_en) 826 return -rte_mtr_error_set(error, ENOTSUP, 827 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 828 "Meter is not support"); 829 /* Meter object must exist. */ 830 fm = mlx5_flow_meter_find(priv, meter_id); 831 if (fm == NULL) 832 return -rte_mtr_error_set(error, ENOENT, 833 RTE_MTR_ERROR_TYPE_MTR_ID, 834 NULL, "Meter not found."); 835 if (fm->active_state == MLX5_FLOW_METER_ENABLE) 836 return 0; 837 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_ENABLE, 838 error); 839 if (!ret) 840 fm->active_state = MLX5_FLOW_METER_ENABLE; 841 return ret; 842 } 843 844 /** 845 * Callback to disable flow meter. 846 * 847 * @param[in] dev 848 * Pointer to Ethernet device. 849 * @param[in] meter_id 850 * Meter id. 851 * @param[out] error 852 * Pointer to rte meter error structure. 853 * 854 * @return 855 * 0 on success, a negative errno value otherwise and rte_errno is set. 856 */ 857 static int 858 mlx5_flow_meter_disable(struct rte_eth_dev *dev, 859 uint32_t meter_id, 860 struct rte_mtr_error *error) 861 { 862 struct mlx5_priv *priv = dev->data->dev_private; 863 struct mlx5_flow_meter *fm; 864 int ret; 865 866 if (!priv->mtr_en) 867 return -rte_mtr_error_set(error, ENOTSUP, 868 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 869 "Meter is not support"); 870 /* Meter object must exist. */ 871 fm = mlx5_flow_meter_find(priv, meter_id); 872 if (fm == NULL) 873 return -rte_mtr_error_set(error, ENOENT, 874 RTE_MTR_ERROR_TYPE_MTR_ID, 875 NULL, "Meter not found."); 876 if (fm->active_state == MLX5_FLOW_METER_DISABLE) 877 return 0; 878 ret = mlx5_flow_meter_modify_state(priv, fm, MLX5_FLOW_METER_DISABLE, 879 error); 880 if (!ret) 881 fm->active_state = MLX5_FLOW_METER_DISABLE; 882 return ret; 883 } 884 885 /** 886 * Callback to update meter profile. 887 * 888 * @param[in] dev 889 * Pointer to Ethernet device. 890 * @param[in] meter_id 891 * Meter id. 892 * @param[in] meter_profile_id 893 * To be updated meter profile id. 894 * @param[out] error 895 * Pointer to rte meter error structure. 896 * 897 * @return 898 * 0 on success, a negative errno value otherwise and rte_errno is set. 899 */ 900 static int 901 mlx5_flow_meter_profile_update(struct rte_eth_dev *dev, 902 uint32_t meter_id, 903 uint32_t meter_profile_id, 904 struct rte_mtr_error *error) 905 { 906 struct mlx5_priv *priv = dev->data->dev_private; 907 struct mlx5_flow_meter_profile *fmp; 908 struct mlx5_flow_meter_profile *old_fmp; 909 struct mlx5_flow_meter *fm; 910 uint64_t modify_bits = MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CBS | 911 MLX5_FLOW_METER_OBJ_MODIFY_FIELD_CIR; 912 int ret; 913 914 if (!priv->mtr_en) 915 return -rte_mtr_error_set(error, ENOTSUP, 916 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 917 "Meter is not support"); 918 /* Meter profile must exist. */ 919 fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id); 920 if (fmp == NULL) 921 return -rte_mtr_error_set(error, ENOENT, 922 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 923 NULL, "Meter profile not found."); 924 /* Meter object must exist. */ 925 fm = mlx5_flow_meter_find(priv, meter_id); 926 if (fm == NULL) 927 return -rte_mtr_error_set(error, ENOENT, 928 RTE_MTR_ERROR_TYPE_MTR_ID, 929 NULL, "Meter not found."); 930 /* MTR object already set to meter profile id. */ 931 old_fmp = fm->profile; 932 if (fmp == old_fmp) 933 return 0; 934 /* Update the profile. */ 935 fm->profile = fmp; 936 /* Update meter params in HW (if not disabled). */ 937 if (fm->active_state == MLX5_FLOW_METER_DISABLE) 938 return 0; 939 ret = mlx5_flow_meter_action_modify(priv, fm, &fm->profile->srtcm_prm, 940 modify_bits, fm->active_state); 941 if (ret) { 942 fm->profile = old_fmp; 943 return -rte_mtr_error_set(error, -ret, 944 RTE_MTR_ERROR_TYPE_MTR_PARAMS, 945 NULL, "Failed to update meter" 946 " parmeters in hardware."); 947 } 948 old_fmp->ref_cnt--; 949 fmp->ref_cnt++; 950 return 0; 951 } 952 953 /** 954 * Callback to update meter stats mask. 955 * 956 * @param[in] dev 957 * Pointer to Ethernet device. 958 * @param[in] meter_id 959 * Meter id. 960 * @param[in] stats_mask 961 * To be updated stats_mask. 962 * @param[out] error 963 * Pointer to rte meter error structure. 964 * 965 * @return 966 * 0 on success, a negative errno value otherwise and rte_errno is set. 967 */ 968 static int 969 mlx5_flow_meter_stats_update(struct rte_eth_dev *dev, 970 uint32_t meter_id, 971 uint64_t stats_mask, 972 struct rte_mtr_error *error) 973 { 974 struct mlx5_priv *priv = dev->data->dev_private; 975 struct mlx5_flow_meter *fm; 976 977 if (!priv->mtr_en) 978 return -rte_mtr_error_set(error, ENOTSUP, 979 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 980 "Meter is not support"); 981 /* Meter object must exist. */ 982 fm = mlx5_flow_meter_find(priv, meter_id); 983 if (fm == NULL) 984 return -rte_mtr_error_set(error, ENOENT, 985 RTE_MTR_ERROR_TYPE_MTR_ID, 986 NULL, "Meter object id not valid."); 987 fm->policer_stats.stats_mask = stats_mask; 988 return 0; 989 } 990 991 /** 992 * Callback to read meter statistics. 993 * 994 * @param[in] dev 995 * Pointer to Ethernet device. 996 * @param[in] meter_id 997 * Meter id. 998 * @param[out] stats 999 * Pointer to store the statistics. 1000 * @param[out] stats_mask 1001 * Pointer to store the stats_mask. 1002 * @param[in] clear 1003 * Statistic to be cleared after read or not. 1004 * @param[out] error 1005 * Pointer to rte meter error structure. 1006 * 1007 * @return 1008 * 0 on success, a negative errno value otherwise and rte_errno is set. 1009 */ 1010 static int 1011 mlx5_flow_meter_stats_read(struct rte_eth_dev *dev, 1012 uint32_t meter_id, 1013 struct rte_mtr_stats *stats, 1014 uint64_t *stats_mask, 1015 int clear, 1016 struct rte_mtr_error *error) 1017 { 1018 static uint64_t meter2mask[RTE_MTR_DROPPED + 1] = { 1019 RTE_MTR_STATS_N_PKTS_GREEN | RTE_MTR_STATS_N_BYTES_GREEN, 1020 RTE_MTR_STATS_N_PKTS_YELLOW | RTE_MTR_STATS_N_BYTES_YELLOW, 1021 RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_BYTES_RED, 1022 RTE_MTR_STATS_N_PKTS_DROPPED | RTE_MTR_STATS_N_BYTES_DROPPED 1023 }; 1024 struct mlx5_priv *priv = dev->data->dev_private; 1025 struct mlx5_flow_meter *fm; 1026 struct mlx5_flow_policer_stats *ps; 1027 uint64_t pkts_dropped = 0; 1028 uint64_t bytes_dropped = 0; 1029 uint64_t pkts; 1030 uint64_t bytes; 1031 int i; 1032 int ret = 0; 1033 1034 if (!priv->mtr_en) 1035 return -rte_mtr_error_set(error, ENOTSUP, 1036 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 1037 "Meter is not support"); 1038 /* Meter object must exist. */ 1039 fm = mlx5_flow_meter_find(priv, meter_id); 1040 if (fm == NULL) 1041 return -rte_mtr_error_set(error, ENOENT, 1042 RTE_MTR_ERROR_TYPE_MTR_ID, 1043 NULL, "Meter object id not valid."); 1044 ps = &fm->policer_stats; 1045 *stats_mask = ps->stats_mask; 1046 for (i = 0; i < RTE_MTR_DROPPED; i++) { 1047 if (*stats_mask & meter2mask[i]) { 1048 ret = mlx5_counter_query(dev, ps->cnt[i], clear, &pkts, 1049 &bytes); 1050 if (ret) 1051 goto error; 1052 if (fm->params.action[i] == MTR_POLICER_ACTION_DROP) { 1053 pkts_dropped += pkts; 1054 bytes_dropped += bytes; 1055 } 1056 /* If need to read the packets, set it. */ 1057 if ((1 << i) & (*stats_mask & meter2mask[i])) 1058 stats->n_pkts[i] = pkts; 1059 /* If need to read the bytes, set it. */ 1060 if ((1 << (RTE_MTR_DROPPED + 1 + i)) & 1061 (*stats_mask & meter2mask[i])) 1062 stats->n_bytes[i] = bytes; 1063 } 1064 } 1065 /* Dropped packets/bytes are treated differently. */ 1066 if (*stats_mask & meter2mask[i]) { 1067 ret = mlx5_counter_query(dev, ps->cnt[i], clear, &pkts, 1068 &bytes); 1069 if (ret) 1070 goto error; 1071 pkts += pkts_dropped; 1072 bytes += bytes_dropped; 1073 /* If need to read the packets, set it. */ 1074 if ((*stats_mask & meter2mask[i]) & 1075 RTE_MTR_STATS_N_PKTS_DROPPED) 1076 stats->n_pkts_dropped = pkts; 1077 /* If need to read the bytes, set it. */ 1078 if ((*stats_mask & meter2mask[i]) & 1079 RTE_MTR_STATS_N_BYTES_DROPPED) 1080 stats->n_bytes_dropped = bytes; 1081 } 1082 return 0; 1083 error: 1084 return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL, 1085 "Failed to read policer counters."); 1086 } 1087 1088 static const struct rte_mtr_ops mlx5_flow_mtr_ops = { 1089 .capabilities_get = mlx5_flow_mtr_cap_get, 1090 .meter_profile_add = mlx5_flow_meter_profile_add, 1091 .meter_profile_delete = mlx5_flow_meter_profile_delete, 1092 .create = mlx5_flow_meter_create, 1093 .destroy = mlx5_flow_meter_destroy, 1094 .meter_enable = mlx5_flow_meter_enable, 1095 .meter_disable = mlx5_flow_meter_disable, 1096 .meter_profile_update = mlx5_flow_meter_profile_update, 1097 .meter_dscp_table_update = NULL, 1098 .policer_actions_update = NULL, 1099 .stats_update = mlx5_flow_meter_stats_update, 1100 .stats_read = mlx5_flow_meter_stats_read, 1101 }; 1102 1103 /** 1104 * Get meter operations. 1105 * 1106 * @param dev 1107 * Pointer to Ethernet device structure. 1108 * @param arg 1109 * Pointer to set the mtr operations. 1110 * 1111 * @return 1112 * Always 0. 1113 */ 1114 int 1115 mlx5_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg) 1116 { 1117 *(const struct rte_mtr_ops **)arg = &mlx5_flow_mtr_ops; 1118 return 0; 1119 } 1120 1121 /** 1122 * Find meter by id. 1123 * 1124 * @param priv 1125 * Pointer to mlx5_priv. 1126 * @param meter_id 1127 * Meter id. 1128 * 1129 * @return 1130 * Pointer to the profile found on success, NULL otherwise. 1131 */ 1132 struct mlx5_flow_meter * 1133 mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id) 1134 { 1135 struct mlx5_flow_meters *fms = &priv->flow_meters; 1136 struct mlx5_flow_meter *fm; 1137 1138 TAILQ_FOREACH(fm, fms, next) 1139 if (meter_id == fm->meter_id) 1140 return fm; 1141 return NULL; 1142 } 1143 1144 /** 1145 * Attach meter to flow. 1146 * Unidirectional Meter creation can only be done 1147 * when flow direction is known, i.e. when calling meter_attach. 1148 * 1149 * @param [in] priv 1150 * Pointer to mlx5 private data. 1151 * @param [in] meter_id 1152 * Flow meter id. 1153 * @param [in] attr 1154 * Pointer to flow attributes. 1155 * @param [out] error 1156 * Pointer to error structure. 1157 * 1158 * @return the flow meter pointer, NULL otherwise. 1159 */ 1160 struct mlx5_flow_meter * 1161 mlx5_flow_meter_attach(struct mlx5_priv *priv, uint32_t meter_id, 1162 const struct rte_flow_attr *attr, 1163 struct rte_flow_error *error) 1164 { 1165 struct mlx5_flow_meter *fm; 1166 1167 fm = mlx5_flow_meter_find(priv, meter_id); 1168 if (fm == NULL) { 1169 rte_flow_error_set(error, ENOENT, 1170 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1171 "Meter object id not valid"); 1172 goto error; 1173 } 1174 if (!fm->shared && fm->ref_cnt) { 1175 DRV_LOG(ERR, "Cannot share a non-shared meter."); 1176 rte_flow_error_set(error, EINVAL, 1177 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1178 "Meter can't be shared"); 1179 goto error; 1180 } 1181 if (!fm->ref_cnt++) { 1182 MLX5_ASSERT(!fm->mfts->meter_action); 1183 fm->attr = *attr; 1184 /* This also creates the meter object. */ 1185 fm->mfts->meter_action = mlx5_flow_meter_action_create(priv, 1186 fm); 1187 if (!fm->mfts->meter_action) 1188 goto error_detach; 1189 } else { 1190 MLX5_ASSERT(fm->mfts->meter_action); 1191 if (attr->transfer != fm->attr.transfer || 1192 attr->ingress != fm->attr.ingress || 1193 attr->egress != fm->attr.egress) { 1194 DRV_LOG(ERR, "meter I/O attributes do not " 1195 "match flow I/O attributes."); 1196 goto error_detach; 1197 } 1198 } 1199 return fm; 1200 error_detach: 1201 mlx5_flow_meter_detach(fm); 1202 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1203 fm->mfts->meter_action ? "Meter attr not match" : 1204 "Meter action create failed"); 1205 error: 1206 return NULL; 1207 } 1208 1209 /** 1210 * Detach meter from flow. 1211 * 1212 * @param [in] fm 1213 * Pointer to flow meter. 1214 */ 1215 void 1216 mlx5_flow_meter_detach(struct mlx5_flow_meter *fm) 1217 { 1218 const struct rte_flow_attr attr = { 0 }; 1219 1220 MLX5_ASSERT(fm->ref_cnt); 1221 if (--fm->ref_cnt) 1222 return; 1223 if (fm->mfts->meter_action) 1224 mlx5_glue->destroy_flow_action(fm->mfts->meter_action); 1225 fm->mfts->meter_action = NULL; 1226 fm->attr = attr; 1227 } 1228 1229 /** 1230 * Flush meter configuration. 1231 * 1232 * @param[in] dev 1233 * Pointer to Ethernet device. 1234 * @param[out] error 1235 * Pointer to rte meter error structure. 1236 * 1237 * @return 1238 * 0 on success, a negative errno value otherwise and rte_errno is set. 1239 */ 1240 int 1241 mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error) 1242 { 1243 struct mlx5_priv *priv = dev->data->dev_private; 1244 struct mlx5_flow_meters *fms = &priv->flow_meters; 1245 struct mlx5_mtr_profiles *fmps = &priv->flow_meter_profiles; 1246 struct mlx5_flow_meter_profile *fmp; 1247 struct mlx5_flow_meter *fm; 1248 const struct rte_flow_attr attr = { 1249 .ingress = 1, 1250 .egress = 1, 1251 .transfer = priv->config.dv_esw_en ? 1 : 0, 1252 }; 1253 void *tmp; 1254 uint32_t i; 1255 1256 TAILQ_FOREACH_SAFE(fm, fms, next, tmp) { 1257 /* Meter object must not have any owner. */ 1258 MLX5_ASSERT(!fm->ref_cnt); 1259 /* Get meter profile. */ 1260 fmp = fm->profile; 1261 if (fmp == NULL) 1262 return -rte_mtr_error_set(error, EINVAL, 1263 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 1264 NULL, "MTR object meter profile invalid."); 1265 /* Update dependencies. */ 1266 fmp->ref_cnt--; 1267 /* Remove from list. */ 1268 TAILQ_REMOVE(fms, fm, next); 1269 /* Free policer counters. */ 1270 for (i = 0; i < RTE_DIM(fm->policer_stats.cnt); i++) 1271 if (fm->policer_stats.cnt[i]) 1272 mlx5_counter_free(dev, 1273 fm->policer_stats.cnt[i]); 1274 /* Free meter flow table. */ 1275 mlx5_flow_destroy_policer_rules(dev, fm, &attr); 1276 mlx5_flow_destroy_mtr_tbls(dev, fm->mfts); 1277 rte_free(fm); 1278 } 1279 TAILQ_FOREACH_SAFE(fmp, fmps, next, tmp) { 1280 /* Check unused. */ 1281 MLX5_ASSERT(!fmp->ref_cnt); 1282 /* Remove from list. */ 1283 TAILQ_REMOVE(&priv->flow_meter_profiles, fmp, next); 1284 rte_free(fmp); 1285 } 1286 return 0; 1287 } 1288