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