get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/101106/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 101106,
    "url": "https://patches.dpdk.org/api/patches/101106/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20211011155057.302142-28-skori@marvell.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20211011155057.302142-28-skori@marvell.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20211011155057.302142-28-skori@marvell.com",
    "date": "2021-10-11T15:50:55",
    "name": "[v4,27/28] net/cnxk: support meter action to flow create",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "841dbf0d4a55b077c288d731207e8a4e72e90d8b",
    "submitter": {
        "id": 1318,
        "url": "https://patches.dpdk.org/api/people/1318/?format=api",
        "name": "Sunil Kumar Kori",
        "email": "skori@marvell.com"
    },
    "delegate": {
        "id": 310,
        "url": "https://patches.dpdk.org/api/users/310/?format=api",
        "username": "jerin",
        "first_name": "Jerin",
        "last_name": "Jacob",
        "email": "jerinj@marvell.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20211011155057.302142-28-skori@marvell.com/mbox/",
    "series": [
        {
            "id": 19528,
            "url": "https://patches.dpdk.org/api/series/19528/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=19528",
            "date": "2021-10-11T15:50:28",
            "name": "Support ingress policer",
            "version": 4,
            "mbox": "https://patches.dpdk.org/series/19528/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/101106/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/101106/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 28A98A034F;\n\tMon, 11 Oct 2021 17:53:58 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 0DCDC411E8;\n\tMon, 11 Oct 2021 17:52:10 +0200 (CEST)",
            "from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com\n [67.231.148.174])\n by mails.dpdk.org (Postfix) with ESMTP id B3072411EB\n for <dev@dpdk.org>; Mon, 11 Oct 2021 17:52:08 +0200 (CEST)",
            "from pps.filterd (m0045849.ppops.net [127.0.0.1])\n by mx0a-0016f401.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 19BE6epv030302\n for <dev@dpdk.org>; Mon, 11 Oct 2021 08:52:07 -0700",
            "from dc5-exch02.marvell.com ([199.233.59.182])\n by mx0a-0016f401.pphosted.com with ESMTP id 3bmpqt0gp1-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT)\n for <dev@dpdk.org>; Mon, 11 Oct 2021 08:52:07 -0700",
            "from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH02.marvell.com\n (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.18;\n Mon, 11 Oct 2021 08:52:06 -0700",
            "from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com\n (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.18 via Frontend\n Transport; Mon, 11 Oct 2021 08:52:06 -0700",
            "from localhost.localdomain (unknown [10.28.34.25])\n by maili.marvell.com (Postfix) with ESMTP id 600FB3F705B;\n Mon, 11 Oct 2021 08:52:04 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com;\n h=from : to : cc :\n subject : date : message-id : in-reply-to : references : mime-version :\n content-transfer-encoding : content-type; s=pfpt0220;\n bh=0bQ4+FWgDEEfMMDR/9spiRJR1Co8sMek1wslI4+8Ibc=;\n b=iwxufbanusVQ1a1HeU+Ru82exRNA6od2aD+B5gnGlADjsyyOfcDzLz8rHL9R9ZFGTkvR\n HFTxMxvut7qqJWtXl/gVXn2j9PR1hcRNLeUyfdjnnfwf3E7PiwNyJ5WtkI0WPm5wOkJV\n eO4oT/+x51OZHScARzHV6XW1YjStJe3hhfskU/YuB46+2x9PSu/cmkXVppz0eDbSVgPw\n /UjKFQUW2wZI6DbRbPSId+hw2IZSWM/ayciG8tN0Ivdlx7EThP7W/Zzc1rZxZy/ZZ0VV\n TTx1W3PVYqjjESk8IGd+VoYnwmUi53ltrQSGJfxmXiKmE5JW9xUmODeTZksmTnuMR8Db nQ==",
        "From": "<skori@marvell.com>",
        "To": "Nithin Dabilpuram <ndabilpuram@marvell.com>, Kiran Kumar K\n <kirankumark@marvell.com>, Sunil Kumar Kori <skori@marvell.com>, Satha Rao\n <skoteshwar@marvell.com>",
        "CC": "<dev@dpdk.org>, Rakesh Kudurumalla <rkudurumalla@marvell.com>",
        "Date": "Mon, 11 Oct 2021 21:20:55 +0530",
        "Message-ID": "<20211011155057.302142-28-skori@marvell.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20211011155057.302142-1-skori@marvell.com>",
        "References": "<20210930090844.1059326-1-skori@marvell.com>\n <20211011155057.302142-1-skori@marvell.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-Proofpoint-ORIG-GUID": "zumXiY_lhK1x4hsZoe499CGh92WtYp8F",
        "X-Proofpoint-GUID": "zumXiY_lhK1x4hsZoe499CGh92WtYp8F",
        "X-Proofpoint-Virus-Version": "vendor=baseguard\n engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475\n definitions=2021-10-11_05,2021-10-11_01,2020-04-07_01",
        "Subject": "[dpdk-dev] [PATCH v4 27/28] net/cnxk: support meter action to flow\n create",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Sunil Kumar Kori <skori@marvell.com>\n\nMeters are configured per flow using rte_flow_create API.\nImplement support for meter action applied on the flow.\n\nSigned-off-by: Sunil Kumar Kori <skori@marvell.com>\nSigned-off-by: Rakesh Kudurumalla <rkudurumalla@marvell.com>\n---\nv4:\n - Rebase support on dpdk-next-net-mrvl branch\n - Handled meter action during flow destroy\n - Handled meter cleanup during port shutdown\n \nv3:\n - Rebase support on latest DPDK\n - Handled multilevel chaining for tree hierarchy\n - Fix naming convention\nv2:\n - Rebase support on latest DPDK\n - Handled multilevel chaining for linear hierarchy\n - Review comments incorporated\n\n doc/guides/nics/features/cnxk.ini      |   1 +\n doc/guides/nics/features/cnxk_vf.ini   |   1 +\n doc/guides/rel_notes/release_21_11.rst |   1 +\n drivers/net/cnxk/cn10k_rte_flow.c      | 171 ++++++++-\n drivers/net/cnxk/cnxk_ethdev.h         |  18 +\n drivers/net/cnxk/cnxk_ethdev_mtr.c     | 506 +++++++++++++++++++++++++\n drivers/net/cnxk/cnxk_rte_flow.c       |   4 +\n 7 files changed, 701 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/doc/guides/nics/features/cnxk.ini b/doc/guides/nics/features/cnxk.ini\nindex 1ced3ee903..f0586457ca 100644\n--- a/doc/guides/nics/features/cnxk.ini\n+++ b/doc/guides/nics/features/cnxk.ini\n@@ -79,6 +79,7 @@ count                = Y\n drop                 = Y\n flag                 = Y\n mark                 = Y\n+meter                = Y\n of_pop_vlan          = Y\n of_push_vlan         = Y\n of_set_vlan_pcp      = Y\ndiff --git a/doc/guides/nics/features/cnxk_vf.ini b/doc/guides/nics/features/cnxk_vf.ini\nindex 139d9b9892..f3d9f23f17 100644\n--- a/doc/guides/nics/features/cnxk_vf.ini\n+++ b/doc/guides/nics/features/cnxk_vf.ini\n@@ -71,6 +71,7 @@ count                = Y\n drop                 = Y\n flag                 = Y\n mark                 = Y\n+meter                = Y\n of_pop_vlan          = Y\n of_push_vlan         = Y\n of_set_vlan_pcp      = Y\ndiff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst\nindex 16c48d54a1..5ec80377ee 100644\n--- a/doc/guides/rel_notes/release_21_11.rst\n+++ b/doc/guides/rel_notes/release_21_11.rst\n@@ -91,6 +91,7 @@ New Features\n   * Added rte_tm support.\n   * Added support for Inline IPsec for CN9K event mode and CN10K\n     poll mode and event mode.\n+  * Added support for ingress meter for CN10K platform.\n \n * **Updated af_packet ethdev driver.**\n \ndiff --git a/drivers/net/cnxk/cn10k_rte_flow.c b/drivers/net/cnxk/cn10k_rte_flow.c\nindex b04de6a7e6..00c0b172e4 100644\n--- a/drivers/net/cnxk/cn10k_rte_flow.c\n+++ b/drivers/net/cnxk/cn10k_rte_flow.c\n@@ -6,6 +6,113 @@\n #include \"cn10k_ethdev.h\"\n #include \"cn10k_rx.h\"\n \n+static int\n+cn10k_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t mtr_id)\n+{\n+\treturn nix_mtr_connect(eth_dev, mtr_id);\n+}\n+\n+static int\n+cn10k_mtr_configure(struct rte_eth_dev *eth_dev,\n+\t\t    const struct rte_flow_action actions[])\n+{\n+\tuint32_t mtr_id = 0xffff, prev_mtr_id = 0xffff, next_mtr_id = 0xffff;\n+\tconst struct rte_flow_action_meter *mtr_conf;\n+\tconst struct rte_flow_action_queue *q_conf;\n+\tconst struct rte_flow_action_rss *rss_conf;\n+\tstruct cnxk_mtr_policy_node *policy;\n+\tbool is_mtr_act = false;\n+\tint tree_level = 0;\n+\tint rc = -EINVAL, i;\n+\n+\tfor (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {\n+\t\tif (actions[i].type == RTE_FLOW_ACTION_TYPE_METER) {\n+\t\t\tmtr_conf = (const struct rte_flow_action_meter\n+\t\t\t\t\t    *)(actions->conf);\n+\t\t\tmtr_id = mtr_conf->mtr_id;\n+\t\t\tis_mtr_act = true;\n+\t\t}\n+\t\tif (actions[i].type == RTE_FLOW_ACTION_TYPE_QUEUE) {\n+\t\t\tq_conf = (const struct rte_flow_action_queue\n+\t\t\t\t\t  *)(actions->conf);\n+\t\t\tif (is_mtr_act)\n+\t\t\t\tnix_mtr_rq_update(eth_dev, mtr_id, 1,\n+\t\t\t\t\t\t  &q_conf->index);\n+\t\t}\n+\t\tif (actions[i].type == RTE_FLOW_ACTION_TYPE_RSS) {\n+\t\t\trss_conf = (const struct rte_flow_action_rss\n+\t\t\t\t\t    *)(actions->conf);\n+\t\t\tif (is_mtr_act)\n+\t\t\t\tnix_mtr_rq_update(eth_dev, mtr_id,\n+\t\t\t\t\t\t  rss_conf->queue_num,\n+\t\t\t\t\t\t  rss_conf->queue);\n+\t\t}\n+\t}\n+\n+\tif (!is_mtr_act)\n+\t\treturn rc;\n+\n+\tprev_mtr_id = mtr_id;\n+\tnext_mtr_id = mtr_id;\n+\twhile (next_mtr_id != 0xffff) {\n+\t\trc = nix_mtr_validate(eth_dev, next_mtr_id);\n+\t\tif (rc)\n+\t\t\treturn rc;\n+\n+\t\trc = nix_mtr_policy_act_get(eth_dev, next_mtr_id, &policy);\n+\t\tif (rc)\n+\t\t\treturn rc;\n+\n+\t\trc = nix_mtr_color_action_validate(eth_dev, mtr_id,\n+\t\t\t\t\t\t   &prev_mtr_id, &next_mtr_id,\n+\t\t\t\t\t\t   policy, &tree_level);\n+\t\tif (rc)\n+\t\t\treturn rc;\n+\t}\n+\n+\treturn nix_mtr_configure(eth_dev, mtr_id);\n+}\n+\n+static int\n+cn10k_rss_action_validate(struct rte_eth_dev *eth_dev,\n+\t\t\t  const struct rte_flow_attr *attr,\n+\t\t\t  const struct rte_flow_action *act)\n+{\n+\tconst struct rte_flow_action_rss *rss;\n+\n+\tif (act == NULL)\n+\t\treturn -EINVAL;\n+\n+\trss = (const struct rte_flow_action_rss *)act->conf;\n+\n+\tif (attr->egress) {\n+\t\tplt_err(\"No support of RSS in egress\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (eth_dev->data->dev_conf.rxmode.mq_mode != ETH_MQ_RX_RSS) {\n+\t\tplt_err(\"multi-queue mode is disabled\");\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\tif (!rss || !rss->queue_num) {\n+\t\tplt_err(\"no valid queues\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {\n+\t\tplt_err(\"non-default RSS hash functions are not supported\");\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\tif (rss->key_len && rss->key_len > ROC_NIX_RSS_KEY_LEN) {\n+\t\tplt_err(\"RSS hash key too large\");\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\treturn 0;\n+}\n+\n struct rte_flow *\n cn10k_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,\n \t\t  const struct rte_flow_item pattern[],\n@@ -13,13 +120,75 @@ cn10k_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,\n \t\t  struct rte_flow_error *error)\n {\n \tstruct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);\n+\tconst struct rte_flow_action *action_rss = NULL;\n+\tconst struct rte_flow_action_meter *mtr = NULL;\n+\tconst struct rte_flow_action *act_q = NULL;\n \tint mark_actions = 0, vtag_actions = 0;\n \tstruct roc_npc *npc = &dev->npc;\n \tstruct roc_npc_flow *flow;\n+\tuint32_t req_act = 0;\n+\tint i, rc;\n+\n+\tfor (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {\n+\t\tif (actions[i].type == RTE_FLOW_ACTION_TYPE_METER)\n+\t\t\treq_act |= ROC_NPC_ACTION_TYPE_METER;\n+\n+\t\tif (actions[i].type == RTE_FLOW_ACTION_TYPE_QUEUE) {\n+\t\t\treq_act |= ROC_NPC_ACTION_TYPE_QUEUE;\n+\t\t\tact_q = &actions[i];\n+\t\t}\n+\t\tif (actions[i].type == RTE_FLOW_ACTION_TYPE_RSS) {\n+\t\t\treq_act |= ROC_NPC_ACTION_TYPE_RSS;\n+\t\t\taction_rss = &actions[i];\n+\t\t}\n+\t}\n+\n+\tif (req_act & ROC_NPC_ACTION_TYPE_METER) {\n+\t\tif ((req_act & ROC_NPC_ACTION_TYPE_RSS) &&\n+\t\t    ((req_act & ROC_NPC_ACTION_TYPE_QUEUE))) {\n+\t\t\treturn NULL;\n+\t\t}\n+\t\tif (req_act & ROC_NPC_ACTION_TYPE_RSS) {\n+\t\t\trc = cn10k_rss_action_validate(eth_dev, attr,\n+\t\t\t\t\t\t       action_rss);\n+\t\t\tif (rc)\n+\t\t\t\treturn NULL;\n+\t\t} else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) {\n+\t\t\tconst struct rte_flow_action_queue *act_queue;\n+\t\t\tact_queue = (const struct rte_flow_action_queue *)\n+\t\t\t\t\t    act_q->conf;\n+\t\t\tif (act_queue->index > eth_dev->data->nb_rx_queues)\n+\t\t\t\treturn NULL;\n+\t\t} else {\n+\t\t\treturn NULL;\n+\t\t}\n+\t}\n+\n+\tfor (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {\n+\t\tif (actions[i].type == RTE_FLOW_ACTION_TYPE_METER) {\n+\t\t\tmtr = (const struct rte_flow_action_meter *)actions[i]\n+\t\t\t\t      .conf;\n+\t\t\trc = cn10k_mtr_configure(eth_dev, actions);\n+\t\t\tif (rc) {\n+\t\t\t\trte_flow_error_set(error, rc,\n+\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION, NULL,\n+\t\t\t\t\t\"Failed to configure mtr \");\n+\t\t\t\treturn NULL;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t}\n \n \tflow = cnxk_flow_create(eth_dev, attr, pattern, actions, error);\n-\tif (!flow)\n+\tif (!flow) {\n+\t\tif (mtr)\n+\t\t\tnix_mtr_chain_reset(eth_dev, mtr->mtr_id);\n+\n \t\treturn NULL;\n+\t} else {\n+\t\tif (mtr)\n+\t\t\tcn10k_mtr_connect(eth_dev, mtr->mtr_id);\n+\t}\n \n \tmark_actions = roc_npc_mark_actions_get(npc);\n \ndiff --git a/drivers/net/cnxk/cnxk_ethdev.h b/drivers/net/cnxk/cnxk_ethdev.h\nindex 10adeeec82..7e13956572 100644\n--- a/drivers/net/cnxk/cnxk_ethdev.h\n+++ b/drivers/net/cnxk/cnxk_ethdev.h\n@@ -575,6 +575,24 @@ cnxk_eth_sec_sess_get_by_sess(struct cnxk_eth_dev *dev,\n \n /* Other private functions */\n int nix_recalc_mtu(struct rte_eth_dev *eth_dev);\n+int nix_mtr_validate(struct rte_eth_dev *dev, uint32_t id);\n+int nix_mtr_policy_act_get(struct rte_eth_dev *eth_dev, uint32_t id,\n+\t\t\t   struct cnxk_mtr_policy_node **policy);\n+int nix_mtr_rq_update(struct rte_eth_dev *eth_dev, uint32_t id,\n+\t\t      uint32_t queue_num, const uint16_t *queue);\n+int nix_mtr_chain_update(struct rte_eth_dev *eth_dev, uint32_t cur_id,\n+\t\t\t uint32_t prev_id, uint32_t next_id);\n+int nix_mtr_chain_reset(struct rte_eth_dev *eth_dev, uint32_t cur_id);\n+struct cnxk_meter_node *nix_get_mtr(struct rte_eth_dev *eth_dev,\n+\t\t\t\t    uint32_t cur_id);\n+int nix_mtr_level_update(struct rte_eth_dev *eth_dev, uint32_t id,\n+\t\t\t uint32_t level);\n+int nix_mtr_configure(struct rte_eth_dev *eth_dev, uint32_t id);\n+int nix_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t id);\n+int nix_mtr_color_action_validate(struct rte_eth_dev *eth_dev, uint32_t id,\n+\t\t\t\t  uint32_t *prev_id, uint32_t *next_id,\n+\t\t\t\t  struct cnxk_mtr_policy_node *policy,\n+\t\t\t\t  int *tree_level);\n \n /* Inlines */\n static __rte_always_inline uint64_t\ndiff --git a/drivers/net/cnxk/cnxk_ethdev_mtr.c b/drivers/net/cnxk/cnxk_ethdev_mtr.c\nindex 08af3f628a..7fde992d0f 100644\n--- a/drivers/net/cnxk/cnxk_ethdev_mtr.c\n+++ b/drivers/net/cnxk/cnxk_ethdev_mtr.c\n@@ -826,3 +826,509 @@ cnxk_nix_mtr_ops_get(struct rte_eth_dev *dev, void *ops)\n \t*(const void **)ops = &nix_mtr_ops;\n \treturn 0;\n }\n+\n+int\n+nix_mtr_validate(struct rte_eth_dev *eth_dev, uint32_t id)\n+{\n+\tstruct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);\n+\tstruct cnxk_mtr_profile_node *profile;\n+\tstruct cnxk_mtr_policy_node *policy;\n+\tstruct cnxk_meter_node *mtr;\n+\n+\tmtr = nix_mtr_find(dev, id);\n+\tif (mtr == NULL)\n+\t\treturn -EINVAL;\n+\n+\tprofile = nix_mtr_profile_find(dev, mtr->params.meter_profile_id);\n+\tif (profile == NULL)\n+\t\treturn -EINVAL;\n+\n+\tpolicy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);\n+\tif (policy == NULL)\n+\t\treturn -EINVAL;\n+\n+\treturn 0;\n+}\n+\n+int\n+nix_mtr_policy_act_get(struct rte_eth_dev *eth_dev, uint32_t id,\n+\t\t       struct cnxk_mtr_policy_node **policy_act)\n+{\n+\tstruct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);\n+\tstruct cnxk_mtr_policy_node *policy;\n+\tstruct cnxk_meter_node *mtr;\n+\n+\tmtr = nix_mtr_find(dev, id);\n+\tif (mtr == NULL)\n+\t\treturn -EINVAL;\n+\n+\tpolicy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);\n+\tif (policy == NULL)\n+\t\treturn -EINVAL;\n+\n+\t*policy_act = policy;\n+\n+\treturn 0;\n+}\n+\n+int\n+nix_mtr_rq_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t queue_num,\n+\t\t  const uint16_t *queue)\n+{\n+\tstruct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);\n+\tstruct cnxk_meter_node *mtr;\n+\tuint32_t i;\n+\n+\tmtr = nix_mtr_find(dev, id);\n+\tif (mtr == NULL)\n+\t\treturn -EINVAL;\n+\n+\tmtr->rq_id = plt_zmalloc(queue_num * sizeof(uint32_t), ROC_ALIGN);\n+\tif (mtr->rq_id == NULL)\n+\t\treturn -ENOMEM;\n+\n+\tmtr->rq_num = queue_num;\n+\tfor (i = 0; i < queue_num; i++)\n+\t\tmtr->rq_id[i] = queue[i];\n+\n+\treturn 0;\n+}\n+\n+int\n+nix_mtr_chain_reset(struct rte_eth_dev *eth_dev, uint32_t cur_id)\n+{\n+\tstruct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};\n+\tstruct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);\n+\tuint32_t mtr_id = cur_id;\n+\tint i = 0, j = 0;\n+\n+\tfor (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {\n+\t\tmtr[i] = nix_mtr_find(dev, mtr_id);\n+\t\tif (mtr[i])\n+\t\t\tmtr_id = mtr[i]->next_id;\n+\t}\n+\tfor (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {\n+\t\tif (mtr[i]) {\n+\t\t\tfor (j = 0; j < MAX_PRV_MTR_NODES; j++)\n+\t\t\t\tmtr[i]->prev_id[i] = ROC_NIX_BPF_ID_INVALID;\n+\t\t\tmtr[i]->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;\n+\t\t\tmtr[i]->next_id = ROC_NIX_BPF_ID_INVALID;\n+\t\t\tmtr[i]->is_next = false;\n+\t\t\tmtr[i]->prev_cnt = 0;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+int\n+nix_mtr_chain_update(struct rte_eth_dev *eth_dev, uint32_t cur_id,\n+\t\t     uint32_t prev_id, uint32_t next_id)\n+{\n+\tstruct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);\n+\tstruct cnxk_meter_node *mtr;\n+\n+\tmtr = nix_mtr_find(dev, cur_id);\n+\tif (mtr == NULL)\n+\t\treturn -EINVAL;\n+\n+\tswitch (lvl_map[mtr->level]) {\n+\tcase ROC_NIX_BPF_LEVEL_F_LEAF:\n+\t\tmtr->prev_id[mtr->prev_cnt] = ROC_NIX_BPF_ID_INVALID;\n+\t\tmtr->next_id = next_id;\n+\t\tmtr->is_next = true;\n+\t\tbreak;\n+\tcase ROC_NIX_BPF_LEVEL_F_MID:\n+\t\tmtr->prev_id[mtr->prev_cnt] = prev_id;\n+\t\tmtr->next_id = next_id;\n+\t\tmtr->is_next = true;\n+\t\tbreak;\n+\tcase ROC_NIX_BPF_LEVEL_F_TOP:\n+\t\tmtr->prev_id[mtr->prev_cnt] = prev_id;\n+\t\tmtr->next_id = ROC_NIX_BPF_ID_INVALID;\n+\t\tmtr->is_next = false;\n+\t\tbreak;\n+\tdefault:\n+\t\tplt_err(\"Invalid meter level\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+struct cnxk_meter_node *\n+nix_get_mtr(struct rte_eth_dev *eth_dev, uint32_t id)\n+{\n+\tstruct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);\n+\tstruct cnxk_meter_node *mtr;\n+\n+\tmtr = nix_mtr_find(dev, id);\n+\tif (mtr == NULL)\n+\t\treturn NULL;\n+\n+\treturn mtr;\n+}\n+\n+int\n+nix_mtr_level_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t level)\n+{\n+\tstruct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);\n+\tstruct cnxk_meter_node *mtr;\n+\n+\tmtr = nix_mtr_find(dev, id);\n+\tif (mtr == NULL)\n+\t\treturn -EINVAL;\n+\n+\tmtr->level = level;\n+\treturn 0;\n+}\n+\n+static void\n+nix_mtr_config_map(struct cnxk_meter_node *mtr, struct roc_nix_bpf_cfg *cfg)\n+{\n+\tenum roc_nix_bpf_algo alg_map[] = {\n+\t\tROC_NIX_BPF_ALGO_NONE, ROC_NIX_BPF_ALGO_2697,\n+\t\tROC_NIX_BPF_ALGO_2698, ROC_NIX_BPF_ALGO_4115};\n+\tstruct cnxk_mtr_profile_node *profile = mtr->profile;\n+\tstruct cnxk_mtr_policy_node *policy = mtr->policy;\n+\n+\tcfg->alg = alg_map[profile->profile.alg];\n+\tcfg->lmode = profile->profile.packet_mode;\n+\n+\tswitch (cfg->alg) {\n+\tcase ROC_NIX_BPF_ALGO_2697:\n+\t\tcfg->algo2697.cir = profile->profile.srtcm_rfc2697.cir * 8;\n+\t\tcfg->algo2697.cbs = profile->profile.srtcm_rfc2697.cbs;\n+\t\tcfg->algo2697.ebs = profile->profile.srtcm_rfc2697.ebs;\n+\t\tbreak;\n+\tcase ROC_NIX_BPF_ALGO_2698:\n+\t\tcfg->algo2698.cir = profile->profile.trtcm_rfc2698.cir * 8;\n+\t\tcfg->algo2698.pir = profile->profile.trtcm_rfc2698.pir * 8;\n+\t\tcfg->algo2698.cbs = profile->profile.trtcm_rfc2698.cbs;\n+\t\tcfg->algo2698.pbs = profile->profile.trtcm_rfc2698.pbs;\n+\t\tbreak;\n+\tcase ROC_NIX_BPF_ALGO_4115:\n+\t\tcfg->algo4115.cir = profile->profile.trtcm_rfc4115.cir * 8;\n+\t\tcfg->algo4115.eir = profile->profile.trtcm_rfc4115.eir * 8;\n+\t\tcfg->algo4115.cbs = profile->profile.trtcm_rfc4115.cbs;\n+\t\tcfg->algo4115.ebs = profile->profile.trtcm_rfc4115.ebs;\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tcfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_PASS;\n+\tcfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_PASS;\n+\tcfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_PASS;\n+\n+\tif (policy->actions[RTE_COLOR_GREEN].action_fate ==\n+\t    RTE_FLOW_ACTION_TYPE_DROP)\n+\t\tcfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_DROP;\n+\n+\tif (policy->actions[RTE_COLOR_YELLOW].action_fate ==\n+\t    RTE_FLOW_ACTION_TYPE_DROP)\n+\t\tcfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_DROP;\n+\n+\tif (policy->actions[RTE_COLOR_RED].action_fate ==\n+\t    RTE_FLOW_ACTION_TYPE_DROP)\n+\t\tcfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_DROP;\n+}\n+\n+static void\n+nix_dscp_table_map(struct cnxk_meter_node *mtr,\n+\t\t   struct roc_nix_bpf_precolor *tbl)\n+{\n+\tenum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,\n+\t\t\t\t\t      ROC_NIX_BPF_COLOR_YELLOW,\n+\t\t\t\t\t      ROC_NIX_BPF_COLOR_RED};\n+\tint i;\n+\n+\ttbl->count = ROC_NIX_BPF_PRE_COLOR_MAX;\n+\ttbl->mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;\n+\n+\tfor (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)\n+\t\ttbl->color[i] = ROC_NIX_BPF_COLOR_GREEN;\n+\n+\tif (mtr->params.dscp_table) {\n+\t\tfor (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)\n+\t\t\ttbl->color[i] = color_map[mtr->params.dscp_table[i]];\n+\t}\n+}\n+\n+int\n+nix_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t id)\n+{\n+\tenum roc_nix_bpf_level_flag lvl_flag = ROC_NIX_BPF_LEVEL_IDX_INVALID;\n+\tstruct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);\n+\tstruct cnxk_meter_node *base_mtr, *next_mtr;\n+\tstruct roc_nix *nix = &dev->nix;\n+\tuint32_t cur_mtr_id = id;\n+\tint rc, i;\n+\n+\tfor (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {\n+\t\tbase_mtr = nix_mtr_find(dev, cur_mtr_id);\n+\t\tif (base_mtr) {\n+\t\t\tlvl_flag = lvl_map[base_mtr->level];\n+\t\t\tif (base_mtr->is_next) {\n+\t\t\t\tnext_mtr = nix_mtr_find(dev, base_mtr->next_id);\n+\t\t\t\tif (next_mtr) {\n+\t\t\t\t\tif (!base_mtr->is_used) {\n+\t\t\t\t\t\trc = roc_nix_bpf_connect(nix,\n+\t\t\t\t\t\t\tlvl_flag,\n+\t\t\t\t\t\t\tbase_mtr->bpf_id,\n+\t\t\t\t\t\t\tnext_mtr->bpf_id);\n+\t\t\t\t\t\tif (rc)\n+\t\t\t\t\t\t\treturn rc;\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t\tcur_mtr_id = base_mtr->next_id;\n+\t\t\t}\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+int\n+nix_mtr_configure(struct rte_eth_dev *eth_dev, uint32_t id)\n+{\n+\tstruct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};\n+\tstruct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);\n+\tstruct roc_nix_bpf_objs profs[ROC_NIX_BPF_LEVEL_MAX];\n+\tuint8_t idx0 = ROC_NIX_BPF_LEVEL_IDX_INVALID;\n+\tuint8_t idx1 = ROC_NIX_BPF_LEVEL_IDX_INVALID;\n+\tuint8_t idx2 = ROC_NIX_BPF_LEVEL_IDX_INVALID;\n+\tuint16_t per_lvl_cnt[ROC_NIX_BPF_LEVEL_MAX];\n+\tint num_mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};\n+\tstruct roc_nix *nix = &dev->nix;\n+\tstruct roc_nix_bpf_precolor tbl;\n+\tstruct roc_nix_bpf_cfg cfg;\n+\tstruct roc_nix_rq *rq;\n+\tuint8_t lvl_mask;\n+\tuint32_t i;\n+\tuint32_t j;\n+\tint rc;\n+\n+\tmtr[0] = nix_mtr_find(dev, id);\n+\tif (mtr[0] == NULL)\n+\t\treturn -EINVAL;\n+\n+\tnum_mtr[0] = 1;\n+\tidx0 = roc_nix_bpf_level_to_idx(lvl_map[mtr[0]->level]);\n+\tif (idx0 == ROC_NIX_BPF_LEVEL_IDX_INVALID)\n+\t\treturn -EINVAL;\n+\n+\tlvl_mask = ROC_NIX_BPF_LEVEL_F_LEAF;\n+\tif (mtr[0]->is_used)\n+\t\tper_lvl_cnt[idx0] = 0;\n+\telse\n+\t\tper_lvl_cnt[idx0] = 1;\n+\n+\tif (mtr[0]->is_next) {\n+\t\tmtr[1] = nix_mtr_find(dev, mtr[0]->next_id);\n+\t\tif (mtr[1] == NULL)\n+\t\t\treturn -EINVAL;\n+\t\tnum_mtr[1] = 1;\n+\t\tidx1 = roc_nix_bpf_level_to_idx(lvl_map[mtr[1]->level]);\n+\t\tif (idx1 == ROC_NIX_BPF_LEVEL_IDX_INVALID)\n+\t\t\treturn -EINVAL;\n+\n+\t\tlvl_mask |= ROC_NIX_BPF_LEVEL_F_MID;\n+\t\tif (mtr[1]->is_used)\n+\t\t\tper_lvl_cnt[idx1] = 0;\n+\t\telse\n+\t\t\tper_lvl_cnt[idx1] = 1;\n+\t}\n+\n+\tif (mtr[1] && mtr[1]->is_next) {\n+\t\tmtr[2] = nix_mtr_find(dev, mtr[1]->next_id);\n+\t\tif (mtr[2] == NULL)\n+\t\t\treturn -EINVAL;\n+\n+\t\tnum_mtr[2] = 1;\n+\t\tidx2 = roc_nix_bpf_level_to_idx(lvl_map[mtr[2]->level]);\n+\t\tif (idx2 == ROC_NIX_BPF_LEVEL_IDX_INVALID)\n+\t\t\treturn -EINVAL;\n+\n+\t\tlvl_mask |= ROC_NIX_BPF_LEVEL_F_TOP;\n+\t\tif (mtr[2]->is_used)\n+\t\t\tper_lvl_cnt[idx2] = 0;\n+\t\telse\n+\t\t\tper_lvl_cnt[idx2] = 1;\n+\t}\n+\n+\trc = roc_nix_bpf_alloc(nix, lvl_mask, per_lvl_cnt, profs);\n+\tif (rc)\n+\t\treturn rc;\n+\tif (mtr[0]->bpf_id == ROC_NIX_BPF_ID_INVALID)\n+\t\tmtr[0]->bpf_id = profs[idx0].ids[0];\n+\n+\tif (num_mtr[0])\n+\t\tif (mtr[0]->is_next && idx1 != ROC_NIX_BPF_LEVEL_IDX_INVALID)\n+\t\t\tif (mtr[1]->bpf_id == ROC_NIX_BPF_ID_INVALID)\n+\t\t\t\tmtr[1]->bpf_id = profs[idx1].ids[0];\n+\n+\tif (num_mtr[1])\n+\t\tif (mtr[1]->is_next && idx2 != ROC_NIX_BPF_LEVEL_IDX_INVALID)\n+\t\t\tif (mtr[2]->bpf_id == ROC_NIX_BPF_ID_INVALID)\n+\t\t\t\tmtr[2]->bpf_id = profs[idx2].ids[0];\n+\n+\tfor (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {\n+\t\tif (num_mtr[i]) {\n+\t\t\tif (!mtr[i]->is_used) {\n+\t\t\t\tmemset(&cfg, 0, sizeof(struct roc_nix_bpf_cfg));\n+\t\t\t\tnix_mtr_config_map(mtr[i], &cfg);\n+\t\t\t\trc = roc_nix_bpf_config(nix, mtr[i]->bpf_id,\n+\t\t\t\t\t\t\tlvl_map[mtr[i]->level],\n+\t\t\t\t\t\t\t&cfg);\n+\n+\t\t\t\tmemset(&tbl, 0,\n+\t\t\t\t       sizeof(struct roc_nix_bpf_precolor));\n+\t\t\t\tnix_dscp_table_map(mtr[i], &tbl);\n+\t\t\t\trc = roc_nix_bpf_pre_color_tbl_setup(nix,\n+\t\t\t\t\tmtr[i]->bpf_id, lvl_map[mtr[i]->level],\n+\t\t\t\t\t&tbl);\n+\n+\t\t\t\tif (mtr[i]->params.meter_enable) {\n+\t\t\t\t\tfor (j = 0; j < mtr[i]->rq_num; j++) {\n+\t\t\t\t\t\trq = &dev->rqs[mtr[i]->rq_id\n+\t\t\t\t\t\t\t\t       [j]];\n+\t\t\t\t\t\trc = roc_nix_bpf_ena_dis(nix,\n+\t\t\t\t\t\t\tmtr[i]->bpf_id, rq,\n+\t\t\t\t\t\t\ttrue);\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\treturn rc;\n+}\n+\n+int\n+nix_mtr_color_action_validate(struct rte_eth_dev *eth_dev, uint32_t id,\n+\t\t\t      uint32_t *prev_id, uint32_t *next_id,\n+\t\t\t      struct cnxk_mtr_policy_node *policy,\n+\t\t\t      int *tree_level)\n+{\n+\tuint32_t action_fate_red = policy->actions[RTE_COLOR_RED].action_fate;\n+\tuint32_t action_fate_green =\n+\t\tpolicy->actions[RTE_COLOR_GREEN].action_fate;\n+\tuint32_t action_fate_yellow =\n+\t\tpolicy->actions[RTE_COLOR_YELLOW].action_fate;\n+\tuint32_t cur_mtr_id = *next_id;\n+\tuint32_t next_mtr_id = 0xffff;\n+\tuint32_t prev_mtr_id = 0xffff;\n+\tstruct cnxk_meter_node *mtr;\n+\n+\tif (action_fate_green == RTE_FLOW_ACTION_TYPE_METER)\n+\t\tnext_mtr_id = policy->actions[RTE_COLOR_GREEN].mtr_id;\n+\n+\tif (action_fate_yellow == RTE_FLOW_ACTION_TYPE_METER)\n+\t\tnext_mtr_id = policy->actions[RTE_COLOR_YELLOW].mtr_id;\n+\n+\tif (action_fate_red == RTE_FLOW_ACTION_TYPE_METER)\n+\t\tnext_mtr_id = policy->actions[RTE_COLOR_RED].mtr_id;\n+\n+\tif (next_mtr_id != 0xffff) {\n+\t\tswitch (*tree_level) {\n+\t\tcase 0:\n+\t\t\tmtr = nix_get_mtr(eth_dev, cur_mtr_id);\n+\t\t\tif (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {\n+\t\t\t\tnix_mtr_level_update(eth_dev, cur_mtr_id, 0);\n+\t\t\t\tnix_mtr_chain_update(eth_dev, cur_mtr_id, -1,\n+\t\t\t\t\t\t     next_mtr_id);\n+\t\t\t} else {\n+\t\t\t\tif (mtr->level == 0)\n+\t\t\t\t\tmtr->is_used = true;\n+\t\t\t\telse\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t\t(*tree_level)++;\n+\t\t\t*next_id = next_mtr_id;\n+\t\t\tbreak;\n+\t\tcase 1:\n+\t\t\tmtr = nix_get_mtr(eth_dev, cur_mtr_id);\n+\t\t\tif (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {\n+\t\t\t\tnix_mtr_level_update(eth_dev, cur_mtr_id, 1);\n+\t\t\t\tprev_mtr_id = id;\n+\t\t\t\tnix_mtr_chain_update(eth_dev, cur_mtr_id,\n+\t\t\t\t\t\t     prev_mtr_id, next_mtr_id);\n+\t\t\t} else {\n+\t\t\t\tif (mtr->level == 1) {\n+\t\t\t\t\tmtr->prev_cnt++;\n+\t\t\t\t\tprev_mtr_id = id;\n+\t\t\t\t\tnix_mtr_chain_update(eth_dev,\n+\t\t\t\t\t\tcur_mtr_id, prev_mtr_id,\n+\t\t\t\t\t\tnext_mtr_id);\n+\n+\t\t\t\t\tmtr->is_used = true;\n+\t\t\t\t} else {\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\t(*tree_level)++;\n+\t\t\t*next_id = next_mtr_id;\n+\t\t\t*prev_id = cur_mtr_id;\n+\t\t\tbreak;\n+\t\tcase 2:\n+\t\t\tnix_mtr_chain_reset(eth_dev, id);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t} else {\n+\t\tswitch (*tree_level) {\n+\t\tcase 0:\n+\t\t\tmtr = nix_get_mtr(eth_dev, cur_mtr_id);\n+\t\t\tif (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {\n+\t\t\t\tnix_mtr_level_update(eth_dev, cur_mtr_id, 0);\n+\t\t\t} else {\n+\t\t\t\tif (mtr->level == 0)\n+\t\t\t\t\tmtr->is_used = true;\n+\t\t\t\telse\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 1:\n+\t\t\tmtr = nix_get_mtr(eth_dev, cur_mtr_id);\n+\t\t\tif (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {\n+\t\t\t\tnix_mtr_level_update(eth_dev, cur_mtr_id, 1);\n+\t\t\t\tprev_mtr_id = id;\n+\t\t\t\tnix_mtr_chain_update(eth_dev, cur_mtr_id,\n+\t\t\t\t\t\t     prev_mtr_id, -1);\n+\t\t\t} else {\n+\t\t\t\tif (mtr->level == 1) {\n+\t\t\t\t\tmtr->prev_cnt++;\n+\t\t\t\t\tprev_mtr_id = id;\n+\t\t\t\t\tnix_mtr_chain_update(eth_dev,\n+\t\t\t\t\t\t\t     cur_mtr_id,\n+\t\t\t\t\t\t\t     prev_mtr_id, -1);\n+\t\t\t\t\tmtr->is_used = true;\n+\t\t\t\t} else {\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 2:\n+\t\t\tmtr = nix_get_mtr(eth_dev, cur_mtr_id);\n+\t\t\tif (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {\n+\t\t\t\tnix_mtr_level_update(eth_dev, cur_mtr_id, 2);\n+\t\t\t\tprev_mtr_id = *prev_id;\n+\t\t\t\tnix_mtr_chain_update(eth_dev, cur_mtr_id,\n+\t\t\t\t\t\t     prev_mtr_id, -1);\n+\t\t\t} else {\n+\t\t\t\tif (mtr->level == 2) {\n+\t\t\t\t\tmtr->prev_cnt++;\n+\t\t\t\t\tprev_mtr_id = *prev_id;\n+\t\t\t\t\tnix_mtr_chain_update(eth_dev,\n+\t\t\t\t\t\t\t     cur_mtr_id,\n+\t\t\t\t\t\t\t     prev_mtr_id, -1);\n+\t\t\t\t\tmtr->is_used = true;\n+\t\t\t\t} else {\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n+\t\t*next_id = 0xffff;\n+\t}\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/cnxk/cnxk_rte_flow.c b/drivers/net/cnxk/cnxk_rte_flow.c\nindex 32c1b5dee5..56dcd36c61 100644\n--- a/drivers/net/cnxk/cnxk_rte_flow.c\n+++ b/drivers/net/cnxk/cnxk_rte_flow.c\n@@ -195,6 +195,10 @@ cnxk_map_actions(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,\n \t\t\t\tROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT;\n \t\t\tin_actions[i].conf = actions->conf;\n \t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_METER:\n+\t\t\tin_actions[i].type = ROC_NPC_ACTION_TYPE_METER;\n+\t\t\tin_actions[i].conf = actions->conf;\n+\t\t\tbreak;\n \t\tdefault:\n \t\t\tplt_npc_dbg(\"Action is not supported = %d\",\n \t\t\t\t    actions->type);\n",
    "prefixes": [
        "v4",
        "27/28"
    ]
}