get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 91583,
    "url": "https://patches.dpdk.org/api/patches/91583/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20210415151135.2098674-4-lizh@nvidia.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": "<20210415151135.2098674-4-lizh@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210415151135.2098674-4-lizh@nvidia.com",
    "date": "2021-04-15T15:11:23",
    "name": "[v5,03/14] net/mlx5: fix meter statistics",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "1160df1f53d12e6f70bf556fc684abb073ad1bd5",
    "submitter": {
        "id": 1967,
        "url": "https://patches.dpdk.org/api/people/1967/?format=api",
        "name": "Li Zhang",
        "email": "lizh@nvidia.com"
    },
    "delegate": {
        "id": 3268,
        "url": "https://patches.dpdk.org/api/users/3268/?format=api",
        "username": "rasland",
        "first_name": "Raslan",
        "last_name": "Darawsheh",
        "email": "rasland@nvidia.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20210415151135.2098674-4-lizh@nvidia.com/mbox/",
    "series": [
        {
            "id": 16417,
            "url": "https://patches.dpdk.org/api/series/16417/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=16417",
            "date": "2021-04-15T15:11:20",
            "name": "Add ASO meter support in MLX5 PMD",
            "version": 5,
            "mbox": "https://patches.dpdk.org/series/16417/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/91583/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/91583/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 5FBE3A0C3F;\n\tThu, 15 Apr 2021 17:12:21 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 4241716231D;\n\tThu, 15 Apr 2021 17:11:58 +0200 (CEST)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by mails.dpdk.org (Postfix) with ESMTP id 430D81622FD\n for <dev@dpdk.org>; Thu, 15 Apr 2021 17:11:51 +0200 (CEST)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n lizh@nvidia.com)\n with SMTP; 15 Apr 2021 18:11:46 +0300",
            "from nvidia.com (c-235-17-1-009.mtl.labs.mlnx [10.235.17.9])\n by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 13FFBjPI032677;\n Thu, 15 Apr 2021 18:11:46 +0300"
        ],
        "From": "Li Zhang <lizh@nvidia.com>",
        "To": "dekelp@nvidia.com, orika@nvidia.com, viacheslavo@nvidia.com,\n matan@nvidia.com, shahafs@nvidia.com, Suanming Mou <suanmingm@mellanox.com>",
        "Cc": "dev@dpdk.org, thomas@monjalon.net, rasland@nvidia.com, roniba@nvidia.com,\n Shun Hao <shunh@nvidia.com>, stable@dpdk.org",
        "Date": "Thu, 15 Apr 2021 18:11:23 +0300",
        "Message-Id": "<20210415151135.2098674-4-lizh@nvidia.com>",
        "X-Mailer": "git-send-email 2.21.0",
        "In-Reply-To": "<20210415151135.2098674-1-lizh@nvidia.com>",
        "References": "<20210331073632.1443011-1-lizh@nvidia.com>\n <20210415151135.2098674-1-lizh@nvidia.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v5 03/14] net/mlx5: fix meter statistics",
        "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: Shun Hao <shunh@nvidia.com>\n\nCurrently, packets after meter will be steered to a global policer\ntable,\nwhich includes green/red color rules for every meter, so as to have\ncounter statistics of each color in every meter.\n\nThere's a bug that all the rules in global policer table are matching\nonly color criteria, so all packets will be counted to one meter only,\nand other meter statistics are always zero.\n\nThis patch does these:\n1. The rules in policer table matches both meter index and color, so\npacket after meter could be counted to the correct meter counter.\n2. The meter index and flow index are now sharing the available\nregister bits dynamically. Meter index starts from lsb, and flow\nindex starts from msb.\n\nFixes: 46a5e6bc6a (\"net/mlx5: prepare meter flow tables\")\nCc: stable@dpdk.org\n\nSigned-off-by: Shun Hao <shunh@nvidia.com>\nAcked-by: Matan Azrad <matan@nvidia.com>\n---\n drivers/net/mlx5/mlx5.c            |   7 +-\n drivers/net/mlx5/mlx5.h            |  15 +-\n drivers/net/mlx5/mlx5_flow.c       | 183 +++++++----\n drivers/net/mlx5/mlx5_flow.h       |  40 +--\n drivers/net/mlx5/mlx5_flow_dv.c    | 489 ++++++++++++++++++-----------\n drivers/net/mlx5/mlx5_flow_meter.c |  53 +++-\n 6 files changed, 496 insertions(+), 291 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex 02cc2c781e..a6cc2d3108 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -277,10 +277,13 @@ static const struct mlx5_indexed_pool_config mlx5_ipool_cfg[] = {\n \t},\n #endif\n \t[MLX5_IPOOL_MTR] = {\n+\t\t/**\n+\t\t * The ipool index should grow continually from small to big,\n+\t\t * for meter idx, so not set grow_trunk to avoid meter index\n+\t\t * not jump continually.\n+\t\t */\n \t\t.size = sizeof(struct mlx5_flow_meter),\n \t\t.trunk_size = 64,\n-\t\t.grow_trunk = 3,\n-\t\t.grow_shift = 2,\n \t\t.need_lock = 1,\n \t\t.release_mem_en = 1,\n \t\t.malloc = mlx5_malloc,\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex e0f7101dbb..c4a04716f7 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -944,9 +944,9 @@ struct mlx5_priv {\n \tunsigned int representor:1; /* Device is a port representor. */\n \tunsigned int master:1; /* Device is a E-Switch master. */\n \tunsigned int txpp_en:1; /* Tx packet pacing enabled. */\n+\tunsigned int sampler_en:1; /* Whether support sampler. */\n \tunsigned int mtr_en:1; /* Whether support meter. */\n \tunsigned int mtr_reg_share:1; /* Whether support meter REG_C share. */\n-\tunsigned int sampler_en:1; /* Whether support sampler. */\n \tuint16_t domain_id; /* Switch domain identifier. */\n \tuint16_t vport_id; /* Associated VF vport index (if any). */\n \tuint32_t vport_meta_tag; /* Used for vport index match ove VF LAG. */\n@@ -1003,6 +1003,10 @@ struct mlx5_priv {\n \tuint32_t rss_shared_actions; /* RSS shared actions. */\n \tstruct mlx5_devx_obj *q_counters; /* DevX queue counter object. */\n \tuint32_t counter_set_id; /* Queue counter ID to set in DevX objects. */\n+\tuint8_t max_mtr_bits;\n+\t/* Indicate how many bits are used by meter id at the most. */\n+\tuint8_t max_mtr_flow_bits;\n+\t/* Indicate how many bits are used by meter flow id at the most. */\n };\n \n #define PORT_ID(priv) ((priv)->dev_data->port_id)\n@@ -1271,11 +1275,10 @@ int mlx5_pmd_socket_init(void);\n int mlx5_flow_meter_ops_get(struct rte_eth_dev *dev, void *arg);\n struct mlx5_flow_meter *mlx5_flow_meter_find(struct mlx5_priv *priv,\n \t\t\t\t\t     uint32_t meter_id);\n-struct mlx5_flow_meter *mlx5_flow_meter_attach\n-\t\t\t\t\t(struct mlx5_priv *priv,\n-\t\t\t\t\t uint32_t meter_id,\n-\t\t\t\t\t const struct rte_flow_attr *attr,\n-\t\t\t\t\t struct rte_flow_error *error);\n+int mlx5_flow_meter_attach(struct mlx5_priv *priv,\n+\t\t\t   struct mlx5_flow_meter *fm,\n+\t\t\t   const struct rte_flow_attr *attr,\n+\t\t\t   struct rte_flow_error *error);\n void mlx5_flow_meter_detach(struct mlx5_flow_meter *fm);\n \n /* mlx5_os.c */\ndiff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex 84463074a5..3ef98b24c4 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -749,9 +749,9 @@ mlx5_flow_get_reg_id(struct rte_eth_dev *dev,\n \t\t\treturn REG_C_0;\n \t\t}\n \t\tbreak;\n-\tcase MLX5_MTR_SFX:\n+\tcase MLX5_MTR_ID:\n \t\t/*\n-\t\t * If meter color and flow match share one register, flow match\n+\t\t * If meter color and meter id share one register, flow match\n \t\t * should use the meter color register for match.\n \t\t */\n \t\tif (priv->mtr_reg_share)\n@@ -3036,7 +3036,8 @@ flow_mreg_split_qrss_release(struct rte_eth_dev *dev,\n \n \tSILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,\n \t\t       handle_idx, dev_handle, next)\n-\t\tif (dev_handle->split_flow_id)\n+\t\tif (dev_handle->split_flow_id &&\n+\t\t    !dev_handle->is_meter_flow_id)\n \t\t\tmlx5_ipool_free(priv->sh->ipool\n \t\t\t\t\t[MLX5_IPOOL_RSS_EXPANTION_FLOW_ID],\n \t\t\t\t\tdev_handle->split_flow_id);\n@@ -3675,23 +3676,30 @@ flow_parse_metadata_split_actions_info(const struct rte_flow_action actions[],\n  *\n  * @param[in] actions\n  *   Pointer to the list of actions.\n- * @param[out] mtr\n+ * @param[out] has_mtr\n  *   Pointer to the meter exist flag.\n+ * @param[out] meter_id\n+ *   Pointer to the meter id.\n  *\n  * @return\n  *   Total number of actions.\n  */\n static int\n-flow_check_meter_action(const struct rte_flow_action actions[], uint32_t *mtr)\n+flow_check_meter_action(const struct rte_flow_action actions[],\n+\t\t\tbool *has_mtr,\n+\t\t\tuint32_t *meter_id)\n {\n+\tconst struct rte_flow_action_meter *mtr = NULL;\n \tint actions_n = 0;\n \n-\tMLX5_ASSERT(mtr);\n-\t*mtr = 0;\n+\tMLX5_ASSERT(has_mtr);\n+\t*has_mtr = false;\n \tfor (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {\n \t\tswitch (actions->type) {\n \t\tcase RTE_FLOW_ACTION_TYPE_METER:\n-\t\t\t*mtr = 1;\n+\t\t\tmtr = actions->conf;\n+\t\t\t*meter_id = mtr->mtr_id;\n+\t\t\t*has_mtr = true;\n \t\t\tbreak;\n \t\tdefault:\n \t\t\tbreak;\n@@ -4348,8 +4356,10 @@ flow_create_split_inner(struct rte_eth_dev *dev,\n  * header will be in the prefix sub flow, as not to take the\n  * L3 tunnel header into account.\n  *\n- * @param dev\n+ * @param[in] dev\n  *   Pointer to Ethernet device.\n+ * @param[in] fm\n+ *   Pointer to flow meter structure.\n  * @param[in] items\n  *   Pattern specification (list terminated by the END pattern item).\n  * @param[out] sfx_items\n@@ -4364,29 +4374,39 @@ flow_create_split_inner(struct rte_eth_dev *dev,\n  *   The pattern items for the suffix flow.\n  * @param[out] tag_sfx\n  *   Pointer to suffix flow tag.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL.\n  *\n  * @return\n- *   0 on success.\n+ *   The flow id, 0 otherwise and rte_errno is set.\n  */\n-static int\n+static uint32_t\n flow_meter_split_prep(struct rte_eth_dev *dev,\n-\t\t const struct rte_flow_item items[],\n-\t\t struct rte_flow_item sfx_items[],\n-\t\t const struct rte_flow_action actions[],\n-\t\t struct rte_flow_action actions_sfx[],\n-\t\t struct rte_flow_action actions_pre[])\n+\t\t      struct mlx5_flow_meter *fm,\n+\t\t      const struct rte_flow_item items[],\n+\t\t      struct rte_flow_item sfx_items[],\n+\t\t      const struct rte_flow_action actions[],\n+\t\t      struct rte_flow_action actions_sfx[],\n+\t\t      struct rte_flow_action actions_pre[],\n+\t\t      struct rte_flow_error *error)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct rte_flow_action *tag_action = NULL;\n \tstruct rte_flow_item *tag_item;\n \tstruct mlx5_rte_flow_action_set_tag *set_tag;\n-\tstruct rte_flow_error error;\n \tconst struct rte_flow_action_raw_encap *raw_encap;\n \tconst struct rte_flow_action_raw_decap *raw_decap;\n-\tstruct mlx5_rte_flow_item_tag *tag_spec;\n-\tstruct mlx5_rte_flow_item_tag *tag_mask;\n+\tstruct mlx5_rte_flow_item_tag *tag_item_spec;\n+\tstruct mlx5_rte_flow_item_tag *tag_item_mask;\n \tuint32_t tag_id = 0;\n \tbool copy_vlan = false;\n+\tuint8_t mtr_id_offset = priv->mtr_reg_share ? MLX5_MTR_COLOR_BITS : 0;\n+\tuint8_t mtr_reg_bits = priv->mtr_reg_share ?\n+\t\t\t\tMLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS;\n+\tuint32_t flow_id = 0;\n+\tuint32_t flow_id_reversed = 0;\n+\tuint8_t flow_id_bits = 0;\n+\tint shift;\n \n \t/* Prepare the actions for prefix and suffix flow. */\n \tfor (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {\n@@ -4395,10 +4415,7 @@ flow_meter_split_prep(struct rte_eth_dev *dev,\n \t\tswitch (actions->type) {\n \t\tcase RTE_FLOW_ACTION_TYPE_METER:\n \t\t\t/* Add the extra tag action first. */\n-\t\t\ttag_action = actions_pre;\n-\t\t\ttag_action->type = (enum rte_flow_action_type)\n-\t\t\t\t\t   MLX5_RTE_FLOW_ACTION_TYPE_TAG;\n-\t\t\tactions_pre++;\n+\t\t\ttag_action = actions_pre++;\n \t\t\taction_cur = &actions_pre;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:\n@@ -4431,23 +4448,22 @@ flow_meter_split_prep(struct rte_eth_dev *dev,\n \tactions_sfx->type = RTE_FLOW_ACTION_TYPE_END;\n \tactions_pre->type = RTE_FLOW_ACTION_TYPE_END;\n \tactions_pre++;\n-\t/* Set the tag. */\n-\tset_tag = (void *)actions_pre;\n-\tset_tag->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0, &error);\n-\tmlx5_ipool_malloc(priv->sh->ipool[MLX5_IPOOL_RSS_EXPANTION_FLOW_ID],\n-\t\t\t  &tag_id);\n-\tif (tag_id >= (1 << (sizeof(tag_id) * 8 - MLX5_MTR_COLOR_BITS))) {\n-\t\tDRV_LOG(ERR, \"Port %u meter flow id exceed max limit.\",\n-\t\t\tdev->data->port_id);\n-\t\tmlx5_ipool_free(priv->sh->ipool\n-\t\t\t\t[MLX5_IPOOL_RSS_EXPANTION_FLOW_ID], tag_id);\n-\t\treturn 0;\n-\t} else if (!tag_id) {\n-\t\treturn 0;\n+\tmlx5_ipool_malloc(fm->flow_ipool, &tag_id);\n+\tif (!tag_id)\n+\t\treturn rte_flow_error_set(error, ENOMEM,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\"Failed to allocate meter flow id.\");\n+\tflow_id = tag_id - 1;\n+\tflow_id_bits = MLX5_REG_BITS - __builtin_clz(flow_id);\n+\tflow_id_bits = flow_id_bits ? flow_id_bits : 1;\n+\tif ((flow_id_bits + priv->max_mtr_bits) > mtr_reg_bits) {\n+\t\tmlx5_ipool_free(fm->flow_ipool, tag_id);\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\"Meter flow id exceeds max limit.\");\n \t}\n-\tset_tag->data = tag_id << MLX5_MTR_COLOR_BITS;\n-\tassert(tag_action);\n-\ttag_action->conf = set_tag;\n+\tif (flow_id_bits > priv->max_mtr_flow_bits)\n+\t\tpriv->max_mtr_flow_bits = flow_id_bits;\n \t/* Prepare the suffix subflow items. */\n \ttag_item = sfx_items++;\n \tfor (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {\n@@ -4476,16 +4492,34 @@ flow_meter_split_prep(struct rte_eth_dev *dev,\n \t}\n \tsfx_items->type = RTE_FLOW_ITEM_TYPE_END;\n \tsfx_items++;\n-\ttag_spec = (struct mlx5_rte_flow_item_tag *)sfx_items;\n-\ttag_spec->data = tag_id << MLX5_MTR_COLOR_BITS;\n-\ttag_spec->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0, &error);\n-\ttag_mask = tag_spec + 1;\n-\ttag_mask->data = 0xffffff00;\n+\t/* Build tag actions and items for meter_id/meter flow_id. */\n+\tassert(tag_action);\n+\tset_tag = (struct mlx5_rte_flow_action_set_tag *)actions_pre;\n+\ttag_item_spec = (struct mlx5_rte_flow_item_tag *)sfx_items;\n+\ttag_item_mask = tag_item_spec + 1;\n+\t/*\n+\t * The color Reg bits used by flow_id are growing from\n+\t * msb to lsb, so must do bit reverse for flow_id val in RegC.\n+\t */\n+\tfor (shift = 0; shift < flow_id_bits; shift++)\n+\t\tflow_id_reversed = (flow_id_reversed << 1) |\n+\t\t\t      ((flow_id >> shift) & 0x1);\n+\t/* Both flow_id and meter_id share the same register. */\n+\tset_tag->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_ID, 0, error);\n+\tset_tag->data =\n+\t\t(fm->idx | (flow_id_reversed << (mtr_reg_bits - flow_id_bits)))\n+\t\t<< mtr_id_offset;\n+\ttag_item_spec->id = set_tag->id;\n+\ttag_item_spec->data = set_tag->data;\n+\ttag_item_mask->data = UINT32_MAX << mtr_id_offset;\n+\ttag_action->type = (enum rte_flow_action_type)\n+\t\t\t\tMLX5_RTE_FLOW_ACTION_TYPE_TAG;\n+\ttag_action->conf = set_tag;\n \ttag_item->type = (enum rte_flow_item_type)\n-\t\t\t MLX5_RTE_FLOW_ITEM_TYPE_TAG;\n-\ttag_item->spec = tag_spec;\n+\t\t\t\tMLX5_RTE_FLOW_ITEM_TYPE_TAG;\n+\ttag_item->spec = tag_item_spec;\n \ttag_item->last = NULL;\n-\ttag_item->mask = tag_mask;\n+\ttag_item->mask = tag_item_mask;\n \treturn tag_id;\n }\n \n@@ -5185,25 +5219,49 @@ flow_create_split_meter(struct rte_eth_dev *dev,\n \t\t\tstruct rte_flow_error *error)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();\n \tstruct rte_flow_action *sfx_actions = NULL;\n \tstruct rte_flow_action *pre_actions = NULL;\n \tstruct rte_flow_item *sfx_items = NULL;\n \tstruct mlx5_flow *dev_flow = NULL;\n \tstruct rte_flow_attr sfx_attr = *attr;\n-\tuint32_t mtr = 0;\n+\tstruct mlx5_flow_meter *fm = NULL;\n+\tbool has_mtr = false;\n+\tuint32_t meter_id;\n \tuint32_t mtr_tag_id = 0;\n \tsize_t act_size;\n \tsize_t item_size;\n \tint actions_n = 0;\n-\tint ret;\n+\tint ret = 0;\n \n \tif (priv->mtr_en)\n-\t\tactions_n = flow_check_meter_action(actions, &mtr);\n-\tif (mtr) {\n-\t\t/* The five prefix actions: meter, decap, encap, tag, end. */\n+\t\tactions_n = flow_check_meter_action(actions, &has_mtr,\n+\t\t\t\t\t\t    &meter_id);\n+\tif (has_mtr) {\n+\t\tif (flow->meter) {\n+\t\t\tfm = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR],\n+\t\t\t\t\t    flow->meter);\n+\t\t\tif (!fm)\n+\t\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t\t\tNULL, \"Meter not found.\");\n+\t\t} else {\n+\t\t\tfm = mlx5_flow_meter_find(priv, meter_id);\n+\t\t\tif (!fm)\n+\t\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t\t\tNULL, \"Meter not found.\");\n+\t\t\tret = mlx5_flow_meter_attach(priv, fm,\n+\t\t\t\t\t\t     &sfx_attr, error);\n+\t\t\tif (ret)\n+\t\t\t\treturn -rte_errno;\n+\t\t\tflow->meter = fm->idx;\n+\t\t}\n+\t\twks->fm = fm;\n+\t\t/* The prefix actions: meter, decap, encap, tag, end. */\n \t\tact_size = sizeof(struct rte_flow_action) * (actions_n + 5) +\n \t\t\t   sizeof(struct mlx5_rte_flow_action_set_tag);\n-\t\t/* tag, vlan, port id, end. */\n+\t\t/* The suffix items: tag, vlan, port id, end. */\n #define METER_SUFFIX_ITEM 4\n \t\titem_size = sizeof(struct rte_flow_item) * METER_SUFFIX_ITEM +\n \t\t\t    sizeof(struct mlx5_rte_flow_item_tag) * 2;\n@@ -5217,9 +5275,9 @@ flow_create_split_meter(struct rte_eth_dev *dev,\n \t\tsfx_items = (struct rte_flow_item *)((char *)sfx_actions +\n \t\t\t     act_size);\n \t\tpre_actions = sfx_actions + actions_n;\n-\t\tmtr_tag_id = flow_meter_split_prep(dev, items, sfx_items,\n+\t\tmtr_tag_id = flow_meter_split_prep(dev, fm, items, sfx_items,\n \t\t\t\t\t\t   actions, sfx_actions,\n-\t\t\t\t\t\t   pre_actions);\n+\t\t\t\t\t\t   pre_actions, error);\n \t\tif (!mtr_tag_id) {\n \t\t\tret = -rte_errno;\n \t\t\tgoto exit;\n@@ -5230,10 +5288,12 @@ flow_create_split_meter(struct rte_eth_dev *dev,\n \t\t\t\t\t      attr, items, pre_actions,\n \t\t\t\t\t      flow_split_info, error);\n \t\tif (ret) {\n+\t\t\tmlx5_ipool_free(fm->flow_ipool, mtr_tag_id);\n \t\t\tret = -rte_errno;\n \t\t\tgoto exit;\n \t\t}\n \t\tdev_flow->handle->split_flow_id = mtr_tag_id;\n+\t\tdev_flow->handle->is_meter_flow_id = 1;\n \t\t/* Setting the sfx group atrr. */\n \t\tsfx_attr.group = sfx_attr.transfer ?\n \t\t\t\t(MLX5_FLOW_TABLE_LEVEL_SUFFIX - 1) :\n@@ -6505,20 +6565,17 @@ mlx5_flow_ops_get(struct rte_eth_dev *dev __rte_unused,\n  *\n  * @param[in] dev\n  *   Pointer to Ethernet device.\n- * @param[in] fm\n- *   Pointer to the flow meter.\n  *\n  * @return\n  *   Pointer to table set on success, NULL otherwise.\n  */\n struct mlx5_meter_domains_infos *\n-mlx5_flow_create_mtr_tbls(struct rte_eth_dev *dev,\n-\t\t\t  const struct mlx5_flow_meter *fm)\n+mlx5_flow_create_mtr_tbls(struct rte_eth_dev *dev)\n {\n \tconst struct mlx5_flow_driver_ops *fops;\n \n \tfops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);\n-\treturn fops->create_mtr_tbls(dev, fm);\n+\treturn fops->create_mtr_tbls(dev);\n }\n \n /**\n@@ -6543,7 +6600,7 @@ mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,\n }\n \n /**\n- * Create policer rules.\n+ * Prepare policer rules.\n  *\n  * @param[in] dev\n  *   Pointer to Ethernet device.\n@@ -6556,14 +6613,14 @@ mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,\n  *   0 on success, -1 otherwise.\n  */\n int\n-mlx5_flow_create_policer_rules(struct rte_eth_dev *dev,\n+mlx5_flow_prepare_policer_rules(struct rte_eth_dev *dev,\n \t\t\t       struct mlx5_flow_meter *fm,\n \t\t\t       const struct rte_flow_attr *attr)\n {\n \tconst struct mlx5_flow_driver_ops *fops;\n \n \tfops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);\n-\treturn fops->create_policer_rules(dev, fm, attr);\n+\treturn fops->prepare_policer_rules(dev, fm, attr);\n }\n \n /**\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex ec673c29ab..4482a456f0 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -79,7 +79,7 @@ enum mlx5_feature_name {\n \tMLX5_APP_TAG,\n \tMLX5_COPY_MARK,\n \tMLX5_MTR_COLOR,\n-\tMLX5_MTR_SFX,\n+\tMLX5_MTR_ID,\n \tMLX5_ASO_FLOW_HIT,\n };\n \n@@ -655,7 +655,8 @@ struct mlx5_flow_handle {\n \tuint64_t layers;\n \t/**< Bit-fields of present layers, see MLX5_FLOW_LAYER_*. */\n \tvoid *drv_flow; /**< pointer to driver flow object. */\n-\tuint32_t split_flow_id:28; /**< Sub flow unique match flow id. */\n+\tuint32_t split_flow_id:27; /**< Sub flow unique match flow id. */\n+\tuint32_t is_meter_flow_id:1; /**< Indate if flow_id is for meter. */\n \tuint32_t mark:1; /**< Metadate rxq mark flag. */\n \tuint32_t fate_action:3; /**< Fate action type. */\n \tunion {\n@@ -842,14 +843,16 @@ struct mlx5_meter_domain_info {\n \t/**< Meter table. */\n \tstruct mlx5_flow_tbl_resource *sfx_tbl;\n \t/**< Meter suffix table. */\n-\tvoid *any_matcher;\n-\t/**< Meter color not match default criteria. */\n-\tvoid *color_matcher;\n-\t/**< Meter color match criteria. */\n+\tstruct mlx5_flow_dv_matcher *drop_matcher;\n+\t/**< Matcher for Drop. */\n+\tstruct mlx5_flow_dv_matcher *color_matcher;\n+\t/**< Matcher for Color. */\n \tvoid *jump_actn;\n \t/**< Meter match action. */\n-\tvoid *policer_rules[RTE_MTR_DROPPED + 1];\n-\t/**< Meter policer for the match. */\n+\tvoid *green_rule;\n+\t/**< Meter green rule. */\n+\tvoid *drop_rule;\n+\t/**< Meter drop rule. */\n };\n \n /* Meter table set for TX RX FDB. */\n@@ -862,10 +865,10 @@ struct mlx5_meter_domains_infos {\n \t/**< RX meter table. */\n \tstruct mlx5_meter_domain_info transfer;\n \t/**< FDB meter table. */\n-\tvoid *drop_actn;\n-\t/**< Drop action as not matched. */\n-\tvoid *count_actns[RTE_MTR_DROPPED + 1];\n-\t/**< Counters for match and unmatched statistics. */\n+\tvoid *green_count;\n+\t/**< Counters for green rule. */\n+\tvoid *drop_count;\n+\t/**< Counters for green rule. */\n \tuint32_t fmp[MLX5_ST_SZ_DW(flow_meter_parameters)];\n \t/**< Flow meter parameter. */\n \tsize_t fmp_size;\n@@ -928,6 +931,8 @@ struct mlx5_flow_meter {\n \t/**< Meter state. */\n \tuint32_t shared:1;\n \t/**< Meter shared or not. */\n+\tstruct mlx5_indexed_pool *flow_ipool;\n+\t/**< Index pool for flow id. */\n };\n \n /* RFC2697 parameter structure. */\n@@ -1166,6 +1171,7 @@ struct mlx5_flow_workspace {\n \tstruct mlx5_flow_rss_desc rss_desc;\n \tuint32_t rssq_num; /* Allocated queue num in rss_desc. */\n \tuint32_t flow_idx; /* Intermediate device flow index. */\n+\tstruct mlx5_flow_meter *fm; /* Pointer to the meter in flow. */\n };\n \n struct mlx5_flow_split_info {\n@@ -1206,8 +1212,7 @@ typedef int (*mlx5_flow_query_t)(struct rte_eth_dev *dev,\n \t\t\t\t void *data,\n \t\t\t\t struct rte_flow_error *error);\n typedef struct mlx5_meter_domains_infos *(*mlx5_flow_create_mtr_tbls_t)\n-\t\t\t\t\t    (struct rte_eth_dev *dev,\n-\t\t\t\t\t     const struct mlx5_flow_meter *fm);\n+\t\t\t\t\t    (struct rte_eth_dev *dev);\n typedef int (*mlx5_flow_destroy_mtr_tbls_t)(struct rte_eth_dev *dev,\n \t\t\t\t\tstruct mlx5_meter_domains_infos *tbls);\n typedef int (*mlx5_flow_create_policer_rules_t)\n@@ -1270,7 +1275,7 @@ struct mlx5_flow_driver_ops {\n \tmlx5_flow_query_t query;\n \tmlx5_flow_create_mtr_tbls_t create_mtr_tbls;\n \tmlx5_flow_destroy_mtr_tbls_t destroy_mtr_tbls;\n-\tmlx5_flow_create_policer_rules_t create_policer_rules;\n+\tmlx5_flow_create_policer_rules_t prepare_policer_rules;\n \tmlx5_flow_destroy_policer_rules_t destroy_policer_rules;\n \tmlx5_flow_counter_alloc_t counter_alloc;\n \tmlx5_flow_counter_free_t counter_free;\n@@ -1470,11 +1475,10 @@ int mlx5_flow_validate_item_ecpri(const struct rte_flow_item *item,\n \t\t\t\t  const struct rte_flow_item_ecpri *acc_mask,\n \t\t\t\t  struct rte_flow_error *error);\n struct mlx5_meter_domains_infos *mlx5_flow_create_mtr_tbls\n-\t\t\t\t\t(struct rte_eth_dev *dev,\n-\t\t\t\t\t const struct mlx5_flow_meter *fm);\n+\t\t\t\t\t(struct rte_eth_dev *dev);\n int mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,\n \t\t\t       struct mlx5_meter_domains_infos *tbl);\n-int mlx5_flow_create_policer_rules(struct rte_eth_dev *dev,\n+int mlx5_flow_prepare_policer_rules(struct rte_eth_dev *dev,\n \t\t\t\t   struct mlx5_flow_meter *fm,\n \t\t\t\t   const struct rte_flow_attr *attr);\n int mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,\ndiff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c\nindex e65cc13bd6..feac8bca34 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -10982,14 +10982,12 @@ flow_dv_translate(struct rte_eth_dev *dev,\n \t\tconst struct rte_flow_action_rss *rss;\n \t\tconst struct rte_flow_action *action = actions;\n \t\tconst uint8_t *rss_key;\n-\t\tconst struct rte_flow_action_meter *mtr;\n \t\tstruct mlx5_flow_tbl_resource *tbl;\n \t\tstruct mlx5_aso_age_action *age_act;\n \t\tuint32_t port_id = 0;\n \t\tstruct mlx5_flow_dv_port_id_action_resource port_id_resource;\n \t\tint action_type = actions->type;\n \t\tconst struct rte_flow_action *found_action = NULL;\n-\t\tstruct mlx5_flow_meter *fm = NULL;\n \t\tuint32_t jump_group = 0;\n \n \t\tif (!mlx5_flow_os_action_supported(action_type))\n@@ -11414,33 +11412,13 @@ flow_dv_translate(struct rte_eth_dev *dev,\n \t\t\t\t\tMLX5_FLOW_FATE_DEFAULT_MISS;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_METER:\n-\t\t\tmtr = actions->conf;\n-\t\t\tif (!flow->meter) {\n-\t\t\t\tfm = mlx5_flow_meter_attach(priv, mtr->mtr_id,\n-\t\t\t\t\t\t\t    attr, error);\n-\t\t\t\tif (!fm)\n-\t\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\t\trte_errno,\n-\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\tNULL,\n-\t\t\t\t\t\t\"meter not found \"\n-\t\t\t\t\t\t\"or invalid parameters\");\n-\t\t\t\tflow->meter = fm->idx;\n-\t\t\t}\n+\t\t\tif (!wks->fm)\n+\t\t\t\treturn rte_flow_error_set(error, rte_errno,\n+\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\tNULL, \"Failed to get meter in flow.\");\n \t\t\t/* Set the meter action. */\n-\t\t\tif (!fm) {\n-\t\t\t\tfm = mlx5_ipool_get(priv->sh->ipool\n-\t\t\t\t\t\t[MLX5_IPOOL_MTR], flow->meter);\n-\t\t\t\tif (!fm)\n-\t\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\t\trte_errno,\n-\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\tNULL,\n-\t\t\t\t\t\t\"meter not found \"\n-\t\t\t\t\t\t\"or invalid parameters\");\n-\t\t\t}\n \t\t\tdev_flow->dv.actions[actions_n++] =\n-\t\t\t\tfm->mfts->meter_action;\n+\t\t\t\twks->fm->mfts->meter_action;\n \t\t\taction_flags |= MLX5_FLOW_ACTION_METER;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:\n@@ -12589,6 +12567,7 @@ flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)\n {\n \tstruct mlx5_flow_handle *dev_handle;\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_flow_meter *fm = NULL;\n \tuint32_t srss = 0;\n \n \tif (!flow)\n@@ -12599,8 +12578,6 @@ flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)\n \t\tflow->counter = 0;\n \t}\n \tif (flow->meter) {\n-\t\tstruct mlx5_flow_meter *fm;\n-\n \t\tfm = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR],\n \t\t\t\t    flow->meter);\n \t\tif (fm)\n@@ -12642,6 +12619,10 @@ flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)\n \t\t\tflow_dv_fate_resource_release(dev, dev_handle);\n \t\telse if (!srss)\n \t\t\tsrss = dev_handle->rix_srss;\n+\t\tif (fm && dev_handle->is_meter_flow_id &&\n+\t\t    dev_handle->split_flow_id)\n+\t\t\tmlx5_ipool_free(fm->flow_ipool,\n+\t\t\t\t\tdev_handle->split_flow_id);\n \t\tmlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],\n \t\t\t   tmp_idx);\n \t}\n@@ -13407,49 +13388,20 @@ flow_dv_destroy_mtr_tbl(struct rte_eth_dev *dev,\n \n \tif (!mtd || !priv->config.dv_flow_en)\n \t\treturn 0;\n-\tif (mtd->ingress.policer_rules[RTE_MTR_DROPPED])\n-\t\tclaim_zero(mlx5_flow_os_destroy_flow\n-\t\t\t   (mtd->ingress.policer_rules[RTE_MTR_DROPPED]));\n-\tif (mtd->egress.policer_rules[RTE_MTR_DROPPED])\n-\t\tclaim_zero(mlx5_flow_os_destroy_flow\n-\t\t\t   (mtd->egress.policer_rules[RTE_MTR_DROPPED]));\n-\tif (mtd->transfer.policer_rules[RTE_MTR_DROPPED])\n-\t\tclaim_zero(mlx5_flow_os_destroy_flow\n-\t\t\t   (mtd->transfer.policer_rules[RTE_MTR_DROPPED]));\n-\tif (mtd->egress.color_matcher)\n-\t\tclaim_zero(mlx5_flow_os_destroy_flow_matcher\n-\t\t\t   (mtd->egress.color_matcher));\n-\tif (mtd->egress.any_matcher)\n-\t\tclaim_zero(mlx5_flow_os_destroy_flow_matcher\n-\t\t\t   (mtd->egress.any_matcher));\n \tif (mtd->egress.tbl)\n \t\tflow_dv_tbl_resource_release(MLX5_SH(dev), mtd->egress.tbl);\n \tif (mtd->egress.sfx_tbl)\n \t\tflow_dv_tbl_resource_release(MLX5_SH(dev), mtd->egress.sfx_tbl);\n-\tif (mtd->ingress.color_matcher)\n-\t\tclaim_zero(mlx5_flow_os_destroy_flow_matcher\n-\t\t\t   (mtd->ingress.color_matcher));\n-\tif (mtd->ingress.any_matcher)\n-\t\tclaim_zero(mlx5_flow_os_destroy_flow_matcher\n-\t\t\t   (mtd->ingress.any_matcher));\n \tif (mtd->ingress.tbl)\n \t\tflow_dv_tbl_resource_release(MLX5_SH(dev), mtd->ingress.tbl);\n \tif (mtd->ingress.sfx_tbl)\n \t\tflow_dv_tbl_resource_release(MLX5_SH(dev),\n \t\t\t\t\t     mtd->ingress.sfx_tbl);\n-\tif (mtd->transfer.color_matcher)\n-\t\tclaim_zero(mlx5_flow_os_destroy_flow_matcher\n-\t\t\t   (mtd->transfer.color_matcher));\n-\tif (mtd->transfer.any_matcher)\n-\t\tclaim_zero(mlx5_flow_os_destroy_flow_matcher\n-\t\t\t   (mtd->transfer.any_matcher));\n \tif (mtd->transfer.tbl)\n \t\tflow_dv_tbl_resource_release(MLX5_SH(dev), mtd->transfer.tbl);\n \tif (mtd->transfer.sfx_tbl)\n \t\tflow_dv_tbl_resource_release(MLX5_SH(dev),\n \t\t\t\t\t     mtd->transfer.sfx_tbl);\n-\tif (mtd->drop_actn)\n-\t\tclaim_zero(mlx5_flow_os_destroy_flow_action(mtd->drop_actn));\n \tmlx5_free(mtd);\n \treturn 0;\n }\n@@ -13468,37 +13420,17 @@ flow_dv_destroy_mtr_tbl(struct rte_eth_dev *dev,\n  *   Table attribute.\n  * @param[in] transfer\n  *   Table attribute.\n- * @param[in] color_reg_c_idx\n- *   Reg C index for color match.\n  *\n  * @return\n- *   0 on success, -1 otherwise and rte_errno is set.\n+ *   0 on success, -1 otherwise.\n  */\n static int\n flow_dv_prepare_mtr_tables(struct rte_eth_dev *dev,\n \t\t\t   struct mlx5_meter_domains_infos *mtb,\n-\t\t\t   uint8_t egress, uint8_t transfer,\n-\t\t\t   uint32_t color_reg_c_idx)\n+\t\t\t   uint8_t egress, uint8_t transfer)\n {\n-\tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_dev_ctx_shared *sh = priv->sh;\n-\tstruct mlx5_flow_dv_match_params mask = {\n-\t\t.size = sizeof(mask.buf),\n-\t};\n-\tstruct mlx5_flow_dv_match_params value = {\n-\t\t.size = sizeof(value.buf),\n-\t};\n-\tstruct mlx5dv_flow_matcher_attr dv_attr = {\n-\t\t.type = IBV_FLOW_ATTR_NORMAL,\n-\t\t.priority = 0,\n-\t\t.match_criteria_enable = 0,\n-\t\t.match_mask = (void *)&mask,\n-\t};\n-\tvoid *actions[METER_ACTIONS];\n-\tstruct mlx5_meter_domain_info *dtb;\n \tstruct rte_flow_error error;\n-\tint i = 0;\n-\tint ret;\n+\tstruct mlx5_meter_domain_info *dtb;\n \n \tif (transfer)\n \t\tdtb = &mtb->transfer;\n@@ -13523,41 +13455,7 @@ flow_dv_prepare_mtr_tables(struct rte_eth_dev *dev,\n \t\tDRV_LOG(ERR, \"Failed to create meter suffix table.\");\n \t\treturn -1;\n \t}\n-\t/* Create matchers, Any and Color. */\n-\tdv_attr.priority = 3;\n-\tdv_attr.match_criteria_enable = 0;\n-\tret = mlx5_flow_os_create_flow_matcher(sh->ctx, &dv_attr, dtb->tbl->obj,\n-\t\t\t\t\t       &dtb->any_matcher);\n-\tif (ret) {\n-\t\tDRV_LOG(ERR, \"Failed to create meter\"\n-\t\t\t     \" policer default matcher.\");\n-\t\tgoto error_exit;\n-\t}\n-\tdv_attr.priority = 0;\n-\tdv_attr.match_criteria_enable =\n-\t\t\t\t1 << MLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT;\n-\tflow_dv_match_meta_reg(mask.buf, value.buf, color_reg_c_idx,\n-\t\t\t       rte_col_2_mlx5_col(RTE_COLORS), UINT8_MAX);\n-\tret = mlx5_flow_os_create_flow_matcher(sh->ctx, &dv_attr, dtb->tbl->obj,\n-\t\t\t\t\t       &dtb->color_matcher);\n-\tif (ret) {\n-\t\tDRV_LOG(ERR, \"Failed to create meter policer color matcher.\");\n-\t\tgoto error_exit;\n-\t}\n-\tif (mtb->count_actns[RTE_MTR_DROPPED])\n-\t\tactions[i++] = mtb->count_actns[RTE_MTR_DROPPED];\n-\tactions[i++] = mtb->drop_actn;\n-\t/* Default rule: lowest priority, match any, actions: drop. */\n-\tret = mlx5_flow_os_create_flow(dtb->any_matcher, (void *)&value, i,\n-\t\t\t\t       actions,\n-\t\t\t\t       &dtb->policer_rules[RTE_MTR_DROPPED]);\n-\tif (ret) {\n-\t\tDRV_LOG(ERR, \"Failed to create meter policer drop rule.\");\n-\t\tgoto error_exit;\n-\t}\n \treturn 0;\n-error_exit:\n-\treturn -1;\n }\n \n /**\n@@ -13566,20 +13464,16 @@ flow_dv_prepare_mtr_tables(struct rte_eth_dev *dev,\n  *\n  * @param[in] dev\n  *   Pointer to Ethernet device.\n- * @param[in] fm\n- *   Pointer to the flow meter.\n  *\n  * @return\n  *   Pointer to table set on success, NULL otherwise and rte_errno is set.\n  */\n static struct mlx5_meter_domains_infos *\n-flow_dv_create_mtr_tbl(struct rte_eth_dev *dev,\n-\t\t       const struct mlx5_flow_meter *fm)\n+flow_dv_create_mtr_tbl(struct rte_eth_dev *dev)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_meter_domains_infos *mtb;\n \tint ret;\n-\tint i;\n \n \tif (!priv->mtr_en) {\n \t\trte_errno = ENOTSUP;\n@@ -13590,37 +13484,21 @@ flow_dv_create_mtr_tbl(struct rte_eth_dev *dev,\n \t\tDRV_LOG(ERR, \"Failed to allocate memory for meter.\");\n \t\treturn NULL;\n \t}\n-\t/* Create meter count actions */\n-\tfor (i = 0; i <= RTE_MTR_DROPPED; i++) {\n-\t\tstruct mlx5_flow_counter *cnt;\n-\t\tif (!fm->policer_stats.cnt[i])\n-\t\t\tcontinue;\n-\t\tcnt = flow_dv_counter_get_by_idx(dev,\n-\t\t      fm->policer_stats.cnt[i], NULL);\n-\t\tmtb->count_actns[i] = cnt->action;\n-\t}\n-\t/* Create drop action. */\n-\tret = mlx5_flow_os_create_flow_action_drop(&mtb->drop_actn);\n-\tif (ret) {\n-\t\tDRV_LOG(ERR, \"Failed to create drop action.\");\n-\t\tgoto error_exit;\n-\t}\n \t/* Egress meter table. */\n-\tret = flow_dv_prepare_mtr_tables(dev, mtb, 1, 0, priv->mtr_color_reg);\n+\tret = flow_dv_prepare_mtr_tables(dev, mtb, 1, 0);\n \tif (ret) {\n \t\tDRV_LOG(ERR, \"Failed to prepare egress meter table.\");\n \t\tgoto error_exit;\n \t}\n \t/* Ingress meter table. */\n-\tret = flow_dv_prepare_mtr_tables(dev, mtb, 0, 0, priv->mtr_color_reg);\n+\tret = flow_dv_prepare_mtr_tables(dev, mtb, 0, 0);\n \tif (ret) {\n \t\tDRV_LOG(ERR, \"Failed to prepare ingress meter table.\");\n \t\tgoto error_exit;\n \t}\n \t/* FDB meter table. */\n \tif (priv->config.dv_esw_en) {\n-\t\tret = flow_dv_prepare_mtr_tables(dev, mtb, 0, 1,\n-\t\t\t\t\t\t priv->mtr_color_reg);\n+\t\tret = flow_dv_prepare_mtr_tables(dev, mtb, 0, 1);\n \t\tif (ret) {\n \t\t\tDRV_LOG(ERR, \"Failed to prepare fdb meter table.\");\n \t\t\tgoto error_exit;\n@@ -13632,24 +13510,152 @@ flow_dv_create_mtr_tbl(struct rte_eth_dev *dev,\n \treturn NULL;\n }\n \n+/**\n+ * Destroy the meter table matchers.\n+ * Lock free, (mutex should be acquired by caller).\n+ *\n+ * @param[in] dev\n+ *   Pointer to Ethernet device.\n+ * @param[in,out] dtb\n+ *   Pointer to DV meter table.\n+ *\n+ * @return\n+ *   Always 0.\n+ */\n+static int\n+flow_dv_destroy_mtr_matchers(struct rte_eth_dev *dev,\n+\t\t\t     struct mlx5_meter_domain_info *dtb)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_flow_tbl_data_entry *tbl;\n+\n+\tif (!priv->config.dv_flow_en)\n+\t\treturn 0;\n+\tif (dtb->drop_matcher) {\n+\t\ttbl = container_of(dtb->drop_matcher->tbl, typeof(*tbl), tbl);\n+\t\tmlx5_cache_unregister(&tbl->matchers,\n+\t\t\t\t      &dtb->drop_matcher->entry);\n+\t\tdtb->drop_matcher = NULL;\n+\t}\n+\tif (dtb->color_matcher) {\n+\t\ttbl = container_of(dtb->color_matcher->tbl, typeof(*tbl), tbl);\n+\t\tmlx5_cache_unregister(&tbl->matchers,\n+\t\t\t\t      &dtb->color_matcher->entry);\n+\t\tdtb->color_matcher = NULL;\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n+ * Create the matchers for meter table.\n+ *\n+ * @param[in] dev\n+ *   Pointer to Ethernet device.\n+ * @param[in] color_reg_c_idx\n+ *   Reg C index for color match.\n+ * @param[in] mtr_id_reg_c_idx\n+ *   Reg C index for meter_id match.\n+ * @param[in] mtr_id_mask\n+ *   Mask for meter_id match criteria.\n+ * @param[in,out] dtb\n+ *   Pointer to DV meter table.\n+ * @param[out] error\n+ *   Perform verbose error reporting if not NULL.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+flow_dv_prepare_mtr_matchers(struct rte_eth_dev *dev,\n+\t\t\t     uint32_t color_reg_c_idx,\n+\t\t\t     uint32_t mtr_id_reg_c_idx,\n+\t\t\t     uint32_t mtr_id_mask,\n+\t\t\t     struct mlx5_meter_domain_info *dtb,\n+\t\t\t     struct rte_flow_error *error)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_flow_tbl_data_entry *tbl_data;\n+\tstruct mlx5_cache_entry *entry;\n+\tstruct mlx5_flow_dv_matcher matcher = {\n+\t\t.mask = {\n+\t\t\t.size = sizeof(matcher.mask.buf) -\n+\t\t\t\tMLX5_ST_SZ_BYTES(fte_match_set_misc4),\n+\t\t},\n+\t\t.tbl = dtb->tbl,\n+\t};\n+\tstruct mlx5_flow_dv_match_params value = {\n+\t\t.size = sizeof(value.buf) -\n+\t\t\tMLX5_ST_SZ_BYTES(fte_match_set_misc4),\n+\t};\n+\tstruct mlx5_flow_cb_ctx ctx = {\n+\t\t.error = error,\n+\t\t.data = &matcher,\n+\t};\n+\tuint32_t color_mask = (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;\n+\n+\ttbl_data = container_of(dtb->tbl, struct mlx5_flow_tbl_data_entry, tbl);\n+\tif (!dtb->drop_matcher) {\n+\t\t/* Create matchers for Drop. */\n+\t\tflow_dv_match_meta_reg(matcher.mask.buf, value.buf,\n+\t\t\t\t       mtr_id_reg_c_idx, 0, mtr_id_mask);\n+\t\tmatcher.priority = MLX5_REG_BITS * 2 - priv->max_mtr_bits;\n+\t\tmatcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,\n+\t\t\t\t\tmatcher.mask.size);\n+\t\tentry = mlx5_cache_register(&tbl_data->matchers, &ctx);\n+\t\tif (!entry) {\n+\t\t\tDRV_LOG(ERR, \"Failed to register meter drop matcher.\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\tdtb->drop_matcher =\n+\t\t\tcontainer_of(entry, struct mlx5_flow_dv_matcher, entry);\n+\t}\n+\tif (!dtb->color_matcher) {\n+\t\t/* Create matchers for Color + meter_id. */\n+\t\tif (priv->mtr_reg_share) {\n+\t\t\tflow_dv_match_meta_reg(matcher.mask.buf, value.buf,\n+\t\t\t\t\tcolor_reg_c_idx, 0,\n+\t\t\t\t\t(mtr_id_mask | color_mask));\n+\t\t} else {\n+\t\t\tflow_dv_match_meta_reg(matcher.mask.buf, value.buf,\n+\t\t\t\t\tcolor_reg_c_idx, 0, color_mask);\n+\t\t\tflow_dv_match_meta_reg(matcher.mask.buf, value.buf,\n+\t\t\t\t\tmtr_id_reg_c_idx, 0, mtr_id_mask);\n+\t\t}\n+\t\tmatcher.priority = MLX5_REG_BITS - priv->max_mtr_bits;\n+\t\tmatcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,\n+\t\t\t\t\tmatcher.mask.size);\n+\t\tentry = mlx5_cache_register(&tbl_data->matchers, &ctx);\n+\t\tif (!entry) {\n+\t\t\tDRV_LOG(ERR, \"Failed to register meter color matcher.\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\tdtb->color_matcher =\n+\t\t\tcontainer_of(entry, struct mlx5_flow_dv_matcher, entry);\n+\t}\n+\treturn 0;\n+}\n+\n /**\n  * Destroy domain policer rule.\n  *\n+ * @param[in] dev\n+ *   Pointer to Ethernet device.\n  * @param[in] dt\n  *   Pointer to domain table.\n  */\n static void\n-flow_dv_destroy_domain_policer_rule(struct mlx5_meter_domain_info *dt)\n+flow_dv_destroy_domain_policer_rule(struct rte_eth_dev *dev,\n+\t\t\t\t    struct mlx5_meter_domain_info *dt)\n {\n-\tint i;\n-\n-\tfor (i = 0; i < RTE_MTR_DROPPED; i++) {\n-\t\tif (dt->policer_rules[i]) {\n-\t\t\tclaim_zero(mlx5_flow_os_destroy_flow\n-\t\t\t\t   (dt->policer_rules[i]));\n-\t\t\tdt->policer_rules[i] = NULL;\n-\t\t}\n+\tif (dt->drop_rule) {\n+\t\tclaim_zero(mlx5_flow_os_destroy_flow(dt->drop_rule));\n+\t\tdt->drop_rule = NULL;\n \t}\n+\tif (dt->green_rule) {\n+\t\tclaim_zero(mlx5_flow_os_destroy_flow(dt->green_rule));\n+\t\tdt->green_rule = NULL;\n+\t}\n+\tflow_dv_destroy_mtr_matchers(dev, dt);\n \tif (dt->jump_actn) {\n \t\tclaim_zero(mlx5_flow_os_destroy_flow_action(dt->jump_actn));\n \t\tdt->jump_actn = NULL;\n@@ -13670,7 +13676,7 @@ flow_dv_destroy_domain_policer_rule(struct mlx5_meter_domain_info *dt)\n  *   Always 0.\n  */\n static int\n-flow_dv_destroy_policer_rules(struct rte_eth_dev *dev __rte_unused,\n+flow_dv_destroy_policer_rules(struct rte_eth_dev *dev,\n \t\t\t      const struct mlx5_flow_meter *fm,\n \t\t\t      const struct rte_flow_attr *attr)\n {\n@@ -13679,39 +13685,56 @@ flow_dv_destroy_policer_rules(struct rte_eth_dev *dev __rte_unused,\n \tif (!mtb)\n \t\treturn 0;\n \tif (attr->egress)\n-\t\tflow_dv_destroy_domain_policer_rule(&mtb->egress);\n+\t\tflow_dv_destroy_domain_policer_rule(dev, &mtb->egress);\n \tif (attr->ingress)\n-\t\tflow_dv_destroy_domain_policer_rule(&mtb->ingress);\n+\t\tflow_dv_destroy_domain_policer_rule(dev, &mtb->ingress);\n \tif (attr->transfer)\n-\t\tflow_dv_destroy_domain_policer_rule(&mtb->transfer);\n+\t\tflow_dv_destroy_domain_policer_rule(dev, &mtb->transfer);\n \treturn 0;\n }\n \n /**\n  * Create specify domain meter policer rule.\n  *\n+ * @param[in] dev\n+ *   Pointer to Ethernet device.\n  * @param[in] fm\n  *   Pointer to flow meter structure.\n  * @param[in] mtb\n  *   Pointer to DV meter table set.\n- * @param[in] mtr_reg_c\n- *   Color match REG_C.\n+ * @param[out] drop_rule\n+ *   The address of pointer saving drop rule.\n+ * @param[out] color_rule\n+ *   The address of pointer saving green rule.\n  *\n  * @return\n  *   0 on success, -1 otherwise.\n  */\n static int\n-flow_dv_create_policer_forward_rule(struct mlx5_flow_meter *fm,\n+flow_dv_create_policer_forward_rule(struct rte_eth_dev *dev,\n+\t\t\t\t    struct mlx5_flow_meter *fm,\n \t\t\t\t    struct mlx5_meter_domain_info *dtb,\n-\t\t\t\t    uint8_t mtr_reg_c)\n+\t\t\t\t    void **drop_rule,\n+\t\t\t\t    void **green_rule)\n {\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_flow_dv_match_params matcher = {\n-\t\t.size = sizeof(matcher.buf),\n+\t\t.size = sizeof(matcher.buf) -\n+\t\t\tMLX5_ST_SZ_BYTES(fte_match_set_misc4),\n \t};\n \tstruct mlx5_flow_dv_match_params value = {\n-\t\t.size = sizeof(value.buf),\n+\t\t.size = sizeof(value.buf) -\n+\t\t\tMLX5_ST_SZ_BYTES(fte_match_set_misc4),\n \t};\n \tstruct mlx5_meter_domains_infos *mtb = fm->mfts;\n+\tstruct rte_flow_error error;\n+\tuint32_t color_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR,\n+\t\t\t\t\t\t    0, &error);\n+\tuint32_t mtr_id_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_ID,\n+\t\t\t\t\t\t     0, &error);\n+\tuint8_t mtr_id_offset = priv->mtr_reg_share ? MLX5_MTR_COLOR_BITS : 0;\n+\tuint32_t mtr_id_mask =\n+\t\t((UINT32_C(1) << priv->max_mtr_bits) - 1) << mtr_id_offset;\n \tvoid *actions[METER_ACTIONS];\n \tint i;\n \tint ret = 0;\n@@ -13724,25 +13747,52 @@ flow_dv_create_policer_forward_rule(struct mlx5_flow_meter *fm,\n \t\tDRV_LOG(ERR, \"Failed to create policer jump action.\");\n \t\tgoto error;\n \t}\n-\tfor (i = 0; i < RTE_MTR_DROPPED; i++) {\n-\t\tint j = 0;\n-\n-\t\tflow_dv_match_meta_reg(matcher.buf, value.buf, mtr_reg_c,\n-\t\t\t\t       rte_col_2_mlx5_col(i), UINT8_MAX);\n-\t\tif (mtb->count_actns[i])\n-\t\t\tactions[j++] = mtb->count_actns[i];\n-\t\tif (fm->action[i] == MTR_POLICER_ACTION_DROP)\n-\t\t\tactions[j++] = mtb->drop_actn;\n-\t\telse\n-\t\t\tactions[j++] = dtb->jump_actn;\n-\t\tret = mlx5_flow_os_create_flow(dtb->color_matcher,\n-\t\t\t\t\t       (void *)&value, j, actions,\n-\t\t\t\t\t       &dtb->policer_rules[i]);\n+\t/* Prepare matchers. */\n+\tif (!dtb->drop_matcher || !dtb->color_matcher) {\n+\t\tret = flow_dv_prepare_mtr_matchers(dev, color_reg_c,\n+\t\t\t\t\t\t   mtr_id_reg_c, mtr_id_mask,\n+\t\t\t\t\t\t   dtb, &error);\n \t\tif (ret) {\n-\t\t\tDRV_LOG(ERR, \"Failed to create policer rule.\");\n+\t\t\tDRV_LOG(ERR, \"Failed to setup matchers for mtr table.\");\n \t\t\tgoto error;\n \t\t}\n \t}\n+\t/* Create Drop flow, matching meter_id only. */\n+\ti = 0;\n+\tflow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c,\n+\t\t\t       (fm->idx << mtr_id_offset), UINT32_MAX);\n+\tif (mtb->drop_count)\n+\t\tactions[i++] = mtb->drop_count;\n+\tactions[i++] = priv->sh->dr_drop_action;\n+\tret = mlx5_flow_os_create_flow(dtb->drop_matcher->matcher_object,\n+\t\t\t\t       (void *)&value, i, actions, drop_rule);\n+\tif (ret) {\n+\t\tDRV_LOG(ERR, \"Failed to create meter policer drop rule.\");\n+\t\tgoto error;\n+\t}\n+\t/* Create flow matching Green color + meter_id. */\n+\ti = 0;\n+\tif (priv->mtr_reg_share) {\n+\t\tflow_dv_match_meta_reg(matcher.buf, value.buf, color_reg_c,\n+\t\t\t\t       ((fm->idx << mtr_id_offset) |\n+\t\t\t\t\trte_col_2_mlx5_col(RTE_COLOR_GREEN)),\n+\t\t\t\t       UINT32_MAX);\n+\t} else {\n+\t\tflow_dv_match_meta_reg(matcher.buf, value.buf, color_reg_c,\n+\t\t\t\t       rte_col_2_mlx5_col(RTE_COLOR_GREEN),\n+\t\t\t\t       UINT32_MAX);\n+\t\tflow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c,\n+\t\t\t\t       fm->idx, UINT32_MAX);\n+\t}\n+\tif (mtb->green_count)\n+\t\tactions[i++] = mtb->green_count;\n+\tactions[i++] = dtb->jump_actn;\n+\tret = mlx5_flow_os_create_flow(dtb->color_matcher->matcher_object,\n+\t\t\t\t       (void *)&value, i, actions, green_rule);\n+\tif (ret) {\n+\t\tDRV_LOG(ERR, \"Failed to create meter policer color rule.\");\n+\t\tgoto error;\n+\t}\n \treturn 0;\n error:\n \trte_errno = errno;\n@@ -13750,7 +13800,8 @@ flow_dv_create_policer_forward_rule(struct mlx5_flow_meter *fm,\n }\n \n /**\n- * Create policer rules.\n+ * Prepare policer rules for all domains.\n+ * If meter already initialized, this will replace all old rules with new ones.\n  *\n  * @param[in] dev\n  *   Pointer to Ethernet device.\n@@ -13763,41 +13814,107 @@ flow_dv_create_policer_forward_rule(struct mlx5_flow_meter *fm,\n  *   0 on success, -1 otherwise.\n  */\n static int\n-flow_dv_create_policer_rules(struct rte_eth_dev *dev,\n-\t\t\t     struct mlx5_flow_meter *fm,\n-\t\t\t     const struct rte_flow_attr *attr)\n+flow_dv_prepare_policer_rules(struct rte_eth_dev *dev,\n+\t\t\t      struct mlx5_flow_meter *fm,\n+\t\t\t      const struct rte_flow_attr *attr)\n {\n-\tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_meter_domains_infos *mtb = fm->mfts;\n+\tbool initialized = false;\n+\tstruct mlx5_flow_counter *cnt;\n+\tvoid *egress_drop_rule = NULL;\n+\tvoid *egress_green_rule = NULL;\n+\tvoid *ingress_drop_rule = NULL;\n+\tvoid *ingress_green_rule = NULL;\n+\tvoid *transfer_drop_rule = NULL;\n+\tvoid *transfer_green_rule = NULL;\n \tint ret;\n \n+\t/* Get the statistics counters for green/drop. */\n+\tif (fm->policer_stats.cnt[RTE_COLOR_GREEN]) {\n+\t\tcnt = flow_dv_counter_get_by_idx(dev,\n+\t\t\t\t\tfm->policer_stats.cnt[RTE_COLOR_GREEN],\n+\t\t\t\t\tNULL);\n+\t\tmtb->green_count = cnt->action;\n+\t} else {\n+\t\tmtb->green_count = NULL;\n+\t}\n+\tif (fm->policer_stats.cnt[RTE_MTR_DROPPED]) {\n+\t\tcnt = flow_dv_counter_get_by_idx(dev,\n+\t\t\t\t\tfm->policer_stats.cnt[RTE_MTR_DROPPED],\n+\t\t\t\t\tNULL);\n+\t\tmtb->drop_count = cnt->action;\n+\t} else {\n+\t\tmtb->drop_count = NULL;\n+\t}\n+\t/**\n+\t * If flow meter has been initialized, all policer rules\n+\t * are created. So can get if meter initialized by checking\n+\t * any policer rule.\n+\t */\n+\tif (mtb->egress.drop_rule)\n+\t\tinitialized = true;\n \tif (attr->egress) {\n-\t\tret = flow_dv_create_policer_forward_rule(fm, &mtb->egress,\n-\t\t\t\t\t\tpriv->mtr_color_reg);\n+\t\tret = flow_dv_create_policer_forward_rule(dev,\n+\t\t\t\tfm, &mtb->egress,\n+\t\t\t\t&egress_drop_rule, &egress_green_rule);\n \t\tif (ret) {\n \t\t\tDRV_LOG(ERR, \"Failed to create egress policer.\");\n \t\t\tgoto error;\n \t\t}\n \t}\n \tif (attr->ingress) {\n-\t\tret = flow_dv_create_policer_forward_rule(fm, &mtb->ingress,\n-\t\t\t\t\t\tpriv->mtr_color_reg);\n+\t\tret = flow_dv_create_policer_forward_rule(dev,\n+\t\t\t\tfm, &mtb->ingress,\n+\t\t\t\t&ingress_drop_rule, &ingress_green_rule);\n \t\tif (ret) {\n \t\t\tDRV_LOG(ERR, \"Failed to create ingress policer.\");\n \t\t\tgoto error;\n \t\t}\n \t}\n \tif (attr->transfer) {\n-\t\tret = flow_dv_create_policer_forward_rule(fm, &mtb->transfer,\n-\t\t\t\t\t\tpriv->mtr_color_reg);\n+\t\tret = flow_dv_create_policer_forward_rule(dev,\n+\t\t\t\tfm, &mtb->transfer,\n+\t\t\t\t&transfer_drop_rule, &transfer_green_rule);\n \t\tif (ret) {\n \t\t\tDRV_LOG(ERR, \"Failed to create transfer policer.\");\n \t\t\tgoto error;\n \t\t}\n \t}\n+\t/* Replace old flows if existing. */\n+\tif (mtb->egress.drop_rule)\n+\t\tclaim_zero(mlx5_flow_os_destroy_flow(mtb->egress.drop_rule));\n+\tif (mtb->egress.green_rule)\n+\t\tclaim_zero(mlx5_flow_os_destroy_flow(mtb->egress.green_rule));\n+\tif (mtb->ingress.drop_rule)\n+\t\tclaim_zero(mlx5_flow_os_destroy_flow(mtb->ingress.drop_rule));\n+\tif (mtb->ingress.green_rule)\n+\t\tclaim_zero(mlx5_flow_os_destroy_flow(mtb->ingress.green_rule));\n+\tif (mtb->transfer.drop_rule)\n+\t\tclaim_zero(mlx5_flow_os_destroy_flow(mtb->transfer.drop_rule));\n+\tif (mtb->transfer.green_rule)\n+\t\tclaim_zero(mlx5_flow_os_destroy_flow(mtb->transfer.green_rule));\n+\tmtb->egress.drop_rule = egress_drop_rule;\n+\tmtb->egress.green_rule = egress_green_rule;\n+\tmtb->ingress.drop_rule = ingress_drop_rule;\n+\tmtb->ingress.green_rule = ingress_green_rule;\n+\tmtb->transfer.drop_rule = transfer_drop_rule;\n+\tmtb->transfer.green_rule = transfer_green_rule;\n \treturn 0;\n error:\n-\tflow_dv_destroy_policer_rules(dev, fm, attr);\n+\tif (egress_drop_rule)\n+\t\tclaim_zero(mlx5_flow_os_destroy_flow(egress_drop_rule));\n+\tif (egress_green_rule)\n+\t\tclaim_zero(mlx5_flow_os_destroy_flow(egress_green_rule));\n+\tif (ingress_drop_rule)\n+\t\tclaim_zero(mlx5_flow_os_destroy_flow(ingress_drop_rule));\n+\tif (ingress_green_rule)\n+\t\tclaim_zero(mlx5_flow_os_destroy_flow(ingress_green_rule));\n+\tif (transfer_drop_rule)\n+\t\tclaim_zero(mlx5_flow_os_destroy_flow(transfer_drop_rule));\n+\tif (transfer_green_rule)\n+\t\tclaim_zero(mlx5_flow_os_destroy_flow(transfer_green_rule));\n+\tif (!initialized)\n+\t\tflow_dv_destroy_policer_rules(dev, fm, attr);\n \treturn -1;\n }\n \n@@ -14094,7 +14211,7 @@ const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {\n \t.query = flow_dv_query,\n \t.create_mtr_tbls = flow_dv_create_mtr_tbl,\n \t.destroy_mtr_tbls = flow_dv_destroy_mtr_tbl,\n-\t.create_policer_rules = flow_dv_create_policer_rules,\n+\t.prepare_policer_rules = flow_dv_prepare_policer_rules,\n \t.destroy_policer_rules = flow_dv_destroy_policer_rules,\n \t.counter_alloc = flow_dv_counter_allocate,\n \t.counter_free = flow_dv_counter_free,\ndiff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c\nindex dbc574b508..7f7693b698 100644\n--- a/drivers/net/mlx5/mlx5_flow_meter.c\n+++ b/drivers/net/mlx5/mlx5_flow_meter.c\n@@ -474,6 +474,12 @@ mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,\n \t\t\t\t\t       MTR_POLICER_ACTION_COLOR_RED };\n \tint i;\n \n+\t/* Meter must use global drop action. */\n+\tif (!priv->sh->dr_drop_action)\n+\t\treturn -rte_mtr_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_MTR_ERROR_TYPE_MTR_PARAMS,\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"No drop action ready for meter.\");\n \t/* Meter params must not be NULL. */\n \tif (params == NULL)\n \t\treturn -rte_mtr_error_set(error, EINVAL,\n@@ -630,9 +636,18 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,\n \t\t\t\t.egress = 1,\n \t\t\t\t.transfer = priv->config.dv_esw_en ? 1 : 0,\n \t\t\t};\n+\tstruct mlx5_indexed_pool_config flow_ipool_cfg = {\n+\t\t.size = 0,\n+\t\t.trunk_size = 64,\n+\t\t.need_lock = 1,\n+\t\t.type = \"mlx5_flow_mtr_flow_id_pool\",\n+\t};\n \tint ret;\n \tunsigned int i;\n \tuint32_t idx = 0;\n+\tuint8_t mtr_id_bits;\n+\tuint8_t mtr_reg_bits = priv->mtr_reg_share ?\n+\t\t\t\tMLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS;\n \n \tif (!priv->mtr_en)\n \t\treturn -rte_mtr_error_set(error, ENOTSUP,\n@@ -654,6 +669,13 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,\n \t\treturn -rte_mtr_error_set(error, ENOMEM,\n \t\t\t\t\t  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,\n \t\t\t\t\t  \"Memory alloc failed for meter.\");\n+\tmtr_id_bits = MLX5_REG_BITS - __builtin_clz(idx);\n+\tif ((mtr_id_bits + priv->max_mtr_flow_bits) > mtr_reg_bits) {\n+\t\tDRV_LOG(ERR, \"Meter number exceeds max limit.\");\n+\t\tgoto error;\n+\t}\n+\tif (mtr_id_bits > priv->max_mtr_bits)\n+\t\tpriv->max_mtr_bits = mtr_id_bits;\n \tfm->idx = idx;\n \t/* Fill the flow meter parameters. */\n \tfm->meter_id = meter_id;\n@@ -667,10 +689,10 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,\n \t\tif (!fm->policer_stats.cnt[i])\n \t\t\tgoto error;\n \t}\n-\tfm->mfts = mlx5_flow_create_mtr_tbls(dev, fm);\n+\tfm->mfts = mlx5_flow_create_mtr_tbls(dev);\n \tif (!fm->mfts)\n \t\tgoto error;\n-\tret = mlx5_flow_create_policer_rules(dev, fm, &attr);\n+\tret = mlx5_flow_prepare_policer_rules(dev, fm, &attr);\n \tif (ret)\n \t\tgoto error;\n \t/* Add to the flow meter list. */\n@@ -679,6 +701,9 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,\n \tfm->shared = !!shared;\n \tfm->policer_stats.stats_mask = params->stats_mask;\n \tfm->profile->ref_cnt++;\n+\tfm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg);\n+\tif (!fm->flow_ipool)\n+\t\tgoto error;\n \trte_spinlock_init(&fm->sl);\n \treturn 0;\n error:\n@@ -749,6 +774,8 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,\n \t\tif (fm->policer_stats.cnt[i])\n \t\t\tmlx5_counter_free(dev, fm->policer_stats.cnt[i]);\n \t/* Free meter flow table */\n+\tif (fm->flow_ipool)\n+\t\tmlx5_ipool_destroy(fm->flow_ipool);\n \tmlx5_flow_destroy_policer_rules(dev, fm, &attr);\n \tmlx5_flow_destroy_mtr_tbls(dev, fm->mfts);\n \tmlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], fm->idx);\n@@ -1153,30 +1180,24 @@ mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id)\n  *\n  * @param [in] priv\n  *  Pointer to mlx5 private data.\n- * @param [in] meter_id\n- *  Flow meter id.\n+ * @param[in] fm\n+ *   Pointer to flow meter.\n  * @param [in] attr\n  *  Pointer to flow attributes.\n  * @param [out] error\n  *  Pointer to error structure.\n  *\n- * @return the flow meter pointer, NULL otherwise.\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n  */\n-struct mlx5_flow_meter *\n-mlx5_flow_meter_attach(struct mlx5_priv *priv, uint32_t meter_id,\n+int\n+mlx5_flow_meter_attach(struct mlx5_priv *priv,\n+\t\t       struct mlx5_flow_meter *fm,\n \t\t       const struct rte_flow_attr *attr,\n \t\t       struct rte_flow_error *error)\n {\n-\tstruct mlx5_flow_meter *fm;\n \tint ret = 0;\n \n-\tfm = mlx5_flow_meter_find(priv, meter_id);\n-\tif (fm == NULL) {\n-\t\trte_flow_error_set(error, ENOENT,\n-\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t   \"Meter object id not valid\");\n-\t\treturn fm;\n-\t}\n \trte_spinlock_lock(&fm->sl);\n \tif (fm->mfts->meter_action) {\n \t\tif (fm->shared &&\n@@ -1210,7 +1231,7 @@ mlx5_flow_meter_attach(struct mlx5_priv *priv, uint32_t meter_id,\n \t\t\t\t   fm->mfts->meter_action ?\n \t\t\t\t   \"Meter attr not match\" :\n \t\t\t\t   \"Meter action create failed\");\n-\treturn ret ? NULL : fm;\n+\treturn ret ? -rte_errno : 0;\n }\n \n /**\n",
    "prefixes": [
        "v5",
        "03/14"
    ]
}