1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(C) 2021 Marvell. 3 */ 4 5 #include "cnxk_ethdev.h" 6 #include <rte_mtr_driver.h> 7 8 #define NIX_MTR_COUNT_MAX 73 /* 64(leaf) + 8(mid) + 1(top) */ 9 #define NIX_MTR_COUNT_PER_FLOW 3 /* 1(leaf) + 1(mid) + 1(top) */ 10 11 #define NIX_BPF_STATS_MASK_ALL \ 12 { \ 13 ROC_NIX_BPF_GREEN_PKT_F_PASS | ROC_NIX_BPF_GREEN_OCTS_F_PASS | \ 14 ROC_NIX_BPF_GREEN_PKT_F_DROP | \ 15 ROC_NIX_BPF_GREEN_OCTS_F_DROP | \ 16 ROC_NIX_BPF_YELLOW_PKT_F_PASS | \ 17 ROC_NIX_BPF_YELLOW_OCTS_F_PASS | \ 18 ROC_NIX_BPF_YELLOW_PKT_F_DROP | \ 19 ROC_NIX_BPF_YELLOW_OCTS_F_DROP | \ 20 ROC_NIX_BPF_RED_PKT_F_PASS | \ 21 ROC_NIX_BPF_RED_OCTS_F_PASS | \ 22 ROC_NIX_BPF_RED_PKT_F_DROP | \ 23 ROC_NIX_BPF_RED_OCTS_F_DROP \ 24 } 25 26 static const enum roc_nix_bpf_level_flag lvl_map[] = {ROC_NIX_BPF_LEVEL_F_LEAF, 27 ROC_NIX_BPF_LEVEL_F_MID, 28 ROC_NIX_BPF_LEVEL_F_TOP}; 29 30 static struct rte_mtr_capabilities mtr_capa = { 31 .n_shared_max = NIX_MTR_COUNT_PER_FLOW, 32 /* .identical = , */ 33 .shared_identical = true, 34 /* .shared_n_flows_per_mtr_max = ,*/ 35 .chaining_n_mtrs_per_flow_max = NIX_MTR_COUNT_PER_FLOW, 36 .chaining_use_prev_mtr_color_supported = true, 37 .chaining_use_prev_mtr_color_enforced = true, 38 .meter_rate_max = NIX_BPF_RATE_MAX / 8, /* Bytes per second */ 39 .color_aware_srtcm_rfc2697_supported = true, 40 .color_aware_trtcm_rfc2698_supported = true, 41 .color_aware_trtcm_rfc4115_supported = true, 42 .srtcm_rfc2697_byte_mode_supported = true, 43 .srtcm_rfc2697_packet_mode_supported = true, 44 .trtcm_rfc2698_byte_mode_supported = true, 45 .trtcm_rfc2698_packet_mode_supported = true, 46 .trtcm_rfc4115_byte_mode_supported = true, 47 .trtcm_rfc4115_packet_mode_supported = true, 48 .stats_mask = RTE_MTR_STATS_N_PKTS_GREEN | RTE_MTR_STATS_N_PKTS_YELLOW | 49 RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_PKTS_DROPPED | 50 RTE_MTR_STATS_N_BYTES_GREEN | 51 RTE_MTR_STATS_N_BYTES_YELLOW | RTE_MTR_STATS_N_BYTES_RED | 52 RTE_MTR_STATS_N_BYTES_DROPPED}; 53 54 static struct cnxk_meter_node * 55 nix_mtr_find(struct cnxk_eth_dev *dev, uint32_t meter_id) 56 { 57 struct cnxk_mtr *fms = &dev->mtr; 58 struct cnxk_meter_node *fm; 59 60 TAILQ_FOREACH(fm, fms, next) 61 if (meter_id == fm->id) 62 return fm; 63 return NULL; 64 } 65 66 static struct cnxk_mtr_profile_node * 67 nix_mtr_profile_find(struct cnxk_eth_dev *dev, uint32_t profile_id) 68 { 69 struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles; 70 struct cnxk_mtr_profile_node *fmp; 71 72 TAILQ_FOREACH(fmp, fmps, next) 73 if (profile_id == fmp->id) 74 return fmp; 75 76 return NULL; 77 } 78 79 static struct cnxk_mtr_policy_node * 80 nix_mtr_policy_find(struct cnxk_eth_dev *dev, uint32_t meter_policy_id) 81 { 82 struct cnxk_mtr_policy *fmps = &dev->mtr_policy; 83 struct cnxk_mtr_policy_node *fmp; 84 85 TAILQ_FOREACH(fmp, fmps, next) 86 if (meter_policy_id == fmp->id) 87 return fmp; 88 return NULL; 89 } 90 91 static int 92 nix_mtr_profile_validate(struct cnxk_eth_dev *dev, uint32_t profile_id, 93 struct rte_mtr_meter_profile *profile, 94 struct rte_mtr_error *error) 95 { 96 int rc = 0; 97 98 PLT_SET_USED(dev); 99 100 if (profile == NULL) 101 return -rte_mtr_error_set(error, EINVAL, 102 RTE_MTR_ERROR_TYPE_METER_PROFILE, 103 NULL, "Meter profile is null."); 104 105 if (profile_id == UINT32_MAX) 106 return -rte_mtr_error_set(error, EINVAL, 107 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 108 NULL, "Meter profile id not valid."); 109 110 switch (profile->alg) { 111 case RTE_MTR_SRTCM_RFC2697: 112 if (profile->srtcm_rfc2697.cir > mtr_capa.meter_rate_max) 113 rc = -rte_mtr_error_set(error, EINVAL, 114 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, 115 "CIR exceeds max meter rate"); 116 117 if (profile->srtcm_rfc2697.cbs > NIX_BPF_BURST_MAX) 118 rc = -rte_mtr_error_set(error, EINVAL, 119 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, 120 "CBS exceeds max meter burst size"); 121 122 if (profile->srtcm_rfc2697.ebs > NIX_BPF_BURST_MAX) 123 rc = -rte_mtr_error_set(error, EINVAL, 124 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, 125 "EBS exceeds max meter burst size"); 126 break; 127 128 case RTE_MTR_TRTCM_RFC2698: 129 if (profile->trtcm_rfc2698.cir > mtr_capa.meter_rate_max) 130 rc = -rte_mtr_error_set(error, EINVAL, 131 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, 132 "CIR exceeds max meter rate"); 133 134 if (profile->trtcm_rfc2698.pir > mtr_capa.meter_rate_max) 135 rc = -rte_mtr_error_set(error, EINVAL, 136 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, 137 "PIR exceeds max meter rate"); 138 139 if (profile->trtcm_rfc2698.cbs > NIX_BPF_BURST_MAX) 140 rc = -rte_mtr_error_set(error, EINVAL, 141 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, 142 "CBS exceeds max meter burst size"); 143 144 if (profile->trtcm_rfc2698.pbs > NIX_BPF_BURST_MAX) 145 rc = -rte_mtr_error_set(error, EINVAL, 146 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, 147 "PBS exceeds max meter burst size"); 148 break; 149 150 case RTE_MTR_TRTCM_RFC4115: 151 if ((profile->trtcm_rfc4115.cir + profile->trtcm_rfc4115.eir) > 152 mtr_capa.meter_rate_max) 153 rc = -rte_mtr_error_set(error, EINVAL, 154 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, 155 "PIR + EIR exceeds max rate"); 156 157 if (profile->trtcm_rfc4115.cbs > NIX_BPF_BURST_MAX) 158 rc = -rte_mtr_error_set(error, EINVAL, 159 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, 160 "CBS exceeds max meter burst size"); 161 162 if (profile->trtcm_rfc4115.ebs > NIX_BPF_BURST_MAX) 163 rc = -rte_mtr_error_set(error, EINVAL, 164 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, 165 "PBS exceeds max meter burst size"); 166 break; 167 168 default: 169 rc = -rte_mtr_error_set(error, EINVAL, 170 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, 171 "alg is invalid"); 172 break; 173 } 174 175 return rc; 176 } 177 178 static int 179 cnxk_nix_mtr_capabilities_get(struct rte_eth_dev *dev, 180 struct rte_mtr_capabilities *capa, 181 struct rte_mtr_error *error) 182 { 183 struct cnxk_eth_dev *eth_dev = cnxk_eth_pmd_priv(dev); 184 uint16_t count[ROC_NIX_BPF_LEVEL_MAX] = {0}; 185 uint8_t lvl_mask = ROC_NIX_BPF_LEVEL_F_LEAF | ROC_NIX_BPF_LEVEL_F_MID | 186 ROC_NIX_BPF_LEVEL_F_TOP; 187 struct roc_nix *nix = ð_dev->nix; 188 int rc; 189 int i; 190 191 RTE_SET_USED(dev); 192 193 if (!capa) 194 return -rte_mtr_error_set(error, EINVAL, 195 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 196 "NULL input parameter"); 197 198 rc = roc_nix_bpf_count_get(nix, lvl_mask, count); 199 if (rc) 200 return rc; 201 202 for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) 203 mtr_capa.n_max += count[i]; 204 205 mtr_capa.meter_srtcm_rfc2697_n_max = mtr_capa.n_max; 206 mtr_capa.meter_trtcm_rfc2698_n_max = mtr_capa.n_max; 207 mtr_capa.meter_trtcm_rfc4115_n_max = mtr_capa.n_max; 208 mtr_capa.meter_policy_n_max = mtr_capa.n_max; 209 210 *capa = mtr_capa; 211 return 0; 212 } 213 214 static int 215 cnxk_nix_mtr_profile_add(struct rte_eth_dev *eth_dev, uint32_t profile_id, 216 struct rte_mtr_meter_profile *profile, 217 struct rte_mtr_error *error) 218 { 219 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 220 struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles; 221 struct cnxk_mtr_profile_node *fmp; 222 int ret; 223 224 /* Check input params. */ 225 ret = nix_mtr_profile_validate(dev, profile_id, profile, error); 226 if (ret) 227 return ret; 228 229 fmp = nix_mtr_profile_find(dev, profile_id); 230 if (fmp) { 231 return -rte_mtr_error_set(error, EEXIST, 232 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 233 NULL, "Profile already exist"); 234 } 235 236 fmp = plt_zmalloc(sizeof(struct cnxk_mtr_profile_node), ROC_ALIGN); 237 if (fmp == NULL) 238 return -rte_mtr_error_set(error, ENOMEM, 239 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 240 "Meter profile memory " 241 "alloc failed."); 242 243 fmp->id = profile_id; 244 fmp->profile = *profile; 245 246 TAILQ_INSERT_TAIL(fmps, fmp, next); 247 248 return 0; 249 } 250 251 static int 252 cnxk_nix_mtr_profile_delete(struct rte_eth_dev *eth_dev, uint32_t profile_id, 253 struct rte_mtr_error *error) 254 { 255 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 256 struct cnxk_mtr_profile_node *fmp; 257 258 if (profile_id == UINT32_MAX) 259 return -rte_mtr_error_set(error, EINVAL, 260 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 261 NULL, "Meter profile id not valid."); 262 263 fmp = nix_mtr_profile_find(dev, profile_id); 264 if (fmp == NULL) 265 return -rte_mtr_error_set(error, ENOENT, 266 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 267 &profile_id, 268 "Meter profile is invalid."); 269 270 if (fmp->ref_cnt) 271 return -rte_mtr_error_set(error, EBUSY, 272 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 273 NULL, "Meter profile is in use."); 274 275 TAILQ_REMOVE(&dev->mtr_profiles, fmp, next); 276 plt_free(fmp); 277 return 0; 278 } 279 280 static int 281 cnxk_nix_mtr_policy_validate(struct rte_eth_dev *dev, 282 struct rte_mtr_meter_policy_params *policy, 283 struct rte_mtr_error *error) 284 { 285 static const char *const action_color[] = {"Green", "Yellow", "Red"}; 286 bool supported[RTE_COLORS] = {false, false, false}; 287 const struct rte_flow_action *action; 288 char message[1024]; 289 uint32_t i; 290 291 RTE_SET_USED(dev); 292 293 if (!policy) 294 return 0; /* Nothing to be validated */ 295 296 for (i = 0; i < RTE_COLORS; i++) { 297 if (policy->actions[i]) { 298 for (action = policy->actions[i]; 299 action->type != RTE_FLOW_ACTION_TYPE_END; 300 action++) { 301 if (action->type == RTE_FLOW_ACTION_TYPE_METER) 302 supported[i] = true; 303 304 if (action->type == RTE_FLOW_ACTION_TYPE_DROP) 305 supported[i] = true; 306 307 if (!supported[i]) { 308 sprintf(message, 309 "%s action is not valid", 310 action_color[i]); 311 return -rte_mtr_error_set(error, 312 ENOTSUP, 313 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, 314 message); 315 } 316 } 317 } else { 318 sprintf(message, "%s action is null", action_color[i]); 319 return -rte_mtr_error_set(error, EINVAL, 320 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, 321 message); 322 } 323 } 324 325 return 0; 326 } 327 328 static void 329 cnxk_fill_policy_actions(struct cnxk_mtr_policy_node *fmp, 330 struct rte_mtr_meter_policy_params *policy) 331 332 { 333 const struct rte_flow_action_meter *mtr; 334 const struct rte_flow_action *action; 335 int i; 336 337 for (i = 0; i < RTE_COLORS; i++) { 338 if (policy->actions[i]) { 339 for (action = policy->actions[i]; 340 action->type != RTE_FLOW_ACTION_TYPE_END; 341 action++) { 342 if (action->type == 343 RTE_FLOW_ACTION_TYPE_METER) { 344 fmp->actions[i].action_fate = 345 action->type; 346 mtr = (const struct 347 rte_flow_action_meter *) 348 action->conf; 349 fmp->actions[i].mtr_id = mtr->mtr_id; 350 } 351 352 if (action->type == RTE_FLOW_ACTION_TYPE_DROP) { 353 fmp->actions[i].action_fate = 354 action->type; 355 } 356 } 357 } 358 } 359 } 360 361 static int 362 cnxk_nix_mtr_policy_add(struct rte_eth_dev *eth_dev, uint32_t policy_id, 363 struct rte_mtr_meter_policy_params *policy, 364 struct rte_mtr_error *error) 365 { 366 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 367 struct cnxk_mtr_policy *fmps = &dev->mtr_policy; 368 struct cnxk_mtr_policy_node *fmp; 369 int rc; 370 371 fmp = nix_mtr_policy_find(dev, policy_id); 372 if (fmp) { 373 return -rte_mtr_error_set(error, EEXIST, 374 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 375 NULL, "Policy already exist"); 376 } 377 378 fmp = plt_zmalloc(sizeof(struct cnxk_mtr_policy_node), ROC_ALIGN); 379 if (fmp == NULL) { 380 return -rte_mtr_error_set(error, ENOMEM, 381 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 382 "Memory allocation failure"); 383 } else { 384 rc = cnxk_nix_mtr_policy_validate(eth_dev, policy, error); 385 if (rc) 386 goto exit; 387 } 388 389 fmp->id = policy_id; 390 cnxk_fill_policy_actions(fmp, policy); 391 TAILQ_INSERT_TAIL(fmps, fmp, next); 392 return 0; 393 394 exit: 395 plt_free(fmp); 396 return rc; 397 } 398 399 static int 400 cnxk_nix_mtr_policy_delete(struct rte_eth_dev *eth_dev, uint32_t policy_id, 401 struct rte_mtr_error *error) 402 { 403 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 404 struct cnxk_mtr_policy_node *fmp; 405 406 fmp = nix_mtr_policy_find(dev, policy_id); 407 if (fmp == NULL) { 408 return -rte_mtr_error_set(error, ENOENT, 409 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 410 NULL, "No policy found"); 411 } 412 413 if (fmp->ref_cnt) 414 return -rte_mtr_error_set(error, EBUSY, 415 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 416 NULL, "Meter policy is in use."); 417 418 TAILQ_REMOVE(&dev->mtr_policy, fmp, next); 419 plt_free(fmp); 420 421 return 0; 422 } 423 424 static int 425 cnxk_nix_mtr_create(struct rte_eth_dev *eth_dev, uint32_t mtr_id, 426 struct rte_mtr_params *params, int shared, 427 struct rte_mtr_error *error) 428 { 429 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 430 struct cnxk_mtr_profile_node *profile; 431 struct cnxk_mtr_policy_node *policy; 432 struct cnxk_mtr *fm = &dev->mtr; 433 struct cnxk_meter_node *mtr; 434 int i; 435 436 RTE_SET_USED(shared); 437 438 if (params == NULL) 439 return -rte_mtr_error_set(error, ENOENT, 440 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 441 "Meter params are invalid."); 442 443 profile = nix_mtr_profile_find(dev, params->meter_profile_id); 444 if (profile == NULL) 445 return -rte_mtr_error_set(error, ENOENT, 446 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, 447 ¶ms->meter_profile_id, 448 "Meter profile is invalid."); 449 450 policy = nix_mtr_policy_find(dev, params->meter_policy_id); 451 if (policy == NULL) 452 return -rte_mtr_error_set(error, ENOENT, 453 RTE_MTR_ERROR_TYPE_METER_POLICY_ID, 454 ¶ms->meter_policy_id, 455 "Meter policy is invalid."); 456 457 mtr = nix_mtr_find(dev, mtr_id); 458 if (mtr) { 459 return -rte_mtr_error_set(error, EEXIST, 460 RTE_MTR_ERROR_TYPE_MTR_ID, NULL, 461 "Meter already exist"); 462 } 463 464 mtr = plt_zmalloc(sizeof(struct cnxk_meter_node), ROC_ALIGN); 465 if (mtr == NULL) { 466 return -rte_mtr_error_set(error, ENOMEM, 467 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 468 "Meter memory alloc failed."); 469 } 470 471 mtr->id = mtr_id; 472 mtr->profile = profile; 473 mtr->policy = policy; 474 mtr->params = *params; 475 mtr->bpf_id = ROC_NIX_BPF_ID_INVALID; 476 mtr->prev_cnt = 0; 477 for (i = 0; i < MAX_PRV_MTR_NODES; i++) 478 mtr->prev_id[i] = ROC_NIX_BPF_ID_INVALID; 479 480 mtr->next_id = ROC_NIX_BPF_ID_INVALID; 481 mtr->is_next = false; 482 mtr->level = ROC_NIX_BPF_LEVEL_IDX_INVALID; 483 484 if (params->dscp_table) { 485 mtr->params.dscp_table = 486 plt_zmalloc(ROC_NIX_BPF_PRE_COLOR_MAX, ROC_ALIGN); 487 if (mtr->params.dscp_table == NULL) { 488 plt_free(mtr); 489 return -rte_mtr_error_set(error, ENOMEM, 490 RTE_MTR_ERROR_TYPE_UNSPECIFIED, 491 NULL, "Memory alloc failed."); 492 } 493 494 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++) 495 mtr->params.dscp_table[i] = params->dscp_table[i]; 496 } 497 498 profile->ref_cnt++; 499 policy->ref_cnt++; 500 TAILQ_INSERT_TAIL(fm, mtr, next); 501 return 0; 502 } 503 504 static int 505 cnxk_nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t mtr_id, 506 struct rte_mtr_error *error) 507 { 508 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 509 struct roc_nix_bpf_objs profs = {0}; 510 struct cnxk_mtr *fm = &dev->mtr; 511 struct roc_nix *nix = &dev->nix; 512 struct cnxk_meter_node *mtr; 513 struct cnxk_meter_node *mid_mtr; 514 struct cnxk_meter_node *top_mtr; 515 int rc = 0; 516 517 mtr = nix_mtr_find(dev, mtr_id); 518 if (mtr == NULL) { 519 return -rte_mtr_error_set(error, ENOENT, 520 RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id, 521 "Meter id is invalid."); 522 } 523 524 if (mtr->ref_cnt) { 525 return -rte_mtr_error_set(error, EADDRINUSE, 526 RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id, 527 "Meter id in use."); 528 } 529 530 switch (lvl_map[mtr->level]) { 531 case ROC_NIX_BPF_LEVEL_F_LEAF: 532 if (mtr->is_next) { 533 rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF, 534 mtr->bpf_id, 535 ROC_NIX_BPF_ID_INVALID); 536 } 537 break; 538 case ROC_NIX_BPF_LEVEL_F_MID: 539 while ((mtr->prev_cnt) + 1) { 540 mid_mtr = 541 nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]); 542 rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF, 543 mid_mtr->bpf_id, 544 ROC_NIX_BPF_ID_INVALID); 545 mtr->prev_cnt--; 546 } 547 if (mtr->is_next) { 548 rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID, 549 mtr->bpf_id, 550 ROC_NIX_BPF_ID_INVALID); 551 } 552 break; 553 case ROC_NIX_BPF_LEVEL_F_TOP: 554 while (mtr->prev_cnt) { 555 top_mtr = 556 nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]); 557 rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID, 558 top_mtr->bpf_id, 559 ROC_NIX_BPF_ID_INVALID); 560 mtr->prev_cnt--; 561 } 562 break; 563 default: 564 return -rte_mtr_error_set(error, EINVAL, 565 RTE_MTR_ERROR_TYPE_MTR_ID, NULL, 566 "Invalid meter level"); 567 } 568 569 if (rc) 570 goto exit; 571 572 profs.level = mtr->level; 573 profs.count = 1; 574 profs.ids[0] = mtr->bpf_id; 575 rc = roc_nix_bpf_free(nix, &profs, 1); 576 if (rc) 577 goto exit; 578 579 mtr->policy->ref_cnt--; 580 mtr->profile->ref_cnt--; 581 TAILQ_REMOVE(fm, mtr, next); 582 plt_free(mtr->params.dscp_table); 583 plt_free(mtr); 584 585 exit: 586 return rc; 587 } 588 589 static int 590 cnxk_nix_mtr_enable(struct rte_eth_dev *eth_dev, uint32_t mtr_id, 591 struct rte_mtr_error *error) 592 { 593 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 594 struct roc_nix *nix = &dev->nix; 595 struct cnxk_meter_node *mtr; 596 struct roc_nix_rq *rq; 597 uint32_t i; 598 int rc = 0; 599 600 mtr = nix_mtr_find(dev, mtr_id); 601 if (mtr == NULL) { 602 return -rte_mtr_error_set(error, ENOENT, 603 RTE_MTR_ERROR_TYPE_MTR_ID, NULL, 604 "Meter id is invalid."); 605 } 606 607 if (mtr->level != 0) 608 return 0; 609 610 for (i = 0; i < mtr->rq_num; i++) { 611 rq = &dev->rqs[mtr->rq_id[i]]; 612 rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, true); 613 } 614 615 return rc; 616 } 617 618 static int 619 cnxk_nix_mtr_disable(struct rte_eth_dev *eth_dev, uint32_t mtr_id, 620 struct rte_mtr_error *error) 621 { 622 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 623 struct roc_nix *nix = &dev->nix; 624 struct cnxk_meter_node *mtr; 625 struct roc_nix_rq *rq; 626 uint32_t i; 627 int rc = 0; 628 629 mtr = nix_mtr_find(dev, mtr_id); 630 if (mtr == NULL) { 631 return -rte_mtr_error_set(error, ENOENT, 632 RTE_MTR_ERROR_TYPE_MTR_ID, NULL, 633 "Meter id is invalid."); 634 } 635 636 if (mtr->level != 0) 637 return 0; 638 639 for (i = 0; i < mtr->rq_num; i++) { 640 rq = &dev->rqs[mtr->rq_id[i]]; 641 rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, false); 642 } 643 644 return rc; 645 } 646 647 static int 648 cnxk_nix_mtr_dscp_table_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id, 649 enum rte_color *dscp_table, 650 struct rte_mtr_error *error) 651 { 652 enum roc_nix_bpf_color nix_dscp_tbl[ROC_NIX_BPF_PRE_COLOR_MAX]; 653 enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN, 654 ROC_NIX_BPF_COLOR_YELLOW, 655 ROC_NIX_BPF_COLOR_RED}; 656 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 657 struct roc_nix_bpf_precolor table; 658 struct roc_nix *nix = &dev->nix; 659 struct cnxk_meter_node *mtr; 660 int rc, i; 661 662 mtr = nix_mtr_find(dev, mtr_id); 663 if (mtr == NULL) { 664 return -rte_mtr_error_set(error, ENOENT, 665 RTE_MTR_ERROR_TYPE_MTR_ID, NULL, 666 "Meter object not found"); 667 } 668 669 if (!dscp_table) { 670 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++) 671 nix_dscp_tbl[i] = ROC_NIX_BPF_COLOR_GREEN; 672 } else { 673 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++) 674 nix_dscp_tbl[i] = color_map[dscp_table[i]]; 675 } 676 677 table.count = ROC_NIX_BPF_PRE_COLOR_MAX; 678 table.mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER; 679 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++) 680 table.color[i] = nix_dscp_tbl[i]; 681 682 rc = roc_nix_bpf_pre_color_tbl_setup(nix, mtr->bpf_id, 683 lvl_map[mtr->level], &table); 684 if (rc) { 685 rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED, 686 NULL, NULL); 687 goto exit; 688 } 689 690 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++) 691 dev->precolor_tbl[i] = nix_dscp_tbl[i]; 692 693 exit: 694 return rc; 695 } 696 697 static int 698 cnxk_nix_mtr_stats_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id, 699 uint64_t stats_mask, struct rte_mtr_error *error) 700 { 701 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 702 struct cnxk_meter_node *mtr; 703 704 if (!stats_mask) 705 return -rte_mtr_error_set(error, EINVAL, 706 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 707 "no bit is set to stats mask"); 708 709 mtr = nix_mtr_find(dev, mtr_id); 710 if (mtr == NULL) { 711 return -rte_mtr_error_set(error, ENOENT, 712 RTE_MTR_ERROR_TYPE_MTR_ID, NULL, 713 "Meter object not found"); 714 } 715 716 mtr->params.stats_mask = stats_mask; 717 return 0; 718 } 719 720 static int 721 cnxk_nix_mtr_stats_read(struct rte_eth_dev *eth_dev, uint32_t mtr_id, 722 struct rte_mtr_stats *stats, uint64_t *stats_mask, 723 int clear, struct rte_mtr_error *error) 724 { 725 uint8_t yellow_pkt_pass, yellow_octs_pass, yellow_pkt_drop; 726 uint8_t green_octs_drop, yellow_octs_drop, red_octs_drop; 727 uint8_t green_pkt_pass, green_octs_pass, green_pkt_drop; 728 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 729 uint8_t red_pkt_pass, red_octs_pass, red_pkt_drop; 730 uint64_t bpf_stats[ROC_NIX_BPF_STATS_MAX] = {0}; 731 uint64_t mask = NIX_BPF_STATS_MASK_ALL; 732 struct roc_nix *nix = &dev->nix; 733 struct cnxk_meter_node *mtr; 734 int rc; 735 736 if (!stats) 737 return -rte_mtr_error_set(error, EINVAL, 738 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, 739 "stats pointer is NULL"); 740 741 mtr = nix_mtr_find(dev, mtr_id); 742 if (mtr == NULL) { 743 return -rte_mtr_error_set(error, ENOENT, 744 RTE_MTR_ERROR_TYPE_MTR_ID, NULL, 745 "Meter object not found"); 746 } 747 748 rc = roc_nix_bpf_stats_read(nix, mtr->bpf_id, mask, lvl_map[mtr->level], 749 bpf_stats); 750 if (rc) { 751 rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED, 752 NULL, NULL); 753 goto exit; 754 } 755 756 green_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_PASS); 757 green_octs_pass = 758 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_PASS); 759 green_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_DROP); 760 green_octs_drop = 761 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_DROP); 762 yellow_pkt_pass = 763 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_PASS); 764 yellow_octs_pass = 765 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_PASS); 766 yellow_pkt_drop = 767 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_DROP); 768 yellow_octs_drop = 769 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_DROP); 770 red_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_PASS); 771 red_octs_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_PASS); 772 red_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_DROP); 773 red_octs_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_DROP); 774 775 if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_GREEN) 776 stats->n_pkts[RTE_COLOR_GREEN] = bpf_stats[green_pkt_pass]; 777 778 if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_YELLOW) 779 stats->n_pkts[RTE_COLOR_YELLOW] = bpf_stats[yellow_pkt_pass]; 780 781 if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_RED) 782 stats->n_pkts[RTE_COLOR_RED] = bpf_stats[red_pkt_pass]; 783 784 if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_GREEN) 785 stats->n_bytes[RTE_COLOR_GREEN] = bpf_stats[green_octs_pass]; 786 787 if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_YELLOW) 788 stats->n_bytes[RTE_COLOR_YELLOW] = bpf_stats[yellow_octs_pass]; 789 790 if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_RED) 791 stats->n_bytes[RTE_COLOR_RED] = bpf_stats[red_octs_pass]; 792 793 if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED) 794 stats->n_pkts_dropped = bpf_stats[green_pkt_drop] + 795 bpf_stats[yellow_pkt_drop] + 796 bpf_stats[red_pkt_drop]; 797 798 if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) 799 stats->n_bytes_dropped = bpf_stats[green_octs_drop] + 800 bpf_stats[yellow_octs_drop] + 801 bpf_stats[red_octs_drop]; 802 803 if (stats_mask) 804 *stats_mask = mtr->params.stats_mask; 805 806 if (clear) { 807 rc = roc_nix_bpf_stats_reset(nix, mtr->bpf_id, mask, 808 lvl_map[mtr->level]); 809 if (rc) { 810 rte_mtr_error_set(error, rc, 811 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, 812 NULL); 813 goto exit; 814 } 815 } 816 817 exit: 818 return rc; 819 } 820 821 const struct rte_mtr_ops nix_mtr_ops = { 822 .capabilities_get = cnxk_nix_mtr_capabilities_get, 823 .meter_profile_add = cnxk_nix_mtr_profile_add, 824 .meter_profile_delete = cnxk_nix_mtr_profile_delete, 825 .meter_policy_validate = cnxk_nix_mtr_policy_validate, 826 .meter_policy_add = cnxk_nix_mtr_policy_add, 827 .meter_policy_delete = cnxk_nix_mtr_policy_delete, 828 .create = cnxk_nix_mtr_create, 829 .destroy = cnxk_nix_mtr_destroy, 830 .meter_enable = cnxk_nix_mtr_enable, 831 .meter_disable = cnxk_nix_mtr_disable, 832 .meter_dscp_table_update = cnxk_nix_mtr_dscp_table_update, 833 .stats_update = cnxk_nix_mtr_stats_update, 834 .stats_read = cnxk_nix_mtr_stats_read, 835 }; 836 837 int 838 cnxk_nix_mtr_ops_get(struct rte_eth_dev *dev, void *ops) 839 { 840 RTE_SET_USED(dev); 841 842 *(const void **)ops = &nix_mtr_ops; 843 return 0; 844 } 845 846 int 847 nix_mtr_validate(struct rte_eth_dev *eth_dev, uint32_t id) 848 { 849 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 850 struct cnxk_mtr_profile_node *profile; 851 struct cnxk_mtr_policy_node *policy; 852 struct cnxk_meter_node *mtr; 853 854 mtr = nix_mtr_find(dev, id); 855 if (mtr == NULL) 856 return -EINVAL; 857 858 profile = nix_mtr_profile_find(dev, mtr->params.meter_profile_id); 859 if (profile == NULL) 860 return -EINVAL; 861 862 policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id); 863 if (policy == NULL) 864 return -EINVAL; 865 866 return 0; 867 } 868 869 int 870 nix_mtr_policy_act_get(struct rte_eth_dev *eth_dev, uint32_t id, 871 struct cnxk_mtr_policy_node **policy_act) 872 { 873 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 874 struct cnxk_mtr_policy_node *policy; 875 struct cnxk_meter_node *mtr; 876 877 mtr = nix_mtr_find(dev, id); 878 if (mtr == NULL) 879 return -EINVAL; 880 881 policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id); 882 if (policy == NULL) 883 return -EINVAL; 884 885 *policy_act = policy; 886 887 return 0; 888 } 889 890 int 891 nix_mtr_rq_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t queue_num, 892 const uint16_t *queue) 893 { 894 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 895 struct cnxk_meter_node *mtr; 896 uint32_t i; 897 898 mtr = nix_mtr_find(dev, id); 899 if (mtr == NULL) 900 return -EINVAL; 901 902 mtr->rq_id = plt_zmalloc(queue_num * sizeof(uint32_t), ROC_ALIGN); 903 if (mtr->rq_id == NULL) 904 return -ENOMEM; 905 906 mtr->rq_num = queue_num; 907 for (i = 0; i < queue_num; i++) 908 mtr->rq_id[i] = queue[i]; 909 910 return 0; 911 } 912 913 int 914 nix_mtr_chain_reset(struct rte_eth_dev *eth_dev, uint32_t cur_id) 915 { 916 struct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0}; 917 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 918 uint32_t mtr_id = cur_id; 919 int i = 0, j = 0; 920 921 for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) { 922 mtr[i] = nix_mtr_find(dev, mtr_id); 923 if (mtr[i]) 924 mtr_id = mtr[i]->next_id; 925 } 926 for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) { 927 if (mtr[i]) { 928 for (j = 0; j < MAX_PRV_MTR_NODES; j++) 929 mtr[i]->prev_id[i] = ROC_NIX_BPF_ID_INVALID; 930 mtr[i]->level = ROC_NIX_BPF_LEVEL_IDX_INVALID; 931 mtr[i]->next_id = ROC_NIX_BPF_ID_INVALID; 932 mtr[i]->is_next = false; 933 mtr[i]->prev_cnt = 0; 934 } 935 } 936 return 0; 937 } 938 939 int 940 nix_mtr_chain_update(struct rte_eth_dev *eth_dev, uint32_t cur_id, 941 uint32_t prev_id, uint32_t next_id) 942 { 943 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 944 struct cnxk_meter_node *mtr; 945 946 mtr = nix_mtr_find(dev, cur_id); 947 if (mtr == NULL) 948 return -EINVAL; 949 950 switch (lvl_map[mtr->level]) { 951 case ROC_NIX_BPF_LEVEL_F_LEAF: 952 mtr->prev_id[mtr->prev_cnt] = ROC_NIX_BPF_ID_INVALID; 953 mtr->next_id = next_id; 954 mtr->is_next = true; 955 break; 956 case ROC_NIX_BPF_LEVEL_F_MID: 957 mtr->prev_id[mtr->prev_cnt] = prev_id; 958 mtr->next_id = next_id; 959 mtr->is_next = true; 960 break; 961 case ROC_NIX_BPF_LEVEL_F_TOP: 962 mtr->prev_id[mtr->prev_cnt] = prev_id; 963 mtr->next_id = ROC_NIX_BPF_ID_INVALID; 964 mtr->is_next = false; 965 break; 966 default: 967 plt_err("Invalid meter level"); 968 return -EINVAL; 969 } 970 971 return 0; 972 } 973 974 struct cnxk_meter_node * 975 nix_get_mtr(struct rte_eth_dev *eth_dev, uint32_t id) 976 { 977 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 978 struct cnxk_meter_node *mtr; 979 980 mtr = nix_mtr_find(dev, id); 981 if (mtr == NULL) 982 return NULL; 983 984 return mtr; 985 } 986 987 int 988 nix_mtr_level_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t level) 989 { 990 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 991 struct cnxk_meter_node *mtr; 992 993 mtr = nix_mtr_find(dev, id); 994 if (mtr == NULL) 995 return -EINVAL; 996 997 mtr->level = level; 998 return 0; 999 } 1000 1001 static void 1002 nix_mtr_config_map(struct cnxk_meter_node *mtr, struct roc_nix_bpf_cfg *cfg) 1003 { 1004 enum roc_nix_bpf_algo alg_map[] = { 1005 ROC_NIX_BPF_ALGO_NONE, ROC_NIX_BPF_ALGO_2697, 1006 ROC_NIX_BPF_ALGO_2698, ROC_NIX_BPF_ALGO_4115}; 1007 struct cnxk_mtr_profile_node *profile = mtr->profile; 1008 struct cnxk_mtr_policy_node *policy = mtr->policy; 1009 1010 cfg->alg = alg_map[profile->profile.alg]; 1011 cfg->lmode = profile->profile.packet_mode; 1012 1013 switch (cfg->alg) { 1014 case ROC_NIX_BPF_ALGO_2697: 1015 cfg->algo2697.cir = profile->profile.srtcm_rfc2697.cir * 8; 1016 cfg->algo2697.cbs = profile->profile.srtcm_rfc2697.cbs; 1017 cfg->algo2697.ebs = profile->profile.srtcm_rfc2697.ebs; 1018 break; 1019 case ROC_NIX_BPF_ALGO_2698: 1020 cfg->algo2698.cir = profile->profile.trtcm_rfc2698.cir * 8; 1021 cfg->algo2698.pir = profile->profile.trtcm_rfc2698.pir * 8; 1022 cfg->algo2698.cbs = profile->profile.trtcm_rfc2698.cbs; 1023 cfg->algo2698.pbs = profile->profile.trtcm_rfc2698.pbs; 1024 break; 1025 case ROC_NIX_BPF_ALGO_4115: 1026 cfg->algo4115.cir = profile->profile.trtcm_rfc4115.cir * 8; 1027 cfg->algo4115.eir = profile->profile.trtcm_rfc4115.eir * 8; 1028 cfg->algo4115.cbs = profile->profile.trtcm_rfc4115.cbs; 1029 cfg->algo4115.ebs = profile->profile.trtcm_rfc4115.ebs; 1030 break; 1031 default: 1032 break; 1033 } 1034 1035 cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_PASS; 1036 cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_PASS; 1037 cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_PASS; 1038 1039 if (policy->actions[RTE_COLOR_GREEN].action_fate == 1040 RTE_FLOW_ACTION_TYPE_DROP) 1041 cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_DROP; 1042 1043 if (policy->actions[RTE_COLOR_YELLOW].action_fate == 1044 RTE_FLOW_ACTION_TYPE_DROP) 1045 cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_DROP; 1046 1047 if (policy->actions[RTE_COLOR_RED].action_fate == 1048 RTE_FLOW_ACTION_TYPE_DROP) 1049 cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_DROP; 1050 } 1051 1052 static void 1053 nix_dscp_table_map(struct cnxk_meter_node *mtr, 1054 struct roc_nix_bpf_precolor *tbl) 1055 { 1056 enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN, 1057 ROC_NIX_BPF_COLOR_YELLOW, 1058 ROC_NIX_BPF_COLOR_RED}; 1059 int i; 1060 1061 tbl->count = ROC_NIX_BPF_PRE_COLOR_MAX; 1062 tbl->mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER; 1063 1064 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++) 1065 tbl->color[i] = ROC_NIX_BPF_COLOR_GREEN; 1066 1067 if (mtr->params.dscp_table) { 1068 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++) 1069 tbl->color[i] = color_map[mtr->params.dscp_table[i]]; 1070 } 1071 } 1072 1073 int 1074 nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t id, 1075 struct rte_mtr_error *error) 1076 { 1077 return cnxk_nix_mtr_destroy(eth_dev, id, error); 1078 } 1079 1080 int 1081 nix_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t id) 1082 { 1083 enum roc_nix_bpf_level_flag lvl_flag = ROC_NIX_BPF_LEVEL_IDX_INVALID; 1084 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 1085 struct cnxk_meter_node *base_mtr, *next_mtr; 1086 struct roc_nix *nix = &dev->nix; 1087 uint32_t cur_mtr_id = id; 1088 int rc, i; 1089 1090 for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) { 1091 base_mtr = nix_mtr_find(dev, cur_mtr_id); 1092 if (base_mtr) { 1093 lvl_flag = lvl_map[base_mtr->level]; 1094 if (base_mtr->is_next) { 1095 next_mtr = nix_mtr_find(dev, base_mtr->next_id); 1096 if (next_mtr) { 1097 if (!base_mtr->is_used) { 1098 rc = roc_nix_bpf_connect(nix, 1099 lvl_flag, 1100 base_mtr->bpf_id, 1101 next_mtr->bpf_id); 1102 if (rc) 1103 return rc; 1104 } 1105 } 1106 cur_mtr_id = base_mtr->next_id; 1107 } 1108 } 1109 } 1110 return 0; 1111 } 1112 1113 int 1114 nix_mtr_configure(struct rte_eth_dev *eth_dev, uint32_t id) 1115 { 1116 struct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0}; 1117 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); 1118 struct roc_nix_bpf_objs profs[ROC_NIX_BPF_LEVEL_MAX]; 1119 uint8_t idx0 = ROC_NIX_BPF_LEVEL_IDX_INVALID; 1120 uint8_t idx1 = ROC_NIX_BPF_LEVEL_IDX_INVALID; 1121 uint8_t idx2 = ROC_NIX_BPF_LEVEL_IDX_INVALID; 1122 uint16_t per_lvl_cnt[ROC_NIX_BPF_LEVEL_MAX]; 1123 int num_mtr[ROC_NIX_BPF_LEVEL_MAX] = {0}; 1124 struct roc_nix *nix = &dev->nix; 1125 struct roc_nix_bpf_precolor tbl; 1126 struct roc_nix_bpf_cfg cfg; 1127 struct roc_nix_rq *rq; 1128 uint8_t lvl_mask; 1129 uint32_t i; 1130 uint32_t j; 1131 int rc; 1132 1133 mtr[0] = nix_mtr_find(dev, id); 1134 if (mtr[0] == NULL) 1135 return -EINVAL; 1136 1137 num_mtr[0] = 1; 1138 idx0 = roc_nix_bpf_level_to_idx(lvl_map[mtr[0]->level]); 1139 if (idx0 == ROC_NIX_BPF_LEVEL_IDX_INVALID) 1140 return -EINVAL; 1141 1142 lvl_mask = ROC_NIX_BPF_LEVEL_F_LEAF; 1143 if (mtr[0]->is_used) 1144 per_lvl_cnt[idx0] = 0; 1145 else 1146 per_lvl_cnt[idx0] = 1; 1147 1148 if (mtr[0]->is_next) { 1149 mtr[1] = nix_mtr_find(dev, mtr[0]->next_id); 1150 if (mtr[1] == NULL) 1151 return -EINVAL; 1152 num_mtr[1] = 1; 1153 idx1 = roc_nix_bpf_level_to_idx(lvl_map[mtr[1]->level]); 1154 if (idx1 == ROC_NIX_BPF_LEVEL_IDX_INVALID) 1155 return -EINVAL; 1156 1157 lvl_mask |= ROC_NIX_BPF_LEVEL_F_MID; 1158 if (mtr[1]->is_used) 1159 per_lvl_cnt[idx1] = 0; 1160 else 1161 per_lvl_cnt[idx1] = 1; 1162 } 1163 1164 if (mtr[1] && mtr[1]->is_next) { 1165 mtr[2] = nix_mtr_find(dev, mtr[1]->next_id); 1166 if (mtr[2] == NULL) 1167 return -EINVAL; 1168 1169 num_mtr[2] = 1; 1170 idx2 = roc_nix_bpf_level_to_idx(lvl_map[mtr[2]->level]); 1171 if (idx2 == ROC_NIX_BPF_LEVEL_IDX_INVALID) 1172 return -EINVAL; 1173 1174 lvl_mask |= ROC_NIX_BPF_LEVEL_F_TOP; 1175 if (mtr[2]->is_used) 1176 per_lvl_cnt[idx2] = 0; 1177 else 1178 per_lvl_cnt[idx2] = 1; 1179 } 1180 1181 rc = roc_nix_bpf_alloc(nix, lvl_mask, per_lvl_cnt, profs); 1182 if (rc) 1183 return rc; 1184 if (mtr[0]->bpf_id == ROC_NIX_BPF_ID_INVALID) 1185 mtr[0]->bpf_id = profs[idx0].ids[0]; 1186 1187 if (num_mtr[0]) 1188 if (mtr[0]->is_next && idx1 != ROC_NIX_BPF_LEVEL_IDX_INVALID) 1189 if (mtr[1]->bpf_id == ROC_NIX_BPF_ID_INVALID) 1190 mtr[1]->bpf_id = profs[idx1].ids[0]; 1191 1192 if (num_mtr[1]) 1193 if (mtr[1]->is_next && idx2 != ROC_NIX_BPF_LEVEL_IDX_INVALID) 1194 if (mtr[2]->bpf_id == ROC_NIX_BPF_ID_INVALID) 1195 mtr[2]->bpf_id = profs[idx2].ids[0]; 1196 1197 for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) { 1198 if (num_mtr[i]) { 1199 if (!mtr[i]->is_used) { 1200 memset(&cfg, 0, sizeof(struct roc_nix_bpf_cfg)); 1201 nix_mtr_config_map(mtr[i], &cfg); 1202 rc = roc_nix_bpf_config(nix, mtr[i]->bpf_id, 1203 lvl_map[mtr[i]->level], 1204 &cfg); 1205 1206 memset(&tbl, 0, 1207 sizeof(struct roc_nix_bpf_precolor)); 1208 nix_dscp_table_map(mtr[i], &tbl); 1209 rc = roc_nix_bpf_pre_color_tbl_setup(nix, 1210 mtr[i]->bpf_id, lvl_map[mtr[i]->level], 1211 &tbl); 1212 1213 if (mtr[i]->params.meter_enable) { 1214 for (j = 0; j < mtr[i]->rq_num; j++) { 1215 rq = &dev->rqs[mtr[i]->rq_id 1216 [j]]; 1217 rc = roc_nix_bpf_ena_dis(nix, 1218 mtr[i]->bpf_id, rq, 1219 true); 1220 } 1221 } 1222 } 1223 } 1224 } 1225 1226 return rc; 1227 } 1228 1229 int 1230 nix_mtr_color_action_validate(struct rte_eth_dev *eth_dev, uint32_t id, 1231 uint32_t *prev_id, uint32_t *next_id, 1232 struct cnxk_mtr_policy_node *policy, 1233 int *tree_level) 1234 { 1235 uint32_t action_fate_red = policy->actions[RTE_COLOR_RED].action_fate; 1236 uint32_t action_fate_green = 1237 policy->actions[RTE_COLOR_GREEN].action_fate; 1238 uint32_t action_fate_yellow = 1239 policy->actions[RTE_COLOR_YELLOW].action_fate; 1240 uint32_t cur_mtr_id = *next_id; 1241 uint32_t next_mtr_id = 0xffff; 1242 uint32_t prev_mtr_id = 0xffff; 1243 struct cnxk_meter_node *mtr; 1244 1245 if (action_fate_green == RTE_FLOW_ACTION_TYPE_METER) 1246 next_mtr_id = policy->actions[RTE_COLOR_GREEN].mtr_id; 1247 1248 if (action_fate_yellow == RTE_FLOW_ACTION_TYPE_METER) 1249 next_mtr_id = policy->actions[RTE_COLOR_YELLOW].mtr_id; 1250 1251 if (action_fate_red == RTE_FLOW_ACTION_TYPE_METER) 1252 next_mtr_id = policy->actions[RTE_COLOR_RED].mtr_id; 1253 1254 if (next_mtr_id != 0xffff) { 1255 switch (*tree_level) { 1256 case 0: 1257 mtr = nix_get_mtr(eth_dev, cur_mtr_id); 1258 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) { 1259 nix_mtr_level_update(eth_dev, cur_mtr_id, 0); 1260 nix_mtr_chain_update(eth_dev, cur_mtr_id, -1, 1261 next_mtr_id); 1262 } else { 1263 if (mtr->level == 0) 1264 mtr->is_used = true; 1265 else 1266 return -EINVAL; 1267 } 1268 (*tree_level)++; 1269 *next_id = next_mtr_id; 1270 break; 1271 case 1: 1272 mtr = nix_get_mtr(eth_dev, cur_mtr_id); 1273 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) { 1274 nix_mtr_level_update(eth_dev, cur_mtr_id, 1); 1275 prev_mtr_id = id; 1276 nix_mtr_chain_update(eth_dev, cur_mtr_id, 1277 prev_mtr_id, next_mtr_id); 1278 } else { 1279 if (mtr->level == 1) { 1280 mtr->prev_cnt++; 1281 prev_mtr_id = id; 1282 nix_mtr_chain_update(eth_dev, 1283 cur_mtr_id, prev_mtr_id, 1284 next_mtr_id); 1285 1286 mtr->is_used = true; 1287 } else { 1288 return -EINVAL; 1289 } 1290 } 1291 (*tree_level)++; 1292 *next_id = next_mtr_id; 1293 *prev_id = cur_mtr_id; 1294 break; 1295 case 2: 1296 nix_mtr_chain_reset(eth_dev, id); 1297 return -EINVAL; 1298 } 1299 } else { 1300 switch (*tree_level) { 1301 case 0: 1302 mtr = nix_get_mtr(eth_dev, cur_mtr_id); 1303 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) { 1304 nix_mtr_level_update(eth_dev, cur_mtr_id, 0); 1305 } else { 1306 if (mtr->level == 0) 1307 mtr->is_used = true; 1308 else 1309 return -EINVAL; 1310 } 1311 break; 1312 case 1: 1313 mtr = nix_get_mtr(eth_dev, cur_mtr_id); 1314 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) { 1315 nix_mtr_level_update(eth_dev, cur_mtr_id, 1); 1316 prev_mtr_id = id; 1317 nix_mtr_chain_update(eth_dev, cur_mtr_id, 1318 prev_mtr_id, -1); 1319 } else { 1320 if (mtr->level == 1) { 1321 mtr->prev_cnt++; 1322 prev_mtr_id = id; 1323 nix_mtr_chain_update(eth_dev, 1324 cur_mtr_id, 1325 prev_mtr_id, -1); 1326 mtr->is_used = true; 1327 } else { 1328 return -EINVAL; 1329 } 1330 } 1331 break; 1332 case 2: 1333 mtr = nix_get_mtr(eth_dev, cur_mtr_id); 1334 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) { 1335 nix_mtr_level_update(eth_dev, cur_mtr_id, 2); 1336 prev_mtr_id = *prev_id; 1337 nix_mtr_chain_update(eth_dev, cur_mtr_id, 1338 prev_mtr_id, -1); 1339 } else { 1340 if (mtr->level == 2) { 1341 mtr->prev_cnt++; 1342 prev_mtr_id = *prev_id; 1343 nix_mtr_chain_update(eth_dev, 1344 cur_mtr_id, 1345 prev_mtr_id, -1); 1346 mtr->is_used = true; 1347 } else { 1348 return -EINVAL; 1349 } 1350 } 1351 break; 1352 } 1353 *next_id = 0xffff; 1354 } 1355 1356 return 0; 1357 } 1358 1359 int 1360 nix_mtr_capabilities_init(struct rte_eth_dev *eth_dev) 1361 { 1362 struct rte_mtr_capabilities capa; 1363 struct rte_mtr_error error; 1364 1365 return cnxk_nix_mtr_capabilities_get(eth_dev, &capa, &error); 1366 } 1367