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