get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 91868,
    "url": "http://patches.dpdk.org/api/patches/91868/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1618916122-181792-4-git-send-email-jiaweiw@nvidia.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<1618916122-181792-4-git-send-email-jiaweiw@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1618916122-181792-4-git-send-email-jiaweiw@nvidia.com",
    "date": "2021-04-20T10:55:10",
    "name": "[v6,03/15] net/mlx5: fix meter statistics",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "7073bce23a292d69169d959c05e0aa61ff59985b",
    "submitter": {
        "id": 1939,
        "url": "http://patches.dpdk.org/api/people/1939/?format=api",
        "name": "Jiawei Wang",
        "email": "jiaweiw@nvidia.com"
    },
    "delegate": {
        "id": 3268,
        "url": "http://patches.dpdk.org/api/users/3268/?format=api",
        "username": "rasland",
        "first_name": "Raslan",
        "last_name": "Darawsheh",
        "email": "rasland@nvidia.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1618916122-181792-4-git-send-email-jiaweiw@nvidia.com/mbox/",
    "series": [
        {
            "id": 16520,
            "url": "http://patches.dpdk.org/api/series/16520/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=16520",
            "date": "2021-04-20T10:55:12",
            "name": "Add ASO meter support in MLX5 PMD",
            "version": 6,
            "mbox": "http://patches.dpdk.org/series/16520/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/91868/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/91868/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 93810A0548;\n\tTue, 20 Apr 2021 12:56:15 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id F3A0F4176D;\n\tTue, 20 Apr 2021 12:55:37 +0200 (CEST)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by mails.dpdk.org (Postfix) with ESMTP id DBE0F416FE\n for <dev@dpdk.org>; Tue, 20 Apr 2021 12:55:25 +0200 (CEST)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n jiaweiw@nvidia.com) with SMTP; 20 Apr 2021 13:55:23 +0300",
            "from nvidia.com (gen-l-vrt-281.mtl.labs.mlnx [10.237.44.1])\n by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 13KAtMRp009943;\n Tue, 20 Apr 2021 13:55:23 +0300"
        ],
        "From": "Jiawei Wang <jiaweiw@nvidia.com>",
        "To": "matan@nvidia.com, orika@nvidia.com, viacheslavo@nvidia.com,\n ferruh.yigit@intel.com, thomas@monjalon.net,\n Shahaf Shuler <shahafs@nvidia.com>, Suanming Mou <suanmingm@mellanox.com>",
        "Cc": "dev@dpdk.org, rasland@nvidia.com, asafp@nvidia.com,\n Shun Hao <shunh@nvidia.com>, stable@dpdk.org",
        "Date": "Tue, 20 Apr 2021 13:55:10 +0300",
        "Message-Id": "<1618916122-181792-4-git-send-email-jiaweiw@nvidia.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1618916122-181792-1-git-send-email-jiaweiw@nvidia.com>",
        "References": "<20210331073632.1443011-1-lizh@nvidia.com>\n <1618916122-181792-1-git-send-email-jiaweiw@nvidia.com>",
        "Subject": "[dpdk-dev] [PATCH v6 03/15] 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 3bf224c..cc756ca 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -277,10 +277,13 @@ static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list =\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 c61f8ff..d208efb 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -953,9 +953,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@@ -1012,6 +1012,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@@ -1280,11 +1284,10 @@ int mlx5_mp_os_req_queue_control(struct rte_eth_dev *dev, uint16_t queue_id,\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 bc27b45..3bb04d5 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -748,9 +748,9 @@ struct mlx5_flow_tunnel_info {\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@@ -3035,7 +3035,8 @@ struct mlx5_flow_tunnel_info {\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@@ -3674,23 +3675,30 @@ struct mlx5_translated_action_handle {\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@@ -4347,8 +4355,10 @@ struct mlx5_hlist_entry *\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@@ -4363,29 +4373,39 @@ struct mlx5_hlist_entry *\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@@ -4394,10 +4414,7 @@ struct mlx5_hlist_entry *\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@@ -4430,23 +4447,22 @@ struct mlx5_hlist_entry *\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@@ -4475,16 +4491,34 @@ struct mlx5_hlist_entry *\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@@ -5192,25 +5226,49 @@ struct mlx5_hlist_entry *\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@@ -5224,9 +5282,9 @@ struct mlx5_hlist_entry *\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@@ -5237,10 +5295,12 @@ struct mlx5_hlist_entry *\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@@ -6512,20 +6572,17 @@ struct mlx5_flow_workspace*\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@@ -6550,7 +6607,7 @@ struct mlx5_meter_domains_infos *\n }\n \n /**\n- * Create policer rules.\n+ * Prepare policer rules.\n  *\n  * @param[in] dev\n  *   Pointer to Ethernet device.\n@@ -6563,14 +6620,14 @@ struct mlx5_meter_domains_infos *\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 a26f11a..a209b81 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -78,7 +78,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@@ -654,7 +654,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@@ -841,14 +842,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@@ -861,10 +864,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@@ -927,6 +930,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@@ -1165,6 +1170,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@@ -1205,8 +1211,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@@ -1269,7 +1274,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@@ -1469,11 +1474,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 0f215df..d4d88aa 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -10997,14 +10997,12 @@ struct mlx5_cache_entry *\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@@ -11429,33 +11427,13 @@ struct mlx5_cache_entry *\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@@ -12604,6 +12582,7 @@ struct mlx5_cache_entry *\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@@ -12614,8 +12593,6 @@ struct mlx5_cache_entry *\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@@ -12657,6 +12634,10 @@ struct mlx5_cache_entry *\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@@ -13425,49 +13406,20 @@ struct mlx5_cache_entry *\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@@ -13486,37 +13438,17 @@ struct mlx5_cache_entry *\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@@ -13541,41 +13473,7 @@ struct mlx5_cache_entry *\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@@ -13584,20 +13482,16 @@ struct mlx5_cache_entry *\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@@ -13608,37 +13502,21 @@ struct mlx5_cache_entry *\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@@ -13651,23 +13529,151 @@ struct mlx5_cache_entry *\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@@ -13688,7 +13694,7 @@ struct mlx5_cache_entry *\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@@ -13697,39 +13703,56 @@ struct mlx5_cache_entry *\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@@ -13742,25 +13765,52 @@ struct mlx5_cache_entry *\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@@ -13768,7 +13818,8 @@ struct mlx5_cache_entry *\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@@ -13781,41 +13832,107 @@ struct mlx5_cache_entry *\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@@ -14112,7 +14229,7 @@ struct mlx5_cache_entry *\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 dbc574b..7f7693b 100644\n--- a/drivers/net/mlx5/mlx5_flow_meter.c\n+++ b/drivers/net/mlx5/mlx5_flow_meter.c\n@@ -474,6 +474,12 @@\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 @@\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 @@\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 @@\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 @@\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 @@\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 @@ struct mlx5_flow_meter *\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 @@ struct mlx5_flow_meter *\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": [
        "v6",
        "03/15"
    ]
}