get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 91525,
    "url": "https://patches.dpdk.org/api/patches/91525/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20210415050505.2082663-3-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": "<20210415050505.2082663-3-lizh@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210415050505.2082663-3-lizh@nvidia.com",
    "date": "2021-04-15T05:05:03",
    "name": "[v5,2/4] net/mlx5: support meter creation with policy",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "cfb50fe7b46fd499d2c94786eefc3732844c5733",
    "submitter": {
        "id": 1967,
        "url": "https://patches.dpdk.org/api/people/1967/?format=api",
        "name": "Li Zhang",
        "email": "lizh@nvidia.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20210415050505.2082663-3-lizh@nvidia.com/mbox/",
    "series": [
        {
            "id": 16390,
            "url": "https://patches.dpdk.org/api/series/16390/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=16390",
            "date": "2021-04-15T05:05:01",
            "name": "net/mlx5: support meter policy operations",
            "version": 5,
            "mbox": "https://patches.dpdk.org/series/16390/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/91525/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/91525/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 61546A0A0C;\n\tThu, 15 Apr 2021 07:05:24 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 1569C161F8A;\n\tThu, 15 Apr 2021 07:05:23 +0200 (CEST)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by mails.dpdk.org (Postfix) with ESMTP id C79F7161F76\n for <dev@dpdk.org>; Thu, 15 Apr 2021 07:05:13 +0200 (CEST)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n lizh@nvidia.com)\n with SMTP; 15 Apr 2021 08:05:09 +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 13F559Be024397;\n Thu, 15 Apr 2021 08:05:09 +0300"
        ],
        "From": "Li Zhang <lizh@nvidia.com>",
        "To": "dekelp@nvidia.com, orika@nvidia.com, viacheslavo@nvidia.com,\n matan@nvidia.com, shahafs@nvidia.com",
        "Cc": "dev@dpdk.org, thomas@monjalon.net, rasland@nvidia.com, roniba@nvidia.com",
        "Date": "Thu, 15 Apr 2021 08:05:03 +0300",
        "Message-Id": "<20210415050505.2082663-3-lizh@nvidia.com>",
        "X-Mailer": "git-send-email 2.21.0",
        "In-Reply-To": "<20210415050505.2082663-1-lizh@nvidia.com>",
        "References": "<20210401081624.1482490-1-lizh@nvidia.com>\n <20210415050505.2082663-1-lizh@nvidia.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v5 2/4] net/mlx5: support meter creation with\n policy",
        "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": "Create a meter with the new pre-defined policy.\n\nThe following cases to be considered:\n1.Add entry match with meter_id in global drop table.\n2.For non-termination policy (policy id 0),\n  add jump rule to suffix table for green and\n  jump rule to drop table for red.\n3.Allocate counter per meter in drop table.\n4.Allocate meter resource per domain per color.\n5.It can work with both ASO and legacy meter HW objects.\n\nSigned-off-by: Li Zhang <lizh@nvidia.com>\nAcked-by: Matan Azrad <matan@nvidia.com>\n---\n drivers/net/mlx5/linux/mlx5_os.c   |  13 +-\n drivers/net/mlx5/mlx5.h            |  62 ++---\n drivers/net/mlx5/mlx5_flow.c       |  26 +-\n drivers/net/mlx5/mlx5_flow.h       |  32 +--\n drivers/net/mlx5/mlx5_flow_dv.c    | 367 ++++++++++++++++++++---------\n drivers/net/mlx5/mlx5_flow_meter.c | 367 ++++++++++++++++++++++++-----\n 6 files changed, 623 insertions(+), 244 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c\nindex 276283d492..c1d4e2a0dc 100644\n--- a/drivers/net/mlx5/linux/mlx5_os.c\n+++ b/drivers/net/mlx5/linux/mlx5_os.c\n@@ -1297,13 +1297,14 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\n \t\t\tif (log_obj_size >=\n \t\t\tconfig->hca_attr.qos.log_meter_aso_granularity &&\n \t\t\tlog_obj_size <=\n-\t\t\tconfig->hca_attr.qos.log_meter_aso_max_alloc) {\n+\t\t\tconfig->hca_attr.qos.log_meter_aso_max_alloc)\n \t\t\t\tsh->meter_aso_en = 1;\n-\t\t\t\terr = mlx5_aso_flow_mtrs_mng_init(priv->sh);\n-\t\t\t\tif (err) {\n-\t\t\t\t\terr = -err;\n-\t\t\t\t\tgoto error;\n-\t\t\t\t}\n+\t\t}\n+\t\tif (priv->mtr_en) {\n+\t\t\terr = mlx5_aso_flow_mtrs_mng_init(priv->sh);\n+\t\t\tif (err) {\n+\t\t\t\terr = -err;\n+\t\t\t\tgoto error;\n \t\t\t}\n \t\t}\n #endif\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex cb7c75aa2e..a8745df3e4 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -702,44 +702,12 @@ struct mlx5_flow_meter_def_policy {\n \t/* Jump action per color. */\n };\n \n-/* Meter table structure. */\n-struct mlx5_meter_domain_info {\n-\tstruct mlx5_flow_tbl_resource *tbl;\n-\t/**< Meter table. */\n-\tstruct mlx5_flow_tbl_resource *sfx_tbl;\n-\t/**< Meter suffix table. */\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 *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-struct mlx5_meter_domains_infos {\n-\tuint32_t ref_cnt;\n-\t/**< Table user count. */\n-\tstruct mlx5_meter_domain_info egress;\n-\t/**< TX meter table. */\n-\tstruct mlx5_meter_domain_info ingress;\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 *green_count;\n-\t/**< Counters for green rule. */\n-\tvoid *drop_count;\n-\t/**< Counters for green rule. */\n-};\n-\n /* Meter parameter structure. */\n struct mlx5_flow_meter_info {\n+\tuint32_t meter_id;\n+\t/**< Meter id. */\n+\tuint32_t policy_id;\n+\t/* Policy id, the first sub_policy idx. */\n \tstruct mlx5_flow_meter_profile *profile;\n \t/**< Meter profile parameters. */\n \trte_spinlock_t sl; /**< Meter action spinlock. */\n@@ -778,8 +746,10 @@ struct mlx5_flow_meter_info {\n \t * received by the application.\n \t */\n \tuint32_t transfer:1;\n-\tstruct mlx5_meter_domains_infos *mfts;\n-\t/**< Flow table created for this meter. */\n+\tuint32_t def_policy:1;\n+\t/* Meter points to default policy. */\n+\tvoid *drop_rule[MLX5_MTR_DOMAIN_MAX];\n+\t/* Meter drop rule in drop table. */\n \tuint32_t drop_cnt;\n \t/**< Color counter for drop. */\n \tuint32_t ref_cnt;\n@@ -790,6 +760,11 @@ struct mlx5_flow_meter_info {\n \t/**< Flow meter action. */\n };\n \n+/* PPS(packets per second) map to BPS(Bytes per second).\n+ * HW treat packet as 128bytes in PPS mode\n+ */\n+#define MLX5_MTRS_PPS_MAP_BPS_SHIFT 7\n+\n /* RFC2697 parameter structure. */\n struct mlx5_flow_meter_srtcm_rfc2697_prm {\n \trte_be32_t cbs_cir;\n@@ -878,12 +853,17 @@ struct mlx5_flow_mtr_mng {\n \t/* Policy index lookup table. */\n \tstruct mlx5_flow_tbl_resource *drop_tbl[MLX5_MTR_DOMAIN_MAX];\n \t/* Meter drop table. */\n-\tstruct mlx5_flow_dv_matcher *drop_matcher[MLX5_MTR_DOMAIN_MAX];\n+\tstruct mlx5_flow_dv_matcher *\n+\t\t\tdrop_matcher[MLX5_MTR_DOMAIN_MAX][MLX5_REG_BITS];\n \t/* Matcher meter in drop table. */\n \tstruct mlx5_flow_dv_matcher *def_matcher[MLX5_MTR_DOMAIN_MAX];\n \t/* Default matcher in drop table. */\n \tvoid *def_rule[MLX5_MTR_DOMAIN_MAX];\n \t/* Default rule in drop table. */\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 /* Table key of the hash organization. */\n@@ -1322,10 +1302,6 @@ 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)\ndiff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex 81e0e3b7a9..77590bbbed 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -4496,14 +4496,14 @@ flow_meter_split_prep(struct rte_eth_dev *dev,\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+\tif ((flow_id_bits + priv->sh->mtrmng->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-\tif (flow_id_bits > priv->max_mtr_flow_bits)\n-\t\tpriv->max_mtr_flow_bits = flow_id_bits;\n+\tif (flow_id_bits > priv->sh->mtrmng->max_mtr_flow_bits)\n+\t\tpriv->sh->mtrmng->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@@ -6778,15 +6778,18 @@ mlx5_flow_create_def_policy(struct rte_eth_dev *dev)\n  *   Pointer to Ethernet device.\n  *\n  * @return\n- *   Pointer to table set on success, NULL otherwise.\n+ *   0 on success, -1 otherwise.\n  */\n-struct mlx5_meter_domains_infos *\n-mlx5_flow_create_mtr_tbls(struct rte_eth_dev *dev)\n+int\n+mlx5_flow_create_mtr_tbls(struct rte_eth_dev *dev,\n+\t\t\tstruct mlx5_flow_meter_info *fm,\n+\t\t\tuint32_t mtr_idx,\n+\t\t\tuint8_t domain_bitmap)\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);\n+\treturn fops->create_mtr_tbls(dev, fm, mtr_idx, domain_bitmap);\n }\n \n /**\n@@ -6796,18 +6799,15 @@ mlx5_flow_create_mtr_tbls(struct rte_eth_dev *dev)\n  *   Pointer to Ethernet device.\n  * @param[in] tbl\n  *   Pointer to the meter table set.\n- *\n- * @return\n- *   0 on success.\n  */\n-int\n+void\n mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,\n-\t\t\t   struct mlx5_meter_domains_infos *tbls)\n+\t\t\t   struct mlx5_flow_meter_info *fm)\n {\n \tconst struct mlx5_flow_driver_ops *fops;\n \n \tfops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);\n-\treturn fops->destroy_mtr_tbls(dev, tbls);\n+\tfops->destroy_mtr_tbls(dev, fm);\n }\n \n /**\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex 51d040c4d2..89e43f2de6 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -222,16 +222,17 @@ enum mlx5_feature_name {\n #define MLX5_FLOW_ACTION_TUNNEL_SET (1ull << 37)\n #define MLX5_FLOW_ACTION_TUNNEL_MATCH (1ull << 38)\n #define MLX5_FLOW_ACTION_MODIFY_FIELD (1ull << 39)\n+#define MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY (1ull << 40)\n \n #define MLX5_FLOW_FATE_ACTIONS \\\n \t(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | \\\n \t MLX5_FLOW_ACTION_RSS | MLX5_FLOW_ACTION_JUMP | \\\n-\t MLX5_FLOW_ACTION_DEFAULT_MISS)\n+\t MLX5_FLOW_ACTION_DEFAULT_MISS | \\\n+\t MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)\n \n #define MLX5_FLOW_FATE_ESWITCH_ACTIONS \\\n \t(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_PORT_ID | \\\n-\t MLX5_FLOW_ACTION_JUMP)\n-\n+\t MLX5_FLOW_ACTION_JUMP | MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)\n \n #define MLX5_FLOW_MODIFY_HDR_ACTIONS (MLX5_FLOW_ACTION_SET_IPV4_SRC | \\\n \t\t\t\t      MLX5_FLOW_ACTION_SET_IPV4_DST | \\\n@@ -832,9 +833,8 @@ struct mlx5_legacy_flow_meter {\n \t/* Must be the first in struct. */\n \tTAILQ_ENTRY(mlx5_legacy_flow_meter) next;\n \t/**< Pointer to the next flow meter structure. */\n-\tuint32_t meter_id;\n-\t/**< Meter id. */\n-\tuint32_t idx; /* Index to meter object. */\n+\tuint32_t idx;\n+\t/* Index to meter object. */\n };\n \n #define MLX5_MAX_TUNNELS 256\n@@ -1088,10 +1088,12 @@ typedef int (*mlx5_flow_query_t)(struct rte_eth_dev *dev,\n \t\t\t\t const struct rte_flow_action *actions,\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-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_mtr_tbls_t)(struct rte_eth_dev *dev,\n+\t\t\t\t\tstruct mlx5_flow_meter_info *fm,\n+\t\t\t\t\tuint32_t mtr_idx,\n+\t\t\t\t\tuint8_t domain_bitmap);\n+typedef void (*mlx5_flow_destroy_mtr_tbls_t)(struct rte_eth_dev *dev,\n+\t\t\t\tstruct mlx5_flow_meter_info *fm);\n typedef void (*mlx5_flow_destroy_mtr_drop_tbls_t)(struct rte_eth_dev *dev);\n typedef uint32_t (*mlx5_flow_mtr_alloc_t)\n \t\t\t\t\t    (struct rte_eth_dev *dev);\n@@ -1409,10 +1411,12 @@ int mlx5_flow_validate_item_ecpri(const struct rte_flow_item *item,\n \t\t\t\t  uint16_t ether_type,\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-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_mtr_tbls(struct rte_eth_dev *dev,\n+\t\t\t\tstruct mlx5_flow_meter_info *fm,\n+\t\t\t\tuint32_t mtr_idx,\n+\t\t\t\tuint8_t domain_bitmap);\n+void mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,\n+\t\t\t       struct mlx5_flow_meter_info *fm);\n void mlx5_flow_destroy_mtr_drop_tbls(struct rte_eth_dev *dev);\n int mlx5_flow_dv_discover_counter_offset_support(struct rte_eth_dev *dev);\n int mlx5_shared_action_flush(struct rte_eth_dev *dev);\ndiff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c\nindex 759731333d..f789f2454e 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -4859,11 +4859,14 @@ mlx5_flow_validate_action_meter(struct rte_eth_dev *dev,\n \t\t\t\tuint64_t action_flags,\n \t\t\t\tconst struct rte_flow_action *action,\n \t\t\t\tconst struct rte_flow_attr *attr,\n+\t\t\t\tbool *def_policy,\n \t\t\t\tstruct rte_flow_error *error)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tconst struct rte_flow_action_meter *am = action->conf;\n \tstruct mlx5_flow_meter_info *fm;\n+\tstruct mlx5_flow_meter_policy *mtr_policy;\n+\tstruct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;\n \n \tif (!am)\n \t\treturn rte_flow_error_set(error, EINVAL,\n@@ -4894,10 +4897,40 @@ mlx5_flow_validate_action_meter(struct rte_eth_dev *dev,\n \t      (!fm->ingress && !attr->ingress && attr->egress) ||\n \t      (!fm->egress && !attr->egress && attr->ingress)))\n \t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\tRTE_FLOW_ERROR_TYPE_ACTION, NULL,\n+\t\t\t\"Flow attributes domain are either invalid \"\n+\t\t\t\"or have a domain conflict with current \"\n+\t\t\t\"meter attributes\");\n+\tif (fm->def_policy) {\n+\t\tif (!((attr->transfer &&\n+\t\t\tmtrmng->def_policy[MLX5_MTR_DOMAIN_TRANSFER]) ||\n+\t\t\t(attr->egress &&\n+\t\t\tmtrmng->def_policy[MLX5_MTR_DOMAIN_EGRESS]) ||\n+\t\t\t(attr->ingress &&\n+\t\t\tmtrmng->def_policy[MLX5_MTR_DOMAIN_INGRESS])))\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, NULL,\n+\t\t\t\t\t  \"Flow attributes domain \"\n+\t\t\t\t\t  \"have a conflict with current \"\n+\t\t\t\t\t  \"meter domain attributes\");\n+\t\t*def_policy = true;\n+\t} else {\n+\t\tmtr_policy = mlx5_flow_meter_policy_find(dev,\n+\t\t\t\t\t\tfm->policy_id, NULL);\n+\t\tif (!mtr_policy)\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, NULL,\n+\t\t\t\t\t  \"Invalid policy id for meter \");\n+\t\tif (!((attr->transfer && mtr_policy->transfer) ||\n+\t\t\t(attr->egress && mtr_policy->egress) ||\n+\t\t\t(attr->ingress && mtr_policy->ingress)))\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n \t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, NULL,\n-\t\t\t\t\t  \"Flow attributes are either invalid \"\n-\t\t\t\t\t  \"or have a conflict with current \"\n-\t\t\t\t\t  \"meter attributes\");\n+\t\t\t\t\t  \"Flow attributes domain \"\n+\t\t\t\t\t  \"have a conflict with current \"\n+\t\t\t\t\t  \"meter domain attributes\");\n+\t\t*def_policy = false;\n+\t}\n \treturn 0;\n }\n \n@@ -6287,6 +6320,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,\n \t\t.fdb_def_rule = !!priv->fdb_def_rule,\n \t};\n \tconst struct rte_eth_hairpin_conf *conf;\n+\tbool def_policy = false;\n \n \tif (items == NULL)\n \t\treturn -1;\n@@ -6628,6 +6662,12 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,\n \t\t\treturn rte_flow_error_set(error, ENOTSUP,\n \t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n \t\t\t\t\t\t  actions, \"too many actions\");\n+\t\tif (action_flags &\n+\t\t\tMLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)\n+\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\tNULL, \"meter action with policy \"\n+\t\t\t\t\"must be the last action\");\n \t\tswitch (type) {\n \t\tcase RTE_FLOW_ACTION_TYPE_VOID:\n \t\t\tbreak;\n@@ -7030,10 +7070,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,\n \t\t\tret = mlx5_flow_validate_action_meter(dev,\n \t\t\t\t\t\t\t      action_flags,\n \t\t\t\t\t\t\t      actions, attr,\n+\t\t\t\t\t\t\t      &def_policy,\n \t\t\t\t\t\t\t      error);\n \t\t\tif (ret < 0)\n \t\t\t\treturn ret;\n \t\t\taction_flags |= MLX5_FLOW_ACTION_METER;\n+\t\t\tif (!def_policy)\n+\t\t\t\taction_flags |=\n+\t\t\t\tMLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY;\n \t\t\t++actions_n;\n \t\t\t/* Meter action will add one more TAG action. */\n \t\t\trw_act_num += MLX5_ACT_NUM_SET_TAG;\n@@ -7290,6 +7334,36 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,\n \t\t\t\t\t\t \"multiple VLAN actions\");\n \t\t}\n \t}\n+\tif (action_flags & MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY) {\n+\t\tif ((action_flags & (MLX5_FLOW_FATE_ACTIONS &\n+\t\t\t~MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)) &&\n+\t\t\tattr->ingress)\n+\t\t\treturn rte_flow_error_set\n+\t\t\t\t(error, ENOTSUP,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\tNULL, \"fate action not supported for \"\n+\t\t\t\t\"meter with policy\");\n+\t\tif (attr->egress) {\n+\t\t\tif (action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)\n+\t\t\t\treturn rte_flow_error_set\n+\t\t\t\t\t(error, ENOTSUP,\n+\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\tNULL, \"modify header action in egress \"\n+\t\t\t\t\t\"cannot be done before meter action\");\n+\t\t\tif (action_flags & MLX5_FLOW_ACTION_ENCAP)\n+\t\t\t\treturn rte_flow_error_set\n+\t\t\t\t\t(error, ENOTSUP,\n+\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\tNULL, \"encap action in egress \"\n+\t\t\t\t\t\"cannot be done before meter action\");\n+\t\t\tif (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN)\n+\t\t\t\treturn rte_flow_error_set\n+\t\t\t\t\t(error, ENOTSUP,\n+\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\tNULL, \"push vlan action in egress \"\n+\t\t\t\t\t\"cannot be done before meter action\");\n+\t\t}\n+\t}\n \t/*\n \t * Hairpin flow will add one more TAG action in TX implicit mode.\n \t * In TX explicit mode, there will be no hairpin flow ID.\n@@ -14113,38 +14187,24 @@ flow_dv_query(struct rte_eth_dev *dev,\n  *\n  * @param[in] dev\n  *   Pointer to Ethernet device.\n- * @param[in] tbl\n- *   Pointer to the meter table set.\n- *\n- * @return\n- *   Always 0.\n+ * @param[in] fm\n+ *   Meter information table.\n  */\n-static int\n-flow_dv_destroy_mtr_tbl(struct rte_eth_dev *dev,\n-\t\t\tstruct mlx5_meter_domains_infos *tbl)\n+static void\n+flow_dv_destroy_mtr_tbls(struct rte_eth_dev *dev,\n+\t\t\tstruct mlx5_flow_meter_info *fm)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_meter_domains_infos *mtd =\n-\t\t\t\t(struct mlx5_meter_domains_infos *)tbl;\n+\tint i;\n \n-\tif (!mtd || !priv->config.dv_flow_en)\n-\t\treturn 0;\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.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.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-\tmlx5_free(mtd);\n-\treturn 0;\n+\tif (!fm || !priv->config.dv_flow_en)\n+\t\treturn;\n+\tfor (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {\n+\t\tif (fm->drop_rule[i]) {\n+\t\t\tclaim_zero(mlx5_flow_os_destroy_flow(fm->drop_rule[i]));\n+\t\t\tfm->drop_rule[i] = NULL;\n+\t\t}\n+\t}\n }\n \n static void\n@@ -14153,7 +14213,7 @@ flow_dv_destroy_mtr_drop_tbls(struct rte_eth_dev *dev)\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;\n \tstruct mlx5_flow_tbl_data_entry *tbl;\n-\tint i;\n+\tint i, j;\n \n \tfor (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {\n \t\tif (mtrmng->def_rule[i]) {\n@@ -14168,12 +14228,16 @@ flow_dv_destroy_mtr_drop_tbls(struct rte_eth_dev *dev)\n \t\t\t\t      &mtrmng->def_matcher[i]->entry);\n \t\t\tmtrmng->def_matcher[i] = NULL;\n \t\t}\n-\t\tif (mtrmng->drop_matcher[i]) {\n-\t\t\ttbl = container_of(mtrmng->drop_matcher[i]->tbl,\n-\t\t\t\tstruct mlx5_flow_tbl_data_entry, tbl);\n-\t\t\tmlx5_cache_unregister(&tbl->matchers,\n-\t\t\t\t      &mtrmng->drop_matcher[i]->entry);\n-\t\t\tmtrmng->drop_matcher[i] = NULL;\n+\t\tfor (j = 0; j < MLX5_REG_BITS; j++) {\n+\t\t\tif (mtrmng->drop_matcher[i][j]) {\n+\t\t\t\ttbl =\n+\t\t\t\tcontainer_of(mtrmng->drop_matcher[i][j]->tbl,\n+\t\t\t\t\t     struct mlx5_flow_tbl_data_entry,\n+\t\t\t\t\t     tbl);\n+\t\t\t\tmlx5_cache_unregister(&tbl->matchers,\n+\t\t\t\t\t&mtrmng->drop_matcher[i][j]->entry);\n+\t\t\t\tmtrmng->drop_matcher[i][j] = NULL;\n+\t\t\t}\n \t\t}\n \t\tif (mtrmng->drop_tbl[i]) {\n \t\t\tflow_dv_tbl_resource_release(MLX5_SH(dev),\n@@ -14626,96 +14690,171 @@ flow_dv_create_def_policy(struct rte_eth_dev *dev)\n }\n \n /**\n- * Create specify domain meter table and suffix table.\n+ * Create the needed meter tables.\n+ * Lock free, (mutex should be acquired by caller).\n  *\n  * @param[in] dev\n  *   Pointer to Ethernet device.\n- * @param[in,out] mtb\n- *   Pointer to DV meter table set.\n- * @param[in] egress\n- *   Table attribute.\n- * @param[in] transfer\n- *   Table attribute.\n- *\n+ * @param[in] fm\n+ *   Meter information table.\n+ * @param[in] mtr_idx\n+ *   Meter index.\n+ * @param[in] policy_id\n+ *   Policy index.\n+ * @param[in] domain_bitmap\n+ *   Domain bitmap.\n  * @return\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+flow_dv_create_mtr_tbls(struct rte_eth_dev *dev,\n+\t\t\tstruct mlx5_flow_meter_info *fm,\n+\t\t\tuint32_t mtr_idx,\n+\t\t\tuint8_t domain_bitmap)\n {\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_flow_mtr_mng *mtrmng = priv->sh->mtrmng;\n \tstruct rte_flow_error error;\n-\tstruct mlx5_meter_domain_info *dtb;\n+\tstruct mlx5_flow_tbl_data_entry *tbl_data;\n+\tuint8_t egress, transfer;\n+\tvoid *actions[METER_ACTIONS];\n+\tint domain, ret, i;\n+\tstruct mlx5_flow_counter *cnt;\n+\tstruct mlx5_flow_dv_match_params value = {\n+\t\t.size = sizeof(value.buf) -\n+\t\tMLX5_ST_SZ_BYTES(fte_match_set_misc4),\n+\t};\n+\tstruct mlx5_flow_dv_match_params matcher_para = {\n+\t\t.size = sizeof(matcher_para.buf) -\n+\t\tMLX5_ST_SZ_BYTES(fte_match_set_misc4),\n+\t};\n+\tint mtr_id_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_ID,\n+\t\t\t\t\t\t     0, &error);\n+\tuint32_t mtr_id_mask = (UINT32_C(1) << mtrmng->max_mtr_bits) - 1;\n+\tuint8_t mtr_id_offset = priv->mtr_reg_share ? MLX5_MTR_COLOR_BITS : 0;\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\tMLX5_ST_SZ_BYTES(fte_match_set_misc4),\n+\t\t},\n+\t};\n+\tstruct mlx5_flow_dv_matcher *drop_matcher;\n+\tstruct mlx5_flow_cb_ctx ctx = {\n+\t\t.error = &error,\n+\t\t.data = &matcher,\n+\t};\n \n-\tif (transfer)\n-\t\tdtb = &mtb->transfer;\n-\telse if (egress)\n-\t\tdtb = &mtb->egress;\n-\telse\n-\t\tdtb = &mtb->ingress;\n-\t/* Create the meter suffix table with SUFFIX level. */\n-\tdtb->sfx_tbl = flow_dv_tbl_resource_get(dev,\n+\tif (!priv->mtr_en || mtr_id_reg_c < 0) {\n+\t\trte_errno = ENOTSUP;\n+\t\treturn -1;\n+\t}\n+\tfor (domain = 0; domain < MLX5_MTR_DOMAIN_MAX; domain++) {\n+\t\tif (!(domain_bitmap & (1 << domain)) ||\n+\t\t\t(mtrmng->def_rule[domain] && !fm->drop_cnt))\n+\t\t\tcontinue;\n+\t\tegress = (domain == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;\n+\t\ttransfer = (domain == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;\n+\t\t/* Create the drop table with METER DROP level. */\n+\t\tif (!mtrmng->drop_tbl[domain]) {\n+\t\t\tmtrmng->drop_tbl[domain] = flow_dv_tbl_resource_get(dev,\n \t\t\t\t\tMLX5_FLOW_TABLE_LEVEL_METER,\n \t\t\t\t\tegress, transfer, false, NULL, 0,\n-\t\t\t\t\t0, MLX5_MTR_TABLE_ID_SUFFIX, &error);\n-\tif (!dtb->sfx_tbl) {\n-\t\tDRV_LOG(ERR, \"Failed to create meter suffix table.\");\n-\t\treturn -1;\n+\t\t\t\t\t0, MLX5_MTR_TABLE_ID_DROP, &error);\n+\t\t\tif (!mtrmng->drop_tbl[domain]) {\n+\t\t\t\tDRV_LOG(ERR, \"Failed to create meter drop table.\");\n+\t\t\t\tgoto policy_error;\n+\t\t\t}\n+\t\t}\n+\t\t/* Create default matcher in drop table. */\n+\t\tmatcher.tbl = mtrmng->drop_tbl[domain],\n+\t\ttbl_data = container_of(mtrmng->drop_tbl[domain],\n+\t\t\t\tstruct mlx5_flow_tbl_data_entry, tbl);\n+\t\tif (!mtrmng->def_matcher[domain]) {\n+\t\t\tflow_dv_match_meta_reg(matcher.mask.buf, value.buf,\n+\t\t\t\t       (enum modify_reg)mtr_id_reg_c,\n+\t\t\t\t       0, 0);\n+\t\t\tmatcher.priority = MLX5_MTRS_DEFAULT_RULE_PRIORITY;\n+\t\t\tmatcher.crc = rte_raw_cksum\n+\t\t\t\t\t((const void *)matcher.mask.buf,\n+\t\t\t\t\tmatcher.mask.size);\n+\t\t\tentry = mlx5_cache_register(&tbl_data->matchers, &ctx);\n+\t\t\tif (!entry) {\n+\t\t\t\tDRV_LOG(ERR, \"Failed to register meter \"\n+\t\t\t\t\"drop default matcher.\");\n+\t\t\t\tgoto policy_error;\n+\t\t\t}\n+\t\t\tmtrmng->def_matcher[domain] = container_of(entry,\n+\t\t\tstruct mlx5_flow_dv_matcher, entry);\n+\t\t}\n+\t\t/* Create default rule in drop table. */\n+\t\tif (!mtrmng->def_rule[domain]) {\n+\t\t\ti = 0;\n+\t\t\tactions[i++] = priv->sh->dr_drop_action;\n+\t\t\tflow_dv_match_meta_reg(matcher_para.buf, value.buf,\n+\t\t\t\t(enum modify_reg)mtr_id_reg_c, 0, 0);\n+\t\t\tret = mlx5_flow_os_create_flow\n+\t\t\t\t(mtrmng->def_matcher[domain]->matcher_object,\n+\t\t\t\t(void *)&value, i, actions,\n+\t\t\t\t&mtrmng->def_rule[domain]);\n+\t\t\tif (ret) {\n+\t\t\t\tDRV_LOG(ERR, \"Failed to create meter \"\n+\t\t\t\t\"default drop rule for drop table.\");\n+\t\t\t\tgoto policy_error;\n+\t\t\t}\n+\t\t}\n+\t\tif (!fm->drop_cnt)\n+\t\t\tcontinue;\n+\t\tMLX5_ASSERT(mtrmng->max_mtr_bits);\n+\t\tif (!mtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1]) {\n+\t\t\t/* Create matchers for Drop. */\n+\t\t\tflow_dv_match_meta_reg(matcher.mask.buf, value.buf,\n+\t\t\t\t\t(enum modify_reg)mtr_id_reg_c, 0,\n+\t\t\t\t\t(mtr_id_mask << mtr_id_offset));\n+\t\t\tmatcher.priority = MLX5_REG_BITS - mtrmng->max_mtr_bits;\n+\t\t\tmatcher.crc = rte_raw_cksum\n+\t\t\t\t\t((const void *)matcher.mask.buf,\n+\t\t\t\t\tmatcher.mask.size);\n+\t\t\tentry = mlx5_cache_register(&tbl_data->matchers, &ctx);\n+\t\t\tif (!entry) {\n+\t\t\t\tDRV_LOG(ERR,\n+\t\t\t\t\"Failed to register meter drop matcher.\");\n+\t\t\t\tgoto policy_error;\n+\t\t\t}\n+\t\t\tmtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1] =\n+\t\t\t\tcontainer_of(entry, struct mlx5_flow_dv_matcher,\n+\t\t\t\t\t     entry);\n+\t\t}\n+\t\tdrop_matcher =\n+\t\t\tmtrmng->drop_matcher[domain][mtrmng->max_mtr_bits - 1];\n+\t\t/* Create drop rule, matching meter_id only. */\n+\t\tflow_dv_match_meta_reg(matcher_para.buf, value.buf,\n+\t\t\t\t(enum modify_reg)mtr_id_reg_c,\n+\t\t\t\t(mtr_idx << mtr_id_offset), UINT32_MAX);\n+\t\ti = 0;\n+\t\tcnt = flow_dv_counter_get_by_idx(dev,\n+\t\t\t\t\tfm->drop_cnt, NULL);\n+\t\tactions[i++] = cnt->action;\n+\t\tactions[i++] = priv->sh->dr_drop_action;\n+\t\tret = mlx5_flow_os_create_flow(drop_matcher->matcher_object,\n+\t\t\t\t\t       (void *)&value, i, actions,\n+\t\t\t\t\t       &fm->drop_rule[domain]);\n+\t\tif (ret) {\n+\t\t\tDRV_LOG(ERR, \"Failed to create meter \"\n+\t\t\t\t\"drop rule for drop table.\");\n+\t\t\t\tgoto policy_error;\n+\t\t}\n \t}\n \treturn 0;\n-}\n-\n-/**\n- * Create the needed meter and suffix tables.\n- * Lock free, (mutex should be acquired by caller).\n- *\n- * @param[in] dev\n- *   Pointer to Ethernet device.\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-{\n-\tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_meter_domains_infos *mtb;\n-\tint ret;\n-\n-\tif (!priv->mtr_en) {\n-\t\trte_errno = ENOTSUP;\n-\t\treturn NULL;\n-\t}\n-\tmtb = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*mtb), 0, SOCKET_ID_ANY);\n-\tif (!mtb) {\n-\t\tDRV_LOG(ERR, \"Failed to allocate memory for meter.\");\n-\t\treturn NULL;\n-\t}\n-\t/* Egress meter table. */\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);\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\tif (ret) {\n-\t\t\tDRV_LOG(ERR, \"Failed to prepare fdb meter table.\");\n-\t\t\tgoto error_exit;\n+policy_error:\n+\tfor (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {\n+\t\tif (fm->drop_rule[i]) {\n+\t\t\tclaim_zero(mlx5_flow_os_destroy_flow\n+\t\t\t\t(fm->drop_rule[i]));\n+\t\t\tfm->drop_rule[i] = NULL;\n \t\t}\n \t}\n-\treturn mtb;\n-error_exit:\n-\tflow_dv_destroy_mtr_tbl(dev, mtb);\n-\treturn NULL;\n+\treturn -1;\n }\n \n /**\n@@ -15296,8 +15435,8 @@ const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {\n \t.remove = flow_dv_remove,\n \t.destroy = flow_dv_destroy,\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_mtr_tbls = flow_dv_create_mtr_tbls,\n+\t.destroy_mtr_tbls = flow_dv_destroy_mtr_tbls,\n \t.destroy_mtr_drop_tbls = flow_dv_destroy_mtr_drop_tbls,\n \t.create_meter = flow_dv_mtr_alloc,\n \t.free_meter = flow_dv_aso_mtr_release_to_pool,\ndiff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c\nindex b38ff77210..e97a1d77a6 100644\n--- a/drivers/net/mlx5/mlx5_flow_meter.c\n+++ b/drivers/net/mlx5/mlx5_flow_meter.c\n@@ -665,9 +665,12 @@ mlx5_flow_meter_policy_add(struct rte_eth_dev *dev,\n \tfor (i = 0; i < MLX5_MTR_DOMAIN_MAX; i++) {\n \t\tif (!(domain_bitmap & (1 << i)))\n \t\t\tcontinue;\n-\t\tmtr_policy->ingress = (i == MLX5_MTR_DOMAIN_INGRESS) ? 1 : 0;\n-\t\tmtr_policy->egress = (i == MLX5_MTR_DOMAIN_EGRESS) ? 1 : 0;\n-\t\tmtr_policy->transfer = (i == MLX5_MTR_DOMAIN_TRANSFER) ? 1 : 0;\n+\t\tif (i == MLX5_MTR_DOMAIN_INGRESS)\n+\t\t\tmtr_policy->ingress = 1;\n+\t\tif (i == MLX5_MTR_DOMAIN_EGRESS)\n+\t\t\tmtr_policy->egress = 1;\n+\t\tif (i == MLX5_MTR_DOMAIN_TRANSFER)\n+\t\t\tmtr_policy->transfer = 1;\n \t\tsub_policy = mlx5_ipool_zmalloc\n \t\t\t\t(priv->sh->ipool[MLX5_IPOOL_MTR_POLICY],\n \t\t\t\t&sub_policy_idx);\n@@ -779,6 +782,56 @@ mlx5_flow_meter_policy_delete(struct rte_eth_dev *dev,\n \treturn 0;\n }\n \n+/**\n+ * Check meter validation.\n+ *\n+ * @param[in] priv\n+ *   Pointer to mlx5 private data structure.\n+ * @param[in] meter_id\n+ *   Meter id.\n+ * @param[in] params\n+ *   Pointer to rte meter parameters.\n+ * @param[out] error\n+ *   Pointer to rte meter error structure.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,\n+\t\t\t struct rte_mtr_params *params,\n+\t\t\t struct rte_mtr_error *error)\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+\t\t\t\t\t  RTE_MTR_ERROR_TYPE_MTR_PARAMS,\n+\t\t\t\t\t  NULL, \"Meter object params null.\");\n+\t/* Previous meter color is not supported. */\n+\tif (params->use_prev_mtr_color)\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  \"Previous meter color \"\n+\t\t\t\t\t  \"not supported.\");\n+\tif (params->meter_policy_id == MLX5_INVALID_POLICY_ID)\n+\t\treturn -rte_mtr_error_set(error, ENOENT,\n+\t\t\t\tRTE_MTR_ERROR_TYPE_METER_POLICY_ID,\n+\t\t\t\tNULL, \"Meter policy id not valid.\");\n+\t/* Validate meter id. */\n+\tif (mlx5_flow_meter_find(priv, meter_id, NULL))\n+\t\treturn -rte_mtr_error_set(error, EEXIST,\n+\t\t\tRTE_MTR_ERROR_TYPE_MTR_ID, NULL,\n+\t\t\t\"Meter object already exists.\");\n+\treturn 0;\n+}\n+\n /**\n  * Modify the flow meter action.\n  *\n@@ -884,13 +937,195 @@ mlx5_flow_meter_action_modify(struct mlx5_priv *priv,\n #endif\n }\n \n-static void\n-mlx5_flow_meter_stats_enable_update(struct mlx5_flow_meter_info *fm,\n+static int\n+mlx5_flow_meter_stats_enable_update(struct rte_eth_dev *dev,\n+\t\t\t\tstruct mlx5_flow_meter_info *fm,\n \t\t\t\tuint64_t stats_mask)\n {\n \tfm->bytes_dropped =\n \t\t(stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) ? 1 : 0;\n \tfm->pkts_dropped = (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED) ? 1 : 0;\n+\tif (fm->bytes_dropped || fm->pkts_dropped) {\n+\t\tif (!fm->drop_cnt) {\n+\t\t\t/* Alloc policer counters. */\n+\t\t\tfm->drop_cnt = mlx5_counter_alloc(dev);\n+\t\t\tif (!fm->drop_cnt)\n+\t\t\t\treturn -1;\n+\t\t}\n+\t} else {\n+\t\tif (fm->drop_cnt) {\n+\t\t\tmlx5_counter_free(dev, fm->drop_cnt);\n+\t\t\tfm->drop_cnt = 0;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n+ * Create meter rules.\n+ *\n+ * @param[in] dev\n+ *   Pointer to Ethernet device.\n+ * @param[in] meter_id\n+ *   Meter id.\n+ * @param[in] params\n+ *   Pointer to rte meter parameters.\n+ * @param[in] shared\n+ *   Meter shared with other flow or not.\n+ * @param[out] error\n+ *   Pointer to rte meter error structure.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,\n+\t\t       struct rte_mtr_params *params, int shared,\n+\t\t       struct rte_mtr_error *error)\n+{\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_legacy_flow_meters *fms = &priv->flow_meters;\n+\tstruct mlx5_flow_meter_profile *fmp;\n+\tstruct mlx5_flow_meter_info *fm;\n+\tstruct mlx5_legacy_flow_meter *legacy_fm;\n+\tstruct mlx5_flow_meter_policy *mtr_policy = NULL;\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+\tstruct mlx5_aso_mtr *aso_mtr;\n+\tuint32_t mtr_idx, policy_idx;\n+\tunion mlx5_l3t_data data;\n+\tint ret;\n+\tuint8_t domain_bitmap;\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+\t\t\t\t\tRTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\t\"Meter is not supported\");\n+\t/* Validate the parameters. */\n+\tret = mlx5_flow_meter_validate(priv, meter_id, params, error);\n+\tif (ret)\n+\t\treturn ret;\n+\t/* Meter profile must exist. */\n+\tfmp = mlx5_flow_meter_profile_find(priv, params->meter_profile_id);\n+\tif (fmp == NULL)\n+\t\treturn -rte_mtr_error_set(error, ENOENT,\n+\t\t\tRTE_MTR_ERROR_TYPE_METER_PROFILE_ID,\n+\t\t\tNULL, \"Meter profile id not valid.\");\n+\t/* Meter policy must exist. */\n+\tif (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {\n+\t\t__atomic_add_fetch\n+\t\t\t(&priv->sh->mtrmng->def_policy_ref_cnt,\n+\t\t\t1, __ATOMIC_RELAXED);\n+\t\tdomain_bitmap = MLX5_MTR_ALL_DOMAIN_BIT;\n+\t\tif (!priv->config.dv_esw_en)\n+\t\t\tdomain_bitmap &= ~MLX5_MTR_DOMAIN_TRANSFER_BIT;\n+\t} else {\n+\t\tmtr_policy = mlx5_flow_meter_policy_find(dev,\n+\t\t\t\tparams->meter_policy_id, &policy_idx);\n+\t\tif (!priv->sh->meter_aso_en)\n+\t\t\treturn -rte_mtr_error_set(error, ENOTSUP,\n+\t\t\t\tRTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\"Part of the policies cannot be \"\n+\t\t\t\t\"supported without ASO \");\n+\t\tif (!mtr_policy)\n+\t\t\treturn -rte_mtr_error_set(error, ENOENT,\n+\t\t\t\tRTE_MTR_ERROR_TYPE_METER_POLICY_ID,\n+\t\t\t\tNULL, \"Meter policy id not valid.\");\n+\t\tdomain_bitmap = (mtr_policy->ingress ?\n+\t\t\t\t\tMLX5_MTR_DOMAIN_INGRESS_BIT : 0) |\n+\t\t\t\t(mtr_policy->egress ?\n+\t\t\t\t\tMLX5_MTR_DOMAIN_EGRESS_BIT : 0) |\n+\t\t\t\t(mtr_policy->transfer ?\n+\t\t\t\t\tMLX5_MTR_DOMAIN_TRANSFER_BIT : 0);\n+\t}\n+\t/* Allocate the flow meter memory. */\n+\tif (priv->sh->meter_aso_en) {\n+\t\tmtr_idx = mlx5_flow_mtr_alloc(dev);\n+\t\tif (!mtr_idx)\n+\t\t\treturn -rte_mtr_error_set(error, ENOMEM,\n+\t\t\t\tRTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\"Memory alloc failed for meter.\");\n+\t\taso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);\n+\t\tfm = &aso_mtr->fm;\n+\t} else {\n+\t\tlegacy_fm = mlx5_ipool_zmalloc\n+\t\t\t\t(priv->sh->ipool[MLX5_IPOOL_MTR], &mtr_idx);\n+\t\tif (legacy_fm == NULL)\n+\t\t\treturn -rte_mtr_error_set(error, ENOMEM,\n+\t\t\t\tRTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\"Memory alloc failed for meter.\");\n+\t\tlegacy_fm->idx = mtr_idx;\n+\t\tfm = &legacy_fm->fm;\n+\t}\n+\tmtr_id_bits = MLX5_REG_BITS - __builtin_clz(mtr_idx);\n+\tif ((mtr_id_bits + priv->sh->mtrmng->max_mtr_flow_bits) >\n+\t    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->sh->mtrmng->max_mtr_bits)\n+\t\tpriv->sh->mtrmng->max_mtr_bits = mtr_id_bits;\n+\t/* Fill the flow meter parameters. */\n+\tfm->meter_id = meter_id;\n+\tfm->policy_id = params->meter_policy_id;\n+\tfm->profile = fmp;\n+\tif (mlx5_flow_meter_stats_enable_update(dev, fm, params->stats_mask))\n+\t\tgoto error;\n+\tif (mlx5_flow_create_mtr_tbls(dev, fm, mtr_idx, domain_bitmap))\n+\t\tgoto error;\n+\t/* Add to the flow meter list. */\n+\tif (!priv->sh->meter_aso_en)\n+\t\tTAILQ_INSERT_TAIL(fms, legacy_fm, next);\n+\t/* Add to the flow meter list. */\n+\tfm->active_state = 1; /* Config meter starts as active. */\n+\tfm->is_enable = 1;\n+\tfm->shared = !!shared;\n+\t__atomic_add_fetch(&fm->profile->ref_cnt, 1, __ATOMIC_RELAXED);\n+\tif (params->meter_policy_id == priv->sh->mtrmng->def_policy_id) {\n+\t\tfm->def_policy = 1;\n+\t\tfm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg);\n+\t\tif (!fm->flow_ipool)\n+\t\t\tgoto error;\n+\t}\n+\trte_spinlock_init(&fm->sl);\n+\t/* If ASO meter supported, update ASO flow meter by wqe. */\n+\tif (priv->sh->meter_aso_en) {\n+\t\taso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);\n+\t\tret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);\n+\t\tif (ret)\n+\t\t\tgoto error;\n+\t\tif (!priv->mtr_idx_tbl) {\n+\t\t\tpriv->mtr_idx_tbl =\n+\t\t\t\tmlx5_l3t_create(MLX5_L3T_TYPE_DWORD);\n+\t\t\tif (!priv->mtr_idx_tbl)\n+\t\t\t\tgoto error;\n+\t\t}\n+\t\tdata.dword = mtr_idx;\n+\t\tif (mlx5_l3t_set_entry(priv->mtr_idx_tbl, meter_id, &data))\n+\t\t\tgoto error;\n+\t}\n+\tif (mtr_policy)\n+\t\t__atomic_add_fetch(&mtr_policy->ref_cnt, 1, __ATOMIC_RELAXED);\n+\treturn 0;\n+error:\n+\tmlx5_flow_destroy_mtr_tbls(dev, fm);\n+\t/* Free policer counters. */\n+\tif (fm->drop_cnt)\n+\t\tmlx5_counter_free(dev, fm->drop_cnt);\n+\tif (priv->sh->meter_aso_en)\n+\t\tmlx5_flow_mtr_free(dev, mtr_idx);\n+\telse\n+\t\tmlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], mtr_idx);\n+\treturn -rte_mtr_error_set(error, ENOTSUP,\n+\t\tRTE_MTR_ERROR_TYPE_UNSPECIFIED,\n+\t\tNULL, \"Failed to create devx meter.\");\n }\n \n static int\n@@ -902,6 +1137,7 @@ mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,\n \tstruct mlx5_legacy_flow_meters *fms = &priv->flow_meters;\n \tstruct mlx5_flow_meter_profile *fmp;\n \tstruct mlx5_legacy_flow_meter *legacy_fm = NULL;\n+\tstruct mlx5_flow_meter_policy *mtr_policy;\n \n \t/* Meter object must not have any owner. */\n \tMLX5_ASSERT(!fm->ref_cnt);\n@@ -911,23 +1147,42 @@ mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,\n \t\treturn -1;\n \t/* Update dependencies. */\n \t__atomic_sub_fetch(&fmp->ref_cnt, 1, __ATOMIC_RELAXED);\n+\tfm->profile = NULL;\n \t/* Remove from list. */\n \tif (!priv->sh->meter_aso_en) {\n-\t\tlegacy_fm = container_of(fm, struct mlx5_legacy_flow_meter, fm);\n+\t\tlegacy_fm = container_of(fm,\n+\t\t\tstruct mlx5_legacy_flow_meter, fm);\n \t\tTAILQ_REMOVE(fms, legacy_fm, next);\n \t}\n \t/* Free drop counters. */\n \tif (fm->drop_cnt)\n \t\tmlx5_counter_free(dev, fm->drop_cnt);\n \t/* Free meter flow table. */\n-\tif (fm->flow_ipool)\n+\tif (fm->flow_ipool) {\n \t\tmlx5_ipool_destroy(fm->flow_ipool);\n-\tmlx5_flow_destroy_mtr_tbls(dev, fm->mfts);\n-\tif (priv->sh->meter_aso_en)\n+\t\tfm->flow_ipool = 0;\n+\t}\n+\tmlx5_flow_destroy_mtr_tbls(dev, fm);\n+\tif (fm->def_policy)\n+\t\t__atomic_sub_fetch(&priv->sh->mtrmng->def_policy_ref_cnt,\n+\t\t\t\t1, __ATOMIC_RELAXED);\n+\tif (priv->sh->meter_aso_en) {\n+\t\tif (!fm->def_policy) {\n+\t\t\tmtr_policy = mlx5_flow_meter_policy_find(dev,\n+\t\t\t\t\t\tfm->policy_id, NULL);\n+\t\t\tif (mtr_policy)\n+\t\t\t\t__atomic_sub_fetch(&mtr_policy->ref_cnt,\n+\t\t\t\t\t\t1, __ATOMIC_RELAXED);\n+\t\t\tfm->policy_id = 0;\n+\t\t}\n+\t\tfm->def_policy = 0;\n+\t\tif (mlx5_l3t_clear_entry(priv->mtr_idx_tbl, fm->meter_id))\n+\t\t\treturn -1;\n \t\tmlx5_flow_mtr_free(dev, mtr_idx);\n-\telse\n+\t} else {\n \t\tmlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR],\n \t\t\t\t\tlegacy_fm->idx);\n+\t}\n \treturn 0;\n }\n \n@@ -954,30 +1209,28 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,\n \n \tif (!priv->mtr_en)\n \t\treturn -rte_mtr_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\t  RTE_MTR_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t\t  NULL,\n \t\t\t\t\t  \"Meter is not supported\");\n \t/* Meter object must exist. */\n \tfm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx);\n \tif (fm == NULL)\n \t\treturn -rte_mtr_error_set(error, ENOENT,\n \t\t\t\t\t  RTE_MTR_ERROR_TYPE_MTR_ID,\n-\t\t\t\t\t  NULL, \"Meter object id not valid.\");\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"Meter object id not valid.\");\n \t/* Meter object must not have any owner. */\n \tif (fm->ref_cnt > 0)\n \t\treturn -rte_mtr_error_set(error, EBUSY,\n \t\t\t\t\t  RTE_MTR_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\t  NULL, \"Meter object is being used.\");\n-\tif (priv->sh->meter_aso_en) {\n-\t\tif (mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id))\n-\t\t\treturn -rte_mtr_error_set(error, EBUSY,\n-\t\t\t\tRTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t\"Fail to delete ASO Meter in index table.\");\n-\t}\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"Meter object is being used.\");\n \t/* Destroy the meter profile. */\n \tif (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))\n \t\treturn -rte_mtr_error_set(error, EINVAL,\n \t\t\t\t\tRTE_MTR_ERROR_TYPE_METER_PROFILE_ID,\n-\t\t\t\t\tNULL, \"MTR object meter profile invalid.\");\n+\t\t\t\t\tNULL,\n+\t\t\t\t\t\"MTR object meter profile invalid.\");\n \treturn 0;\n }\n \n@@ -1211,7 +1464,11 @@ mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,\n \t\treturn -rte_mtr_error_set(error, ENOENT,\n \t\t\t\t\t  RTE_MTR_ERROR_TYPE_MTR_ID,\n \t\t\t\t\t  NULL, \"Meter object id not valid.\");\n-\tmlx5_flow_meter_stats_enable_update(fm, stats_mask);\n+\tif (mlx5_flow_meter_stats_enable_update(dev, fm, stats_mask))\n+\t\treturn -rte_mtr_error_set(error, ENOENT,\n+\t\t\t\t\t  RTE_MTR_ERROR_TYPE_MTR_ID,\n+\t\t\t\t\t  NULL, \"Fail to allocate \"\n+\t\t\t\t\t  \"counter for meter.\");\n \treturn 0;\n }\n \n@@ -1289,6 +1546,7 @@ static const struct rte_mtr_ops mlx5_flow_mtr_ops = {\n \t.meter_policy_validate = mlx5_flow_meter_policy_validate,\n \t.meter_policy_add = mlx5_flow_meter_policy_add,\n \t.meter_policy_delete = mlx5_flow_meter_policy_delete,\n+\t.create = mlx5_flow_meter_create,\n \t.destroy = mlx5_flow_meter_destroy,\n \t.meter_enable = mlx5_flow_meter_enable,\n \t.meter_disable = mlx5_flow_meter_disable,\n@@ -1327,7 +1585,7 @@ mlx5_flow_meter_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)\n  *   Pointer to Meter index.\n  *\n  * @return\n- *   Pointer to the profile found on success, NULL otherwise.\n+ *   Pointer to the meter info found on success, NULL otherwise.\n  */\n struct mlx5_flow_meter_info *\n mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,\n@@ -1342,30 +1600,27 @@ mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,\n \n \tif (priv->sh->meter_aso_en) {\n \t\trte_spinlock_lock(&pools_mng->mtrsl);\n-\t\tif (priv->mtr_idx_tbl) {\n-\t\t\tif (mlx5_l3t_get_entry(priv->mtr_idx_tbl,\n-\t\t\t\tmeter_id, &data) ||\n-\t\t\t\t!data.dword) {\n-\t\t\t\trte_spinlock_unlock(&pools_mng->mtrsl);\n-\t\t\t\treturn NULL;\n-\t\t\t}\n-\t\t\tif (mtr_idx)\n-\t\t\t\t*mtr_idx = data.dword;\n-\t\t\taso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);\n-\t\t\t/* Remove reference taken by the mlx5_l3t_get_entry. */\n-\t\t\tmlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);\n-\t\t} else {\n-\t\t\tif (mtr_idx)\n-\t\t\t\t*mtr_idx = meter_id;\n-\t\t\taso_mtr = mlx5_aso_meter_by_idx(priv, meter_id);\n+\t\tif (!pools_mng->n_valid || !priv->mtr_idx_tbl) {\n+\t\t\trte_spinlock_unlock(&pools_mng->mtrsl);\n+\t\t\treturn NULL;\n \t\t}\n+\t\tif (mlx5_l3t_get_entry(priv->mtr_idx_tbl, meter_id, &data) ||\n+\t\t\t!data.dword) {\n+\t\t\trte_spinlock_unlock(&pools_mng->mtrsl);\n+\t\t\treturn NULL;\n+\t\t}\n+\t\tif (mtr_idx)\n+\t\t\t*mtr_idx = data.dword;\n+\t\taso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);\n+\t\t/* Remove reference taken by the mlx5_l3t_get_entry. */\n+\t\tmlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);\n \t\trte_spinlock_unlock(&pools_mng->mtrsl);\n \t\tif (!aso_mtr || aso_mtr->state == ASO_METER_FREE)\n \t\t\treturn NULL;\n \t\treturn &aso_mtr->fm;\n \t}\n \tTAILQ_FOREACH(legacy_fm, fms, next)\n-\t\tif (meter_id == legacy_fm->meter_id) {\n+\t\tif (meter_id == legacy_fm->fm.meter_id) {\n \t\t\tif (mtr_idx)\n \t\t\t\t*mtr_idx = legacy_fm->idx;\n \t\t\treturn &legacy_fm->fm;\n@@ -1382,7 +1637,7 @@ mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,\n  *   Meter index.\n  *\n  * @return\n- *   Pointer to the profile found on success, NULL otherwise.\n+ *   Pointer to the meter info found on success, NULL otherwise.\n  */\n struct mlx5_flow_meter_info *\n flow_dv_meter_find_by_idx(struct mlx5_priv *priv, uint32_t idx)\n@@ -1391,6 +1646,8 @@ flow_dv_meter_find_by_idx(struct mlx5_priv *priv, uint32_t idx)\n \n \tif (priv->sh->meter_aso_en) {\n \t\taso_mtr = mlx5_aso_meter_by_idx(priv, idx);\n+\t\tif (!aso_mtr)\n+\t\t\treturn NULL;\n \t\treturn &aso_mtr->fm;\n \t} else {\n \t\treturn mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MTR], idx);\n@@ -1526,32 +1783,33 @@ int\n mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_aso_mtr_pools_mng *pools_mng =\n-\t\t\t\t&priv->sh->mtrmng->pools_mng;\n \tstruct mlx5_legacy_flow_meters *fms = &priv->flow_meters;\n \tstruct mlx5_mtr_profiles *fmps = &priv->flow_meter_profiles;\n \tstruct mlx5_flow_meter_profile *fmp;\n \tstruct mlx5_legacy_flow_meter *legacy_fm;\n \tstruct mlx5_flow_meter_info *fm;\n-\tstruct mlx5_aso_mtr_pool *mtr_pool;\n \tstruct mlx5_flow_meter_sub_policy *sub_policy;\n \tvoid *tmp;\n-\tuint32_t i, offset, mtr_idx, policy_idx;\n+\tuint32_t i, mtr_idx, policy_idx;\n \tvoid *entry;\n+\tstruct mlx5_aso_mtr *aso_mtr;\n \n \tif (!priv->mtr_en)\n \t\treturn 0;\n \tif (priv->sh->meter_aso_en) {\n-\t\ti = pools_mng->n_valid;\n-\t\twhile (i--) {\n-\t\t\tmtr_pool = pools_mng->pools[i];\n-\t\t\tfor (offset = 0; offset < MLX5_ASO_MTRS_PER_POOL;\n-\t\t\t\toffset++) {\n-\t\t\t\tfm = &mtr_pool->mtrs[offset].fm;\n-\t\t\t\tmtr_idx = MLX5_MAKE_MTR_IDX(i, offset);\n-\t\t\t\t(void)mlx5_flow_meter_params_flush(dev,\n+\t\tif (priv->mtr_idx_tbl) {\n+\t\t\tMLX5_L3T_FOREACH(priv->mtr_idx_tbl, i, entry) {\n+\t\t\t\tmtr_idx = *(uint32_t *)entry;\n+\t\t\t\tif (mtr_idx) {\n+\t\t\t\t\taso_mtr =\n+\t\t\t\t\tmlx5_aso_meter_by_idx(priv, mtr_idx);\n+\t\t\t\t\tfm = &aso_mtr->fm;\n+\t\t\t\t\t(void)mlx5_flow_meter_params_flush(dev,\n \t\t\t\t\t\tfm, mtr_idx);\n+\t\t\t\t}\n \t\t\t}\n+\t\t\tmlx5_l3t_destroy(priv->mtr_idx_tbl);\n+\t\t\tpriv->mtr_idx_tbl = NULL;\n \t\t}\n \t} else {\n \t\tTAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) {\n@@ -1562,7 +1820,7 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)\n \t\t\t\tNULL, \"MTR object meter profile invalid.\");\n \t\t}\n \t}\n-\tif (priv->sh->mtrmng->policy_idx_tbl) {\n+\tif (priv->sh->mtrmng->policy_idx_tbl && priv->sh->refcnt == 1) {\n \t\tMLX5_L3T_FOREACH(priv->sh->mtrmng->policy_idx_tbl,\n \t\t\t\t\ti, entry) {\n \t\t\tpolicy_idx = *(uint32_t *)entry;\n@@ -1597,6 +1855,7 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)\n \t}\n \t/* Delete default policy table. */\n \tmlx5_flow_destroy_def_policy(dev);\n-\tmlx5_flow_destroy_mtr_drop_tbls(dev);\n+\tif (priv->sh->refcnt == 1)\n+\t\tmlx5_flow_destroy_mtr_drop_tbls(dev);\n \treturn 0;\n }\n",
    "prefixes": [
        "v5",
        "2/4"
    ]
}