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