get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 91557,
    "url": "https://patches.dpdk.org/api/patches/91557/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20210415092023.2089541-2-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": "<20210415092023.2089541-2-lizh@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210415092023.2089541-2-lizh@nvidia.com",
    "date": "2021-04-15T09:20:22",
    "name": "[v8,1/2] ethdev: add pre-defined meter policy API",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "6e017881e819447aac1abbbe3e1b16d6f48b1243",
    "submitter": {
        "id": 1967,
        "url": "https://patches.dpdk.org/api/people/1967/?format=api",
        "name": "Li Zhang",
        "email": "lizh@nvidia.com"
    },
    "delegate": {
        "id": 319,
        "url": "https://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20210415092023.2089541-2-lizh@nvidia.com/mbox/",
    "series": [
        {
            "id": 16404,
            "url": "https://patches.dpdk.org/api/series/16404/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=16404",
            "date": "2021-04-15T09:20:21",
            "name": "Support meter policy API",
            "version": 8,
            "mbox": "https://patches.dpdk.org/series/16404/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/91557/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/91557/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 4C86FA0A0E;\n\tThu, 15 Apr 2021 11:20:44 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 20CA5162168;\n\tThu, 15 Apr 2021 11:20:36 +0200 (CEST)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by mails.dpdk.org (Postfix) with ESMTP id A1A5216213C\n for <dev@dpdk.org>; Thu, 15 Apr 2021 11:20:31 +0200 (CEST)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n lizh@nvidia.com)\n with SMTP; 15 Apr 2021 12:20:27 +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 13F9KRht026624;\n Thu, 15 Apr 2021 12:20:27 +0300"
        ],
        "From": "Li Zhang <lizh@nvidia.com>",
        "To": "dekelp@nvidia.com, orika@nvidia.com, viacheslavo@nvidia.com,\n matan@nvidia.com, shahafs@nvidia.com, cristian.dumitrescu@intel.com,\n lironh@marvell.com, jerinj@marvell.com, ferruh.yigit@intel.com,\n ajit.khaparde@broadcom.com, Wisam Jaddo <wisamm@nvidia.com>,\n Xiaoyun Li <xiaoyun.li@intel.com>,\n Jasvinder Singh <jasvinder.singh@intel.com>,\n Thomas Monjalon <thomas@monjalon.net>,\n Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>,\n Ray Kinsella <mdr@ashroe.eu>, Neil Horman <nhorman@tuxdriver.com>",
        "Cc": "dev@dpdk.org, rasland@nvidia.com, roniba@nvidia.com,\n Haifei Luo <haifeil@nvidia.com>, Jiawei Wang <jiaweiw@nvidia.com>",
        "Date": "Thu, 15 Apr 2021 12:20:22 +0300",
        "Message-Id": "<20210415092023.2089541-2-lizh@nvidia.com>",
        "X-Mailer": "git-send-email 2.21.0",
        "In-Reply-To": "<20210415092023.2089541-1-lizh@nvidia.com>",
        "References": "<20210318085815.804896-1-lizh@nvidia.com>\n <20210415092023.2089541-1-lizh@nvidia.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v8 1/2] ethdev: add pre-defined meter policy API",
        "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": "Currently, the flow meter policy does not support multiple actions\nper color; also the allowed action types per color are very limited.\nIn addition, the policy cannot be pre-defined.\n\nDue to the growing in flow actions offload abilities there is a potential\nfor the user to use variety of actions per color differently.\nThis new meter policy API comes to allow this potential in the most ethdev\ncommon way using rte_flow action definition.\nA list of rte_flow actions will be provided by the user per color\nin order to create a meter policy.\nIn addition, the API forces to pre-define the policy before\nthe meters creation in order to allow sharing of single policy\nwith multiple meters efficiently.\n\nmeter_policy_id is added into struct rte_mtr_params.\nSo that it can get the policy during the meters creation.\n\nAllow coloring the packet using a new rte_flow_action_color\nas could be done by the old policy API.\n\nAdd two common policy template as macros in the head file.\n\nThe next API function were added:\n- rte_mtr_meter_policy_add\n- rte_mtr_meter_policy_delete\n- rte_mtr_meter_policy_update\n- rte_mtr_meter_policy_validate\nThe next struct was changed:\n- rte_mtr_params\n- rte_mtr_capabilities\nThe next API was deleted:\n- rte_mtr_policer_actions_update\n\nTo support this API the following app were changed:\napp/test-flow-perf: clean meter policer\napp/testpmd: clean meter policer\n\nTo support this API the following drivers were changed:\nnet/softnic: support meter policy API\n1. cleans meter rte_mtr_policer_action.\n2. Support policy API to get color action as policer action did.\n   The color action will be mapped into rte_table_action_policer.\n\nnet/mlx5: clean meter creation management\nCleans and breaks part of the current meter management\nin order to allow better design with policy API.\n\nSigned-off-by: Li Zhang <lizh@nvidia.com>\nSigned-off-by: Haifei Luo <haifeil@nvidia.com>\nSigned-off-by: Jiawei Wang <jiaweiw@nvidia.com>\nAcked-by: Matan Azrad <matan@nvidia.com>\nAcked-by: Ray Kinsella <mdr@ashroe.eu>\n---\n app/test-flow-perf/main.c                     |   7 -\n app/test-pmd/cmdline.c                        |   1 -\n app/test-pmd/cmdline_mtr.c                    | 172 -------\n app/test-pmd/cmdline_mtr.h                    |   1 -\n doc/guides/prog_guide/rte_flow.rst            |  21 +\n .../traffic_metering_and_policing.rst         |  16 +-\n doc/guides/rel_notes/release_21_05.rst        |  21 +\n doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  18 -\n drivers/net/mlx5/mlx5.h                       |  24 +-\n drivers/net/mlx5/mlx5_flow.c                  |  46 --\n drivers/net/mlx5/mlx5_flow.h                  |  18 +-\n drivers/net/mlx5/mlx5_flow_aso.c              |   8 +-\n drivers/net/mlx5/mlx5_flow_dv.c               | 461 +-----------------\n drivers/net/mlx5/mlx5_flow_meter.c            | 369 +-------------\n drivers/net/softnic/rte_eth_softnic_flow.c    |  19 +-\n .../net/softnic/rte_eth_softnic_internals.h   |  18 +-\n drivers/net/softnic/rte_eth_softnic_meter.c   | 290 ++++++++---\n lib/librte_ethdev/rte_flow.h                  |  22 +\n lib/librte_ethdev/rte_mtr.c                   |  55 ++-\n lib/librte_ethdev/rte_mtr.h                   | 223 +++++++--\n lib/librte_ethdev/rte_mtr_driver.h            |  44 +-\n lib/librte_ethdev/version.map                 |   5 +-\n 22 files changed, 603 insertions(+), 1256 deletions(-)",
    "diff": "diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c\nindex 8e229679df..9be8edc31d 100644\n--- a/app/test-flow-perf/main.c\n+++ b/app/test-flow-perf/main.c\n@@ -928,13 +928,6 @@ create_meter_rule(int port_id, uint32_t counter)\n \n \t/*create meter*/\n \tparams.meter_profile_id = default_prof_id;\n-\tparams.action[RTE_COLOR_GREEN] =\n-\t\tMTR_POLICER_ACTION_COLOR_GREEN;\n-\tparams.action[RTE_COLOR_YELLOW] =\n-\t\tMTR_POLICER_ACTION_COLOR_YELLOW;\n-\tparams.action[RTE_COLOR_RED] =\n-\t\tMTR_POLICER_ACTION_DROP;\n-\n \tret = rte_mtr_create(port_id, counter, &params, 1, &error);\n \tif (ret != 0) {\n \t\tprintf(\"Port %u create meter idx(%d) error(%d) message: %s\\n\",\ndiff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c\nindex 5bf1497f2b..e244df27dc 100644\n--- a/app/test-pmd/cmdline.c\n+++ b/app/test-pmd/cmdline.c\n@@ -17074,7 +17074,6 @@ cmdline_parse_ctx_t main_ctx[] = {\n \t(cmdline_parse_inst_t *)&cmd_del_port_meter,\n \t(cmdline_parse_inst_t *)&cmd_set_port_meter_profile,\n \t(cmdline_parse_inst_t *)&cmd_set_port_meter_dscp_table,\n-\t(cmdline_parse_inst_t *)&cmd_set_port_meter_policer_action,\n \t(cmdline_parse_inst_t *)&cmd_set_port_meter_stats_mask,\n \t(cmdline_parse_inst_t *)&cmd_show_port_meter_stats,\n \t(cmdline_parse_inst_t *)&cmd_mcast_addr,\ndiff --git a/app/test-pmd/cmdline_mtr.c b/app/test-pmd/cmdline_mtr.c\nindex 4d9bfde78d..aa454af536 100644\n--- a/app/test-pmd/cmdline_mtr.c\n+++ b/app/test-pmd/cmdline_mtr.c\n@@ -146,53 +146,6 @@ parse_meter_color_str(char *c_str, uint32_t *use_prev_meter_color,\n \treturn 0;\n }\n \n-static int\n-string_to_policer_action(char *s)\n-{\n-\tif ((strcmp(s, \"G\") == 0) || (strcmp(s, \"g\") == 0))\n-\t\treturn MTR_POLICER_ACTION_COLOR_GREEN;\n-\n-\tif ((strcmp(s, \"Y\") == 0) || (strcmp(s, \"y\") == 0))\n-\t\treturn MTR_POLICER_ACTION_COLOR_YELLOW;\n-\n-\tif ((strcmp(s, \"R\") == 0) || (strcmp(s, \"r\") == 0))\n-\t\treturn MTR_POLICER_ACTION_COLOR_RED;\n-\n-\tif ((strcmp(s, \"D\") == 0) || (strcmp(s, \"d\") == 0))\n-\t\treturn MTR_POLICER_ACTION_DROP;\n-\n-\treturn -1;\n-}\n-\n-static int\n-parse_policer_action_string(char *p_str, uint32_t action_mask,\n-\tenum rte_mtr_policer_action actions[])\n-{\n-\tchar *token;\n-\tint count = __builtin_popcount(action_mask);\n-\tint g_color = 0, y_color = 0, action, i;\n-\n-\tfor (i = 0; i < count; i++) {\n-\t\ttoken = strtok_r(p_str, PARSE_DELIMITER, &p_str);\n-\t\tif (token ==  NULL)\n-\t\t\treturn -1;\n-\n-\t\taction = string_to_policer_action(token);\n-\t\tif (action == -1)\n-\t\t\treturn -1;\n-\n-\t\tif (g_color == 0 && (action_mask & 0x1)) {\n-\t\t\tactions[RTE_COLOR_GREEN] = action;\n-\t\t\tg_color = 1;\n-\t\t} else if (y_color == 0 && (action_mask & 0x2)) {\n-\t\t\tactions[RTE_COLOR_YELLOW] = action;\n-\t\t\ty_color = 1;\n-\t\t} else\n-\t\t\tactions[RTE_COLOR_RED] = action;\n-\t}\n-\treturn 0;\n-}\n-\n static int\n parse_multi_token_string(char *t_str, uint16_t *port_id,\n \tuint32_t *mtr_id, enum rte_color **dscp_table)\n@@ -302,10 +255,6 @@ static void cmd_show_port_meter_cap_parsed(void *parsed_result,\n \t\tcap.color_aware_trtcm_rfc2698_supported);\n \tprintf(\"cap.color_aware_trtcm_rfc4115_supported %\" PRId32 \"\\n\",\n \t\tcap.color_aware_trtcm_rfc4115_supported);\n-\tprintf(\"cap.policer_action_recolor_supported %\" PRId32 \"\\n\",\n-\t\tcap.policer_action_recolor_supported);\n-\tprintf(\"cap.policer_action_drop_supported %\" PRId32 \"\\n\",\n-\t\tcap.policer_action_drop_supported);\n \tprintf(\"cap.srtcm_rfc2697_byte_mode_supported %\" PRId32 \"\\n\",\n \t\tcap.srtcm_rfc2697_byte_mode_supported);\n \tprintf(\"cap.srtcm_rfc2697_packet_mode_supported %\" PRId32 \"\\n\",\n@@ -842,12 +791,6 @@ static void cmd_create_port_meter_parsed(void *parsed_result,\n \telse\n \t\tparams.meter_enable = 0;\n \n-\tparams.action[RTE_COLOR_GREEN] =\n-\t\tstring_to_policer_action(res->g_action);\n-\tparams.action[RTE_COLOR_YELLOW] =\n-\t\tstring_to_policer_action(res->y_action);\n-\tparams.action[RTE_COLOR_RED] =\n-\t\tstring_to_policer_action(res->r_action);\n \tparams.stats_mask = res->statistics_mask;\n \n \tret = rte_mtr_create(port_id, mtr_id, &params, shared, &error);\n@@ -1215,121 +1158,6 @@ cmdline_parse_inst_t cmd_set_port_meter_dscp_table = {\n \t},\n };\n \n-/* *** Set Port Meter Policer Action *** */\n-struct cmd_set_port_meter_policer_action_result {\n-\tcmdline_fixed_string_t set;\n-\tcmdline_fixed_string_t port;\n-\tcmdline_fixed_string_t meter;\n-\tcmdline_fixed_string_t policer;\n-\tcmdline_fixed_string_t action;\n-\tuint16_t port_id;\n-\tuint32_t mtr_id;\n-\tuint32_t action_mask;\n-\tcmdline_multi_string_t policer_action;\n-};\n-\n-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_set =\n-\tTOKEN_STRING_INITIALIZER(\n-\t\tstruct cmd_set_port_meter_policer_action_result, set, \"set\");\n-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_port =\n-\tTOKEN_STRING_INITIALIZER(\n-\t\tstruct cmd_set_port_meter_policer_action_result, port, \"port\");\n-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_meter =\n-\tTOKEN_STRING_INITIALIZER(\n-\t\tstruct cmd_set_port_meter_policer_action_result, meter,\n-\t\t\"meter\");\n-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_policer =\n-\tTOKEN_STRING_INITIALIZER(\n-\t\tstruct cmd_set_port_meter_policer_action_result, policer,\n-\t\t\"policer\");\n-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_action =\n-\tTOKEN_STRING_INITIALIZER(\n-\t\tstruct cmd_set_port_meter_policer_action_result, action,\n-\t\t\"action\");\n-cmdline_parse_token_num_t cmd_set_port_meter_policer_action_port_id =\n-\tTOKEN_NUM_INITIALIZER(\n-\t\tstruct cmd_set_port_meter_policer_action_result, port_id,\n-\t\tRTE_UINT16);\n-cmdline_parse_token_num_t cmd_set_port_meter_policer_action_mtr_id =\n-\tTOKEN_NUM_INITIALIZER(\n-\t\tstruct cmd_set_port_meter_policer_action_result, mtr_id,\n-\t\tRTE_UINT32);\n-cmdline_parse_token_num_t cmd_set_port_meter_policer_action_action_mask =\n-\tTOKEN_NUM_INITIALIZER(\n-\t\tstruct cmd_set_port_meter_policer_action_result, action_mask,\n-\t\tRTE_UINT32);\n-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_policer_action =\n-\tTOKEN_STRING_INITIALIZER(\n-\t\tstruct cmd_set_port_meter_policer_action_result,\n-\t\tpolicer_action, TOKEN_STRING_MULTI);\n-\n-static void cmd_set_port_meter_policer_action_parsed(void *parsed_result,\n-\t__rte_unused struct cmdline *cl,\n-\t__rte_unused void *data)\n-{\n-\tstruct cmd_set_port_meter_policer_action_result *res = parsed_result;\n-\tenum rte_mtr_policer_action *actions;\n-\tstruct rte_mtr_error error;\n-\tuint32_t mtr_id = res->mtr_id;\n-\tuint32_t action_mask = res->action_mask;\n-\tuint16_t port_id = res->port_id;\n-\tchar *p_str = res->policer_action;\n-\tint ret;\n-\n-\tif (port_id_is_invalid(port_id, ENABLED_WARN))\n-\t\treturn;\n-\n-\t/* Check: action mask */\n-\tif (action_mask == 0 || (action_mask & (~0x7UL))) {\n-\t\tprintf(\" Policer action mask not correct (error)\\n\");\n-\t\treturn;\n-\t}\n-\n-\t/* Allocate memory for policer actions */\n-\tactions = (enum rte_mtr_policer_action *)malloc(RTE_COLORS *\n-\t\tsizeof(enum rte_mtr_policer_action));\n-\tif (actions == NULL) {\n-\t\tprintf(\"Memory for policer actions not allocated (error)\\n\");\n-\t\treturn;\n-\t}\n-\t/* Parse policer action string */\n-\tret = parse_policer_action_string(p_str, action_mask, actions);\n-\tif (ret) {\n-\t\tprintf(\" Policer action string parse error\\n\");\n-\t\tfree(actions);\n-\t\treturn;\n-\t}\n-\n-\tret = rte_mtr_policer_actions_update(port_id, mtr_id,\n-\t\taction_mask, actions, &error);\n-\tif (ret != 0) {\n-\t\tfree(actions);\n-\t\tprint_err_msg(&error);\n-\t\treturn;\n-\t}\n-\n-\tfree(actions);\n-}\n-\n-cmdline_parse_inst_t cmd_set_port_meter_policer_action = {\n-\t.f = cmd_set_port_meter_policer_action_parsed,\n-\t.data = NULL,\n-\t.help_str = \"set port meter policer action <port_id> <mtr_id> \"\n-\t\t\"<action_mask> <action0> [<action1> <action2>]\",\n-\t.tokens = {\n-\t\t(void *)&cmd_set_port_meter_policer_action_set,\n-\t\t(void *)&cmd_set_port_meter_policer_action_port,\n-\t\t(void *)&cmd_set_port_meter_policer_action_meter,\n-\t\t(void *)&cmd_set_port_meter_policer_action_policer,\n-\t\t(void *)&cmd_set_port_meter_policer_action_action,\n-\t\t(void *)&cmd_set_port_meter_policer_action_port_id,\n-\t\t(void *)&cmd_set_port_meter_policer_action_mtr_id,\n-\t\t(void *)&cmd_set_port_meter_policer_action_action_mask,\n-\t\t(void *)&cmd_set_port_meter_policer_action_policer_action,\n-\t\tNULL,\n-\t},\n-};\n-\n /* *** Set Port Meter Stats Mask *** */\n struct cmd_set_port_meter_stats_mask_result {\n \tcmdline_fixed_string_t set;\ndiff --git a/app/test-pmd/cmdline_mtr.h b/app/test-pmd/cmdline_mtr.h\nindex e69d6da023..7e2713cea3 100644\n--- a/app/test-pmd/cmdline_mtr.h\n+++ b/app/test-pmd/cmdline_mtr.h\n@@ -17,7 +17,6 @@ extern cmdline_parse_inst_t cmd_disable_port_meter;\n extern cmdline_parse_inst_t cmd_del_port_meter;\n extern cmdline_parse_inst_t cmd_set_port_meter_profile;\n extern cmdline_parse_inst_t cmd_set_port_meter_dscp_table;\n-extern cmdline_parse_inst_t cmd_set_port_meter_policer_action;\n extern cmdline_parse_inst_t cmd_set_port_meter_stats_mask;\n extern cmdline_parse_inst_t cmd_show_port_meter_stats;\n \ndiff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst\nindex e1b93ecedf..2f5a6e0c31 100644\n--- a/doc/guides/prog_guide/rte_flow.rst\n+++ b/doc/guides/prog_guide/rte_flow.rst\n@@ -2841,6 +2841,27 @@ for ``RTE_FLOW_FIELD_VALUE`` and ``RTE_FLOW_FIELD_POINTER`` respectively.\n    | ``value``     | immediate value or a pointer to this value               |\n    +---------------+----------------------------------------------------------+\n \n+Action: ``METER_COLOR``\n+^^^^^^^^^^^^^^^^^^^^^^^\n+\n+Color the packet to reflect the meter color result.\n+\n+The meter action must be configured before meter color action.\n+Meter color action is set to a color to reflect the meter color result.\n+Set the meter color in the mbuf to the selected color.\n+The meter color action output color is the output color of the packet,\n+which is set in the packet meta-data (i.e. struct ``rte_mbuf::sched::color``)\n+\n+.. _table_rte_flow_action_meter_color:\n+\n+.. table:: METER_COLOR\n+\n+   +-----------------+--------------+\n+   | Field           | Value        |\n+   +=================+==============+\n+   | ``meter_color`` | Packet color |\n+   +-----------------+--------------+\n+\n Negative types\n ~~~~~~~~~~~~~~\n \ndiff --git a/doc/guides/prog_guide/traffic_metering_and_policing.rst b/doc/guides/prog_guide/traffic_metering_and_policing.rst\nindex 90c781eb1d..c0537e653c 100644\n--- a/doc/guides/prog_guide/traffic_metering_and_policing.rst\n+++ b/doc/guides/prog_guide/traffic_metering_and_policing.rst\n@@ -56,18 +56,10 @@ The processing done for each input packet hitting an MTR object is:\n   color blind mode, which is equivalent to considering all input packets\n   initially colored as green.\n \n-* Policing: There is a separate policer action configured for each meter\n-  output color, which can:\n-\n-  * Drop the packet.\n-\n-  * Keep the same packet color: the policer output color matches the meter\n-    output color (essentially a no-op action).\n-\n-  * Recolor the packet: the policer output color is set to a different color\n-    than the meter output color. The policer output color is the output color\n-    of the packet, which is set in the packet meta-data (i.e. struct\n-    ``rte_mbuf::sched::color``).\n+* There is a meter policy API to manage pre-defined policies for meter.\n+  Any rte_flow action list can be configured per color for each policy.\n+  A meter object configured with a policy executes the actions per packet\n+  according to the packet color.\n \n * Statistics: The set of counters maintained for each MTR object is\n   configurable and subject to the implementation support. This set includes\ndiff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst\nindex 82ee71152f..5a8eeb6446 100644\n--- a/doc/guides/rel_notes/release_21_05.rst\n+++ b/doc/guides/rel_notes/release_21_05.rst\n@@ -192,6 +192,27 @@ New Features\n   * Added command to dump internal representation information of single flow.\n     ``flow dump (port_id) rule (rule_id)``\n \n+  * deleted the port meter policer action command .\n+    ``set port meter policer action (port_id) (mtr_id) (action_mask) ...``\n+  * Added command to create meter policy.\n+    ``add port meter policy (port_id) (policy_id) g_actions {action} end y_actions {action} end r_actions {action} end``\n+  * Added command to delete meter policy.\n+    ``del port meter policy (port_id) (policy_id)``\n+\n+* **Updated meter API.**\n+\n+  * ethdev: Deleted meter policer API to support policy API.\n+    ``rte_mtr_policer_actions_update()``\n+  * ethdev: Added meter API to support pre-defined policy, rte_flow action list per color.\n+    ``rte_mtr_meter_policy_add()``, ``rte_mtr_meter_policy_delete()`` and\n+    ``rte_mtr_create_with_policy()``\n+  * ethdev: Removed rte_mtr_policer_action from rte_mtr_params structures.\n+  * ethdev: Added rte_mtr_meter_policy_params structures to support policy API.\n+  * ethdev: Added meter_policy_id into rte_mtr_params structures.\n+  * ethdev: Removed policer_action_recolor_supported and policer_action_drop_supported from rte_mtr_capabilities structures.\n+  * ethdev: Added meter_policy_n_max into rte_mtr_capabilities structures.\n+  * ethdev: Added RTE_FLOW_ACTION_TYPE_METER_COLOR in enum rte_flow_action_type.\n+  * ethdev: Added RTE_MTR_ERROR_TYPE_METER_POLICY_ID and RTE_MTR_ERROR_TYPE_METER_POLICY_ID into rte_mtr_error_type.\n \n Removed Items\n -------------\ndiff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst\nindex e3bfed566d..824d8bdf27 100644\n--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst\n+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst\n@@ -2833,24 +2833,6 @@ Set meter dscp table for the ethernet device::\n    testpmd> set port meter dscp table (port_id) (mtr_id) [(dscp_tbl_entry0) \\\n    (dscp_tbl_entry1)...(dscp_tbl_entry63)]\n \n-set port meter policer action\n-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n-\n-Set meter policer action for the ethernet device::\n-\n-   testpmd> set port meter policer action (port_id) (mtr_id) (action_mask) \\\n-   (action0) [(action1) (action1)]\n-\n-where:\n-\n-* ``action_mask``: Bit mask indicating which policer actions need to be\n-  updated. One or more policer actions can be updated in a single function\n-  invocation. To update the policer action associated with color C, bit\n-  (1 << C) needs to be set in *action_mask* and element at position C\n-  in the *actions* array needs to be valid.\n-* ``actionx``: Policer action for the color x,\n-  RTE_MTR_GREEN <= x < RTE_MTR_COLORS\n-\n set port meter stats mask\n ~~~~~~~~~~~~~~~~~~~~~~~~~\n \ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex 50e3b6de33..221e601fa9 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -584,14 +584,6 @@ struct mlx5_dev_shared_port {\n /* Modify this value if enum rte_mtr_color changes. */\n #define RTE_MTR_DROPPED RTE_COLORS\n \n-/* Meter policer statistics */\n-struct mlx5_flow_policer_stats {\n-\tuint32_t pass_cnt;\n-\t/**< Color counter for pass. */\n-\tuint32_t drop_cnt;\n-\t/**< Color counter for drop. */\n-};\n-\n /* Meter table structure. */\n struct mlx5_meter_domain_info {\n \tstruct mlx5_flow_tbl_resource *tbl;\n@@ -630,24 +622,12 @@ struct mlx5_meter_domains_infos {\n \n /* Meter parameter structure. */\n struct mlx5_flow_meter_info {\n-\tuint32_t meter_id;\n-\t/**< Meter id. */\n \tstruct mlx5_flow_meter_profile *profile;\n \t/**< Meter profile parameters. */\n \trte_spinlock_t sl; /**< Meter action spinlock. */\n-\t/** Policer actions (per meter output color). */\n-\tenum rte_mtr_policer_action action[RTE_COLORS];\n \t/** Set of stats counters to be enabled.\n \t * @see enum rte_mtr_stats_type\n \t */\n-\tuint32_t green_bytes:1;\n-\t/** Set green bytes stats to be enabled. */\n-\tuint32_t green_pkts:1;\n-\t/** Set green packets stats to be enabled. */\n-\tuint32_t red_bytes:1;\n-\t/** Set red bytes stats to be enabled. */\n-\tuint32_t red_pkts:1;\n-\t/** Set red packets stats to be enabled. */\n \tuint32_t bytes_dropped:1;\n \t/** Set bytes dropped stats to be enabled. */\n \tuint32_t pkts_dropped:1;\n@@ -682,8 +662,8 @@ struct mlx5_flow_meter_info {\n \tuint32_t transfer:1;\n \tstruct mlx5_meter_domains_infos *mfts;\n \t/**< Flow table created for this meter. */\n-\tstruct mlx5_flow_policer_stats policer_stats;\n-\t/**< Meter policer statistics. */\n+\tuint32_t drop_cnt;\n+\t/**< Color counter for drop. */\n \tuint32_t ref_cnt;\n \t/**< Use count. */\n \tstruct mlx5_indexed_pool *flow_ipool;\ndiff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex bd957e7b29..eed43a208b 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -6648,52 +6648,6 @@ mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,\n \treturn fops->destroy_mtr_tbls(dev, tbls);\n }\n \n-/**\n- * Prepare policer rules.\n- *\n- * @param[in] dev\n- *   Pointer to Ethernet device.\n- * @param[in] fm\n- *   Pointer to flow meter structure.\n- * @param[in] attr\n- *   Pointer to flow attributes.\n- *\n- * @return\n- *   0 on success, -1 otherwise.\n- */\n-int\n-mlx5_flow_prepare_policer_rules(struct rte_eth_dev *dev,\n-\t\t\t       struct mlx5_flow_meter_info *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->prepare_policer_rules(dev, fm, attr);\n-}\n-\n-/**\n- * Destroy policer rules.\n- *\n- * @param[in] fm\n- *   Pointer to flow meter structure.\n- * @param[in] attr\n- *   Pointer to flow attributes.\n- *\n- * @return\n- *   0 on success, -1 otherwise.\n- */\n-int\n-mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,\n-\t\t\t\tstruct mlx5_flow_meter_info *fm,\n-\t\t\t\tconst 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->destroy_policer_rules(dev, fm, attr);\n-}\n-\n /**\n  * Allocate the needed aso flow meter id.\n  *\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex cb2803d080..7fa15eef7b 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -839,6 +839,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 };\n \n@@ -1097,14 +1099,6 @@ 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_policer_rules_t)\n-\t\t\t\t\t(struct rte_eth_dev *dev,\n-\t\t\t\t\t struct mlx5_flow_meter_info *fm,\n-\t\t\t\t\t const struct rte_flow_attr *attr);\n-typedef int (*mlx5_flow_destroy_policer_rules_t)\n-\t\t\t\t\t(struct rte_eth_dev *dev,\n-\t\t\t\t\t const struct mlx5_flow_meter_info *fm,\n-\t\t\t\t\t const struct rte_flow_attr *attr);\n typedef uint32_t (*mlx5_flow_mtr_alloc_t)\n \t\t\t\t\t    (struct rte_eth_dev *dev);\n typedef void (*mlx5_flow_mtr_free_t)(struct rte_eth_dev *dev,\n@@ -1161,8 +1155,6 @@ 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 prepare_policer_rules;\n-\tmlx5_flow_destroy_policer_rules_t destroy_policer_rules;\n \tmlx5_flow_mtr_alloc_t create_meter;\n \tmlx5_flow_mtr_free_t free_meter;\n \tmlx5_flow_counter_alloc_t counter_alloc;\n@@ -1392,12 +1384,6 @@ 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_prepare_policer_rules(struct rte_eth_dev *dev,\n-\t\t\t\t   struct mlx5_flow_meter_info *fm,\n-\t\t\t\t   const struct rte_flow_attr *attr);\n-int mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,\n-\t\t\t\t    struct mlx5_flow_meter_info *fm,\n-\t\t\t\t    const struct rte_flow_attr *attr);\n int mlx5_flow_meter_flush(struct rte_eth_dev *dev,\n \t\t\t  struct rte_mtr_error *error);\n int mlx5_flow_dv_discover_counter_offset_support(struct rte_eth_dev *dev);\ndiff --git a/drivers/net/mlx5/mlx5_flow_aso.c b/drivers/net/mlx5/mlx5_flow_aso.c\nindex cd2cc016b9..62d2df054b 100644\n--- a/drivers/net/mlx5/mlx5_flow_aso.c\n+++ b/drivers/net/mlx5/mlx5_flow_aso.c\n@@ -808,8 +808,8 @@ mlx5_aso_meter_update_by_wqe(struct mlx5_dev_ctx_shared *sh,\n \t\t/* Waiting for wqe resource. */\n \t\trte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);\n \t} while (--poll_wqe_times);\n-\tDRV_LOG(ERR, \"Fail to send WQE for ASO meter %d\",\n-\t\t\tmtr->fm.meter_id);\n+\tDRV_LOG(ERR, \"Fail to send WQE for ASO meter offset %d\",\n+\t\t\tmtr->offset);\n \treturn -1;\n }\n \n@@ -844,7 +844,7 @@ mlx5_aso_mtr_wait(struct mlx5_dev_ctx_shared *sh,\n \t\t/* Waiting for CQE ready. */\n \t\trte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);\n \t} while (--poll_cqe_times);\n-\tDRV_LOG(ERR, \"Fail to poll CQE ready for ASO meter %d\",\n-\t\t\tmtr->fm.meter_id);\n+\tDRV_LOG(ERR, \"Fail to poll CQE ready for ASO meter offset %d\",\n+\t\t\tmtr->offset);\n \treturn -1;\n }\ndiff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c\nindex c558147969..e7e4d17a25 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -185,31 +185,6 @@ flow_dv_attr_init(const struct rte_flow_item *item, union flow_dv_attr *attr,\n \tattr->valid = 1;\n }\n \n-/**\n- * Convert rte_mtr_color to mlx5 color.\n- *\n- * @param[in] rcol\n- *   rte_mtr_color.\n- *\n- * @return\n- *   mlx5 color.\n- */\n-static int\n-rte_col_2_mlx5_col(enum rte_color rcol)\n-{\n-\tswitch (rcol) {\n-\tcase RTE_COLOR_GREEN:\n-\t\treturn MLX5_FLOW_COLOR_GREEN;\n-\tcase RTE_COLOR_YELLOW:\n-\t\treturn MLX5_FLOW_COLOR_YELLOW;\n-\tcase RTE_COLOR_RED:\n-\t\treturn MLX5_FLOW_COLOR_RED;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-\treturn MLX5_FLOW_COLOR_UNDEFINED;\n-}\n-\n struct field_modify_info {\n \tuint32_t size; /* Size of field in protocol header, in bytes. */\n \tuint32_t offset; /* Offset of field in protocol header, in bytes. */\n@@ -6026,12 +6001,10 @@ flow_dv_mtr_pool_create(struct rte_eth_dev *dev,\n \tmtrmng->n_valid++;\n \tfor (i = 1; i < MLX5_ASO_MTRS_PER_POOL; ++i) {\n \t\tpool->mtrs[i].offset = i;\n-\t\tpool->mtrs[i].fm.meter_id = UINT32_MAX;\n \t\tLIST_INSERT_HEAD(&mtrmng->meters,\n \t\t\t\t\t\t&pool->mtrs[i], next);\n \t}\n \tpool->mtrs[0].offset = 0;\n-\tpool->mtrs[0].fm.meter_id = UINT32_MAX;\n \t*mtr_free = &pool->mtrs[0];\n \treturn pool;\n }\n@@ -6055,7 +6028,6 @@ flow_dv_aso_mtr_release_to_pool(struct rte_eth_dev *dev, uint32_t mtr_idx)\n \trte_spinlock_lock(&mtrmng->mtrsl);\n \tmemset(&aso_mtr->fm, 0, sizeof(struct mlx5_flow_meter_info));\n \taso_mtr->state = ASO_METER_FREE;\n-\taso_mtr->fm.meter_id = UINT32_MAX;\n \tLIST_INSERT_HEAD(&mtrmng->meters, aso_mtr, next);\n \trte_spinlock_unlock(&mtrmng->mtrsl);\n }\n@@ -6095,8 +6067,8 @@ flow_dv_mtr_alloc(struct rte_eth_dev *dev)\n \tmtr_free->state = ASO_METER_WAIT;\n \trte_spinlock_unlock(&mtrmng->mtrsl);\n \tpool = container_of(mtr_free,\n-\t\t\t\t\tstruct mlx5_aso_mtr_pool,\n-\t\t\t\t\tmtrs[mtr_free->offset]);\n+\t\t\tstruct mlx5_aso_mtr_pool,\n+\t\t\tmtrs[mtr_free->offset]);\n \tmtr_idx = MLX5_MAKE_MTR_IDX(pool->index, mtr_free->offset);\n \tif (!mtr_free->fm.meter_action) {\n #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO\n@@ -13703,433 +13675,6 @@ flow_dv_create_mtr_tbl(struct rte_eth_dev *dev)\n \treturn NULL;\n }\n \n-/**\n- * Destroy the meter table matchers.\n- * Lock free, (mutex should be acquired by caller).\n- *\n- * @param[in] dev\n- *   Pointer to Ethernet device.\n- * @param[in,out] dtb\n- *   Pointer to DV meter table.\n- *\n- * @return\n- *   Always 0.\n- */\n-static int\n-flow_dv_destroy_mtr_matchers(struct rte_eth_dev *dev,\n-\t\t\t     struct mlx5_meter_domain_info *dtb)\n-{\n-\tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_flow_tbl_data_entry *tbl;\n-\n-\tif (!priv->config.dv_flow_en)\n-\t\treturn 0;\n-\tif (dtb->drop_matcher) {\n-\t\ttbl = container_of(dtb->drop_matcher->tbl, typeof(*tbl), tbl);\n-\t\tmlx5_cache_unregister(&tbl->matchers,\n-\t\t\t\t      &dtb->drop_matcher->entry);\n-\t\tdtb->drop_matcher = NULL;\n-\t}\n-\tif (dtb->color_matcher) {\n-\t\ttbl = container_of(dtb->color_matcher->tbl, typeof(*tbl), tbl);\n-\t\tmlx5_cache_unregister(&tbl->matchers,\n-\t\t\t\t      &dtb->color_matcher->entry);\n-\t\tdtb->color_matcher = NULL;\n-\t}\n-\treturn 0;\n-}\n-\n-/**\n- * Create the matchers for meter table.\n- *\n- * @param[in] dev\n- *   Pointer to Ethernet device.\n- * @param[in] color_reg_c_idx\n- *   Reg C index for color match.\n- * @param[in] mtr_id_reg_c_idx\n- *   Reg C index for meter_id match.\n- * @param[in] mtr_id_mask\n- *   Mask for meter_id match criteria.\n- * @param[in,out] dtb\n- *   Pointer to DV meter table.\n- * @param[out] error\n- *   Perform verbose error reporting if not NULL.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-flow_dv_prepare_mtr_matchers(struct rte_eth_dev *dev,\n-\t\t\t     uint32_t color_reg_c_idx,\n-\t\t\t     uint32_t mtr_id_reg_c_idx,\n-\t\t\t     uint32_t mtr_id_mask,\n-\t\t\t     struct mlx5_meter_domain_info *dtb,\n-\t\t\t     struct rte_flow_error *error)\n-{\n-\tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_flow_tbl_data_entry *tbl_data;\n-\tstruct mlx5_cache_entry *entry;\n-\tstruct mlx5_flow_dv_matcher matcher = {\n-\t\t.mask = {\n-\t\t\t.size = sizeof(matcher.mask.buf) -\n-\t\t\t\tMLX5_ST_SZ_BYTES(fte_match_set_misc4),\n-\t\t},\n-\t\t.tbl = dtb->tbl,\n-\t};\n-\tstruct mlx5_flow_dv_match_params value = {\n-\t\t.size = sizeof(value.buf) -\n-\t\t\tMLX5_ST_SZ_BYTES(fte_match_set_misc4),\n-\t};\n-\tstruct mlx5_flow_cb_ctx ctx = {\n-\t\t.error = error,\n-\t\t.data = &matcher,\n-\t};\n-\tuint32_t color_mask = (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;\n-\n-\ttbl_data = container_of(dtb->tbl, struct mlx5_flow_tbl_data_entry, tbl);\n-\tif (!dtb->drop_matcher) {\n-\t\t/* Create matchers for Drop. */\n-\t\tflow_dv_match_meta_reg(matcher.mask.buf, value.buf,\n-\t\t\t\t       mtr_id_reg_c_idx, 0, mtr_id_mask);\n-\t\tmatcher.priority = MLX5_REG_BITS * 2 - priv->max_mtr_bits;\n-\t\tmatcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,\n-\t\t\t\t\tmatcher.mask.size);\n-\t\tentry = mlx5_cache_register(&tbl_data->matchers, &ctx);\n-\t\tif (!entry) {\n-\t\t\tDRV_LOG(ERR, \"Failed to register meter drop matcher.\");\n-\t\t\treturn -1;\n-\t\t}\n-\t\tdtb->drop_matcher =\n-\t\t\tcontainer_of(entry, struct mlx5_flow_dv_matcher, entry);\n-\t}\n-\tif (!dtb->color_matcher) {\n-\t\t/* Create matchers for Color + meter_id. */\n-\t\tif (priv->mtr_reg_share) {\n-\t\t\tflow_dv_match_meta_reg(matcher.mask.buf, value.buf,\n-\t\t\t\t\tcolor_reg_c_idx, 0,\n-\t\t\t\t\t(mtr_id_mask | color_mask));\n-\t\t} else {\n-\t\t\tflow_dv_match_meta_reg(matcher.mask.buf, value.buf,\n-\t\t\t\t\tcolor_reg_c_idx, 0, color_mask);\n-\t\t\tflow_dv_match_meta_reg(matcher.mask.buf, value.buf,\n-\t\t\t\t\tmtr_id_reg_c_idx, 0, mtr_id_mask);\n-\t\t}\n-\t\tmatcher.priority = MLX5_REG_BITS - priv->max_mtr_bits;\n-\t\tmatcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,\n-\t\t\t\t\tmatcher.mask.size);\n-\t\tentry = mlx5_cache_register(&tbl_data->matchers, &ctx);\n-\t\tif (!entry) {\n-\t\t\tDRV_LOG(ERR, \"Failed to register meter color matcher.\");\n-\t\t\treturn -1;\n-\t\t}\n-\t\tdtb->color_matcher =\n-\t\t\tcontainer_of(entry, struct mlx5_flow_dv_matcher, entry);\n-\t}\n-\treturn 0;\n-}\n-\n-/**\n- * Destroy domain policer rule.\n- *\n- * @param[in] dev\n- *   Pointer to Ethernet device.\n- * @param[in] dt\n- *   Pointer to domain table.\n- */\n-static void\n-flow_dv_destroy_domain_policer_rule(struct rte_eth_dev *dev,\n-\t\t\t\t    struct mlx5_meter_domain_info *dt)\n-{\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-\t}\n-}\n-\n-/**\n- * Destroy policer rules.\n- *\n- * @param[in] dev\n- *   Pointer to Ethernet device.\n- * @param[in] fm\n- *   Pointer to flow meter structure.\n- * @param[in] attr\n- *   Pointer to flow attributes.\n- *\n- * @return\n- *   Always 0.\n- */\n-static int\n-flow_dv_destroy_policer_rules(struct rte_eth_dev *dev,\n-\t\t\t      const struct mlx5_flow_meter_info *fm,\n-\t\t\t      const struct rte_flow_attr *attr)\n-{\n-\tstruct mlx5_meter_domains_infos *mtb = fm ? fm->mfts : NULL;\n-\n-\tif (!mtb)\n-\t\treturn 0;\n-\tif (attr->egress)\n-\t\tflow_dv_destroy_domain_policer_rule(dev, &mtb->egress);\n-\tif (attr->ingress)\n-\t\tflow_dv_destroy_domain_policer_rule(dev, &mtb->ingress);\n-\tif (attr->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] mtr_idx\n- *   meter index.\n- * @param[in] mtb\n- *   Pointer to DV meter table set.\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 rte_eth_dev *dev,\n-\t\t\t\t    struct mlx5_flow_meter_info *fm,\n-\t\t\t\t    uint32_t mtr_idx,\n-\t\t\t\t    struct mlx5_meter_domain_info *dtb,\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\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\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-\n-\t/* Create jump action. */\n-\tif (!dtb->jump_actn)\n-\t\tret = mlx5_flow_os_create_flow_action_dest_flow_tbl\n-\t\t\t\t(dtb->sfx_tbl->obj, &dtb->jump_actn);\n-\tif (ret) {\n-\t\tDRV_LOG(ERR, \"Failed to create policer jump action.\");\n-\t\tgoto error;\n-\t}\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 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       (mtr_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       ((mtr_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       mtr_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-\treturn -1;\n-}\n-\n-/**\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- * @param[in] fm\n- *   Pointer to flow meter structure.\n- * @param[in] attr\n- *   Pointer to flow attributes.\n- *\n- * @return\n- *   0 on success, -1 otherwise.\n- */\n-static int\n-flow_dv_prepare_policer_rules(struct rte_eth_dev *dev,\n-\t\t\t      struct mlx5_flow_meter_info *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-\tuint32_t mtr_idx;\n-\tint ret;\n-\n-\t/* Get the statistics counters for green/drop. */\n-\tif (fm->policer_stats.pass_cnt) {\n-\t\tcnt = flow_dv_counter_get_by_idx(dev,\n-\t\t\t\t\tfm->policer_stats.pass_cnt,\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.drop_cnt) {\n-\t\tcnt = flow_dv_counter_get_by_idx(dev,\n-\t\t\t\t\tfm->policer_stats.drop_cnt,\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 (priv->sh->meter_aso_en) {\n-\t\tstruct mlx5_aso_mtr *aso_mtr = NULL;\n-\t\tstruct mlx5_aso_mtr_pool *pool;\n-\n-\t\taso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);\n-\t\tpool = container_of(aso_mtr, struct mlx5_aso_mtr_pool,\n-\t\t\t\t    mtrs[aso_mtr->offset]);\n-\t\tmtr_idx = MLX5_MAKE_MTR_IDX(pool->index, aso_mtr->offset);\n-\t} else {\n-\t\tstruct mlx5_legacy_flow_meter *legacy_fm;\n-\n-\t\tlegacy_fm = container_of(fm, struct mlx5_legacy_flow_meter, fm);\n-\t\tmtr_idx = legacy_fm->idx;\n-\t}\n-\tif (attr->egress) {\n-\t\tret = flow_dv_create_policer_forward_rule(dev,\n-\t\t\t\tfm, mtr_idx, &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(dev,\n-\t\t\t\tfm, mtr_idx, &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(dev,\n-\t\t\t\tfm, mtr_idx, &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-\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 /**\n  * Validate the batch counter support in root table.\n  *\n@@ -14424,8 +13969,6 @@ const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {\n \t.query = flow_dv_query,\n \t.create_mtr_tbls = flow_dv_create_mtr_tbl,\n \t.destroy_mtr_tbls = flow_dv_destroy_mtr_tbl,\n-\t.prepare_policer_rules = flow_dv_prepare_policer_rules,\n-\t.destroy_policer_rules = flow_dv_destroy_policer_rules,\n \t.create_meter = flow_dv_mtr_alloc,\n \t.free_meter = flow_dv_aso_mtr_release_to_pool,\n \t.counter_alloc = flow_dv_counter_allocate,\ndiff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c\nindex 714b382d55..af0a1c18cb 100644\n--- a/drivers/net/mlx5/mlx5_flow_meter.c\n+++ b/drivers/net/mlx5/mlx5_flow_meter.c\n@@ -329,7 +329,6 @@ mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,\n \tcap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */\n \tcap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap->n_max : 0;\n \tcap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */\n-\tcap->policer_action_drop_supported = 1;\n \tcap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED |\n \t\t\t  RTE_MTR_STATS_N_PKTS_DROPPED;\n \treturn 0;\n@@ -436,90 +435,6 @@ mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,\n \treturn 0;\n }\n \n-/**\n- * Convert wrong color setting action to verbose error.\n- *\n- * @param[in] action\n- *   Policy color action.\n- *\n- * @return\n- *   Verbose meter color error type.\n- */\n-static inline enum rte_mtr_error_type\n-action2error(enum rte_mtr_policer_action action)\n-{\n-\tswitch (action) {\n-\tcase MTR_POLICER_ACTION_COLOR_GREEN:\n-\t\treturn RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN;\n-\tcase MTR_POLICER_ACTION_COLOR_YELLOW:\n-\t\treturn RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW;\n-\tcase MTR_POLICER_ACTION_COLOR_RED:\n-\t\treturn RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-\treturn RTE_MTR_ERROR_TYPE_UNSPECIFIED;\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-\t/* Validate policer settings. */\n-\tif (params->action[RTE_COLOR_RED] != MTR_POLICER_ACTION_DROP)\n-\t\treturn -rte_mtr_error_set\n-\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t action2error(params->action[RTE_COLOR_RED]),\n-\t\t\t\t NULL,\n-\t\t\t\t \"Red color only supports drop action.\");\n-\tif (params->action[RTE_COLOR_GREEN] != MTR_POLICER_ACTION_COLOR_GREEN)\n-\t\treturn -rte_mtr_error_set\n-\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t action2error(params->action[RTE_COLOR_GREEN]),\n-\t\t\t\t NULL,\n-\t\t\t\t \"Green color only supports recolor green action.\");\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\t\t\t  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,\n-\t\t\t\t\t  \"Meter object already exists.\");\n-\treturn 0;\n-}\n-\n /**\n  * Modify the flow meter action.\n  *\n@@ -629,167 +544,14 @@ static void\n mlx5_flow_meter_stats_enable_update(struct mlx5_flow_meter_info *fm,\n \t\t\t\tuint64_t stats_mask)\n {\n-\tfm->green_bytes = (stats_mask & RTE_MTR_STATS_N_BYTES_GREEN) ? 1 : 0;\n-\tfm->green_pkts = (stats_mask & RTE_MTR_STATS_N_PKTS_GREEN) ? 1 : 0;\n-\tfm->red_bytes = (stats_mask & RTE_MTR_STATS_N_BYTES_RED) ? 1 : 0;\n-\tfm->red_pkts = (stats_mask & RTE_MTR_STATS_N_PKTS_RED) ? 1 : 0;\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 }\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_legacy_flow_meter *legacy_fm;\n-\tstruct mlx5_flow_meter_info *fm;\n-\tconst struct rte_flow_attr attr = {\n-\t\t\t\t.ingress = 1,\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-\tstruct mlx5_aso_mtr *aso_mtr;\n-\tunion mlx5_l3t_data data;\n-\tuint32_t mtr_idx;\n-\tint ret;\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\t  RTE_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\t\t\t  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,\n-\t\t\t\t\t  NULL, \"Meter profile id not valid.\");\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->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-\t/* Fill the flow meter parameters. */\n-\tfm->meter_id = meter_id;\n-\tfm->profile = fmp;\n-\tmemcpy(fm->action, params->action, sizeof(params->action));\n-\tmlx5_flow_meter_stats_enable_update(fm, params->stats_mask);\n-\t/* Alloc policer counters. */\n-\tif (fm->green_bytes || fm->green_pkts) {\n-\t\tfm->policer_stats.pass_cnt = mlx5_counter_alloc(dev);\n-\t\tif (!fm->policer_stats.pass_cnt)\n-\t\t\tgoto error;\n-\t}\n-\tif (fm->red_bytes || fm->red_pkts ||\n-\t    fm->bytes_dropped || fm->pkts_dropped) {\n-\t\tfm->policer_stats.drop_cnt = mlx5_counter_alloc(dev);\n-\t\tif (!fm->policer_stats.drop_cnt)\n-\t\t\tgoto error;\n-\t}\n-\tfm->mfts = mlx5_flow_create_mtr_tbls(dev);\n-\tif (!fm->mfts)\n-\t\tgoto error;\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-\tif (!priv->sh->meter_aso_en)\n-\t\tTAILQ_INSERT_TAIL(fms, legacy_fm, next);\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-\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-\t/* If ASO meter supported, allocate ASO flow meter. */\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\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-\treturn 0;\n-error:\n-\tmlx5_flow_destroy_policer_rules(dev, fm, &attr);\n-\tmlx5_flow_destroy_mtr_tbls(dev, fm->mfts);\n-\t/* Free policer counters. */\n-\tif (fm->policer_stats.pass_cnt)\n-\t\tmlx5_counter_free(dev, fm->policer_stats.pass_cnt);\n-\tif (fm->policer_stats.drop_cnt)\n-\t\tmlx5_counter_free(dev, fm->policer_stats.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, -ret,\n-\t\t\t\t  RTE_MTR_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t  NULL, \"Failed to create devx meter.\");\n-}\n-\n static int\n mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,\n \t\t\tstruct mlx5_flow_meter_info *fm,\n-\t\t\tconst struct rte_flow_attr *attr,\n \t\t\tuint32_t mtr_idx)\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n@@ -810,15 +572,12 @@ mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,\n \t\tlegacy_fm = container_of(fm, struct mlx5_legacy_flow_meter, fm);\n \t\tTAILQ_REMOVE(fms, legacy_fm, next);\n \t}\n-\t/* Free policer counters. */\n-\tif (fm->policer_stats.pass_cnt)\n-\t\tmlx5_counter_free(dev, fm->policer_stats.pass_cnt);\n-\tif (fm->policer_stats.drop_cnt)\n-\t\tmlx5_counter_free(dev, fm->policer_stats.drop_cnt);\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 \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 \tif (priv->sh->meter_aso_en)\n \t\tmlx5_flow_mtr_free(dev, mtr_idx);\n@@ -847,11 +606,6 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_flow_meter_info *fm;\n-\tconst struct rte_flow_attr attr = {\n-\t\t\t\t.ingress = 1,\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 \tuint32_t mtr_idx = 0;\n \n \tif (!priv->mtr_en)\n@@ -876,7 +630,7 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,\n \t\t\t\t\"Fail to delete ASO Meter in index table.\");\n \t}\n \t/* Destroy the meter profile. */\n-\tif (mlx5_flow_meter_params_flush(dev, fm, &attr, mtr_idx))\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@@ -1102,13 +856,6 @@ mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_flow_meter_info *fm;\n-\tconst struct rte_flow_attr attr = {\n-\t\t\t\t.ingress = 1,\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-\tbool need_updated = false;\n-\tstruct mlx5_flow_policer_stats old_policer_stats;\n \n \tif (!priv->mtr_en)\n \t\treturn -rte_mtr_error_set(error, ENOTSUP,\n@@ -1120,69 +867,6 @@ 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-\told_policer_stats.pass_cnt = 0;\n-\told_policer_stats.drop_cnt = 0;\n-\tif (!!((RTE_MTR_STATS_N_PKTS_GREEN |\n-\t\t\t\tRTE_MTR_STATS_N_BYTES_GREEN) & stats_mask) !=\n-\t\t!!fm->policer_stats.pass_cnt) {\n-\t\tneed_updated = true;\n-\t\tif (fm->policer_stats.pass_cnt) {\n-\t\t\told_policer_stats.pass_cnt = fm->policer_stats.pass_cnt;\n-\t\t\tfm->policer_stats.pass_cnt = 0;\n-\t\t} else {\n-\t\t\tfm->policer_stats.pass_cnt =\n-\t\t\t\tmlx5_counter_alloc(dev);\n-\t\t\tif (!fm->policer_stats.pass_cnt)\n-\t\t\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  \"Counter alloc failed for meter.\");\n-\t\t}\n-\t}\n-\tif (!!((RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_BYTES_RED |\n-\t\tRTE_MTR_STATS_N_PKTS_DROPPED | RTE_MTR_STATS_N_BYTES_DROPPED) &\n-\t\tstats_mask) !=\n-\t\t!!fm->policer_stats.drop_cnt) {\n-\t\tneed_updated = true;\n-\t\tif (fm->policer_stats.drop_cnt) {\n-\t\t\told_policer_stats.drop_cnt = fm->policer_stats.drop_cnt;\n-\t\t\tfm->policer_stats.drop_cnt = 0;\n-\t\t} else {\n-\t\t\tfm->policer_stats.drop_cnt =\n-\t\t\t\tmlx5_counter_alloc(dev);\n-\t\t\tif (!fm->policer_stats.drop_cnt)\n-\t\t\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  \"Counter alloc failed for meter.\");\n-\t\t}\n-\t}\n-\tif (need_updated) {\n-\t\tif (mlx5_flow_prepare_policer_rules(dev, fm, &attr)) {\n-\t\t\tif (fm->policer_stats.pass_cnt &&\n-\t\t\t\tfm->policer_stats.pass_cnt !=\n-\t\t\t\told_policer_stats.pass_cnt)\n-\t\t\t\tmlx5_counter_free(dev,\n-\t\t\t\t\tfm->policer_stats.pass_cnt);\n-\t\t\tfm->policer_stats.pass_cnt =\n-\t\t\t\t\told_policer_stats.pass_cnt;\n-\t\t\tif (fm->policer_stats.drop_cnt &&\n-\t\t\t\tfm->policer_stats.drop_cnt !=\n-\t\t\t\told_policer_stats.drop_cnt)\n-\t\t\t\tmlx5_counter_free(dev,\n-\t\t\t\t\tfm->policer_stats.drop_cnt);\n-\t\t\tfm->policer_stats.pass_cnt =\n-\t\t\t\t\told_policer_stats.pass_cnt;\n-\t\t\treturn -rte_mtr_error_set(error, ENOTSUP,\n-\t\t\t\tRTE_MTR_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\tNULL, \"Failed to create meter policer rules.\");\n-\t\t}\n-\t\t/* Free old policer counters. */\n-\t\tif (old_policer_stats.pass_cnt)\n-\t\t\tmlx5_counter_free(dev,\n-\t\t\t\told_policer_stats.pass_cnt);\n-\t\tif (old_policer_stats.drop_cnt)\n-\t\t\tmlx5_counter_free(dev,\n-\t\t\t\told_policer_stats.drop_cnt);\n-\t}\n \tmlx5_flow_meter_stats_enable_update(fm, stats_mask);\n \treturn 0;\n }\n@@ -1216,7 +900,6 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,\n {\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tstruct mlx5_flow_meter_info *fm;\n-\tstruct mlx5_flow_policer_stats *ps;\n \tuint64_t pkts;\n \tuint64_t bytes;\n \tint ret = 0;\n@@ -1231,35 +914,14 @@ mlx5_flow_meter_stats_read(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-\tps = &fm->policer_stats;\n \t*stats_mask = 0;\n-\tif (fm->green_bytes)\n-\t\t*stats_mask |= RTE_MTR_STATS_N_BYTES_GREEN;\n-\tif (fm->green_pkts)\n-\t\t*stats_mask |= RTE_MTR_STATS_N_PKTS_GREEN;\n-\tif (fm->red_bytes)\n-\t\t*stats_mask |= RTE_MTR_STATS_N_BYTES_RED;\n-\tif (fm->red_pkts)\n-\t\t*stats_mask |= RTE_MTR_STATS_N_PKTS_RED;\n \tif (fm->bytes_dropped)\n \t\t*stats_mask |= RTE_MTR_STATS_N_BYTES_DROPPED;\n \tif (fm->pkts_dropped)\n \t\t*stats_mask |= RTE_MTR_STATS_N_PKTS_DROPPED;\n \tmemset(stats, 0, sizeof(*stats));\n-\tif (ps->pass_cnt) {\n-\t\tret = mlx5_counter_query(dev, ps->pass_cnt, clear, &pkts,\n-\t\t\t\t\t\t &bytes);\n-\t\tif (ret)\n-\t\t\tgoto error;\n-\t\t/* If need to read the packets, set it. */\n-\t\tif (fm->green_pkts)\n-\t\t\tstats->n_pkts[RTE_COLOR_GREEN] = pkts;\n-\t\t/* If need to read the bytes, set it. */\n-\t\tif (fm->green_bytes)\n-\t\t\tstats->n_bytes[RTE_COLOR_GREEN] = bytes;\n-\t}\n-\tif (ps->drop_cnt) {\n-\t\tret = mlx5_counter_query(dev, ps->drop_cnt, clear, &pkts,\n+\tif (fm->drop_cnt) {\n+\t\tret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts,\n \t\t\t\t\t\t &bytes);\n \t\tif (ret)\n \t\t\tgoto error;\n@@ -1273,20 +935,18 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,\n \treturn 0;\n error:\n \treturn -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,\n-\t\t\t\t \"Failed to read policer counters.\");\n+\t\t\t\t \"Failed to read meter drop counters.\");\n }\n \n static const struct rte_mtr_ops mlx5_flow_mtr_ops = {\n \t.capabilities_get = mlx5_flow_mtr_cap_get,\n \t.meter_profile_add = mlx5_flow_meter_profile_add,\n \t.meter_profile_delete = mlx5_flow_meter_profile_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 \t.meter_profile_update = mlx5_flow_meter_profile_update,\n \t.meter_dscp_table_update = NULL,\n-\t.policer_actions_update = NULL,\n \t.stats_update = mlx5_flow_meter_stats_update,\n \t.stats_read = mlx5_flow_meter_stats_read,\n };\n@@ -1344,12 +1004,11 @@ mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,\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\tMLX5_ASSERT(meter_id == aso_mtr->fm.meter_id);\n \t\trte_spinlock_unlock(&mtrmng->mtrsl);\n \t\treturn &aso_mtr->fm;\n \t}\n \tTAILQ_FOREACH(legacy_fm, fms, next)\n-\t\tif (meter_id == legacy_fm->fm.meter_id) {\n+\t\tif (meter_id == legacy_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@@ -1517,11 +1176,6 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)\n \tstruct mlx5_legacy_flow_meter *legacy_fm;\n \tstruct mlx5_flow_meter_info *fm;\n \tstruct mlx5_aso_mtr_pool *mtr_pool;\n-\tconst struct rte_flow_attr attr = {\n-\t\t\t\t.ingress = 1,\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 \tvoid *tmp;\n \tuint32_t i, offset, mtr_idx;\n \n@@ -1533,9 +1187,8 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)\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\tif (fm->meter_id != UINT32_MAX &&\n-\t\t\t\t\tmlx5_flow_meter_params_flush(dev,\n-\t\t\t\t\t\tfm, &attr, mtr_idx))\n+\t\t\t\tif (mlx5_flow_meter_params_flush(dev,\n+\t\t\t\t\t\tfm, mtr_idx))\n \t\t\t\t\treturn -rte_mtr_error_set\n \t\t\t\t\t(error, EINVAL,\n \t\t\t\t\tRTE_MTR_ERROR_TYPE_METER_PROFILE_ID,\n@@ -1545,7 +1198,7 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)\n \t} else {\n \t\tTAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) {\n \t\t\tfm = &legacy_fm->fm;\n-\t\t\tif (mlx5_flow_meter_params_flush(dev, fm, &attr, 0))\n+\t\t\tif (mlx5_flow_meter_params_flush(dev, fm, 0))\n \t\t\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.\");\ndiff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c\nindex 7925bad1c0..27eaf380cd 100644\n--- a/drivers/net/softnic/rte_eth_softnic_flow.c\n+++ b/drivers/net/softnic/rte_eth_softnic_flow.c\n@@ -1166,6 +1166,7 @@ flow_rule_action_get(struct pmd_internals *softnic,\n {\n \tstruct softnic_table_action_profile *profile;\n \tstruct softnic_table_action_profile_params *params;\n+\tstruct softnic_mtr_meter_policy *policy;\n \tint n_jump_queue_rss_drop = 0;\n \tint n_count = 0;\n \tint n_mark = 0;\n@@ -1621,15 +1622,25 @@ flow_rule_action_get(struct pmd_internals *softnic,\n \t\t\t\t\treturn -1;\n \t\t\t\t}\n \t\t\t}\n-\n+\t\t\t/* Meter policy must exist */\n+\t\t\tpolicy = softnic_mtr_meter_policy_find(softnic,\n+\t\t\t\t\tm->params.meter_policy_id);\n+\t\t\tif (policy == NULL) {\n+\t\t\t\trte_flow_error_set(error,\n+\t\t\t\t\t\tEINVAL,\n+\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t\t\tNULL,\n+\t\t\t\t\t\t\"METER: fail to find meter policy\");\n+\t\t\t\treturn -1;\n+\t\t\t}\n \t\t\t/* RTE_TABLE_ACTION_METER */\n \t\t\trule_action->mtr.mtr[0].meter_profile_id = meter_profile_id;\n \t\t\trule_action->mtr.mtr[0].policer[RTE_COLOR_GREEN] =\n-\t\t\t\tsoftnic_table_action_policer(m->params.action[RTE_COLOR_GREEN]);\n+\t\t\t\tpolicy->policer[RTE_COLOR_GREEN];\n \t\t\trule_action->mtr.mtr[0].policer[RTE_COLOR_YELLOW] =\n-\t\t\t\tsoftnic_table_action_policer(m->params.action[RTE_COLOR_YELLOW]);\n+\t\t\t\tpolicy->policer[RTE_COLOR_YELLOW];\n \t\t\trule_action->mtr.mtr[0].policer[RTE_COLOR_RED] =\n-\t\t\t\tsoftnic_table_action_policer(m->params.action[RTE_COLOR_RED]);\n+\t\t\t\tpolicy->policer[RTE_COLOR_RED];\n \t\t\trule_action->mtr.tc_mask = 1;\n \t\t\trule_action->action_mask |= 1 << RTE_TABLE_ACTION_MTR;\n \t\t\tbreak;\ndiff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h\nindex faf90a5a8c..1b3186ef0b 100644\n--- a/drivers/net/softnic/rte_eth_softnic_internals.h\n+++ b/drivers/net/softnic/rte_eth_softnic_internals.h\n@@ -83,6 +83,16 @@ struct softnic_mtr_meter_profile {\n \n TAILQ_HEAD(softnic_mtr_meter_profile_list, softnic_mtr_meter_profile);\n \n+/* MTR meter policy */\n+struct softnic_mtr_meter_policy {\n+\tTAILQ_ENTRY(softnic_mtr_meter_policy) node;\n+\tuint32_t meter_policy_id;\n+\tenum rte_table_action_policer policer[RTE_COLORS];\n+\tuint32_t n_users;\n+};\n+\n+TAILQ_HEAD(softnic_mtr_meter_policy_list, softnic_mtr_meter_policy);\n+\n /* MTR meter object */\n struct softnic_mtr {\n \tTAILQ_ENTRY(softnic_mtr) node;\n@@ -95,6 +105,7 @@ TAILQ_HEAD(softnic_mtr_list, softnic_mtr);\n \n struct mtr_internals {\n \tstruct softnic_mtr_meter_profile_list meter_profiles;\n+\tstruct softnic_mtr_meter_policy_list meter_policies;\n \tstruct softnic_mtr_list mtrs;\n };\n \n@@ -678,6 +689,10 @@ struct softnic_mtr_meter_profile *\n softnic_mtr_meter_profile_find(struct pmd_internals *p,\n \tuint32_t meter_profile_id);\n \n+struct softnic_mtr_meter_policy *\n+softnic_mtr_meter_policy_find(struct pmd_internals *p,\n+\tuint32_t meter_policy_id);\n+\n extern const struct rte_mtr_ops pmd_mtr_ops;\n \n /**\n@@ -841,9 +856,6 @@ softnic_table_action_profile_create(struct pmd_internals *p,\n \tconst char *name,\n \tstruct softnic_table_action_profile_params *params);\n \n-enum rte_table_action_policer\n-softnic_table_action_policer(enum rte_mtr_policer_action action);\n-\n /**\n  * Pipeline\n  */\ndiff --git a/drivers/net/softnic/rte_eth_softnic_meter.c b/drivers/net/softnic/rte_eth_softnic_meter.c\nindex b27b1285e9..f4e0640621 100644\n--- a/drivers/net/softnic/rte_eth_softnic_meter.c\n+++ b/drivers/net/softnic/rte_eth_softnic_meter.c\n@@ -65,27 +65,6 @@ softnic_mtr_meter_profile_find(struct pmd_internals *p,\n \treturn NULL;\n }\n \n-enum rte_table_action_policer\n-softnic_table_action_policer(enum rte_mtr_policer_action action)\n-{\n-\tswitch (action) {\n-\tcase MTR_POLICER_ACTION_COLOR_GREEN:\n-\t\treturn RTE_TABLE_ACTION_POLICER_COLOR_GREEN;\n-\n-\t\t/* FALLTHROUGH */\n-\tcase MTR_POLICER_ACTION_COLOR_YELLOW:\n-\t\treturn RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;\n-\n-\t\t/* FALLTHROUGH */\n-\tcase MTR_POLICER_ACTION_COLOR_RED:\n-\t\treturn RTE_TABLE_ACTION_POLICER_COLOR_RED;\n-\n-\t\t/* FALLTHROUGH */\n-\tdefault:\n-\t\treturn RTE_TABLE_ACTION_POLICER_DROP;\n-\t}\n-}\n-\n static int\n meter_profile_check(struct rte_eth_dev *dev,\n \tuint32_t meter_profile_id,\n@@ -208,6 +187,153 @@ pmd_mtr_meter_profile_delete(struct rte_eth_dev *dev,\n \treturn 0;\n }\n \n+struct softnic_mtr_meter_policy *\n+softnic_mtr_meter_policy_find(struct pmd_internals *p,\n+\tuint32_t meter_policy_id)\n+{\n+\tstruct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;\n+\tstruct softnic_mtr_meter_policy *mp;\n+\n+\tTAILQ_FOREACH(mp, mpl, node)\n+\t\tif (meter_policy_id == mp->meter_policy_id)\n+\t\t\treturn mp;\n+\n+\treturn NULL;\n+}\n+\n+/* MTR meter policy add */\n+static int\n+pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,\n+\tuint32_t meter_policy_id,\n+\tstruct rte_mtr_meter_policy_params *policy,\n+\tstruct rte_mtr_error *error)\n+{\n+\tstruct pmd_internals *p = dev->data->dev_private;\n+\tstruct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;\n+\tstruct softnic_mtr_meter_policy *mp;\n+\tconst struct rte_flow_action *act;\n+\tconst struct rte_flow_action_meter_color *recolor;\n+\tuint32_t i;\n+\tbool valid_act_found;\n+\n+\tif (policy == NULL)\n+\t\treturn -rte_mtr_error_set(error,\n+\t\t\tEINVAL,\n+\t\t\tRTE_MTR_ERROR_TYPE_METER_POLICY,\n+\t\t\tNULL,\n+\t\t\t\"Null meter policy invalid\");\n+\n+\t/* Meter policy must not exist. */\n+\tmp = softnic_mtr_meter_policy_find(p, meter_policy_id);\n+\tif (mp != NULL)\n+\t\treturn -rte_mtr_error_set(error,\n+\t\t\tEINVAL,\n+\t\t\tRTE_MTR_ERROR_TYPE_METER_POLICY_ID,\n+\t\t\tNULL,\n+\t\t\t\"Meter policy already exists\");\n+\n+\tfor (i = 0; i < RTE_COLORS; i++) {\n+\t\tif (policy->actions[i] == NULL)\n+\t\t\treturn -rte_mtr_error_set(error,\n+\t\t\t\tEINVAL,\n+\t\t\t\tRTE_MTR_ERROR_TYPE_METER_POLICY,\n+\t\t\t\tNULL,\n+\t\t\t\t\"Null action list\");\n+\t\tfor (act = policy->actions[i], valid_act_found = false;\n+\t\t\tact && act->type != RTE_FLOW_ACTION_TYPE_END;\n+\t\t\tact++) {\n+\t\t\t/*\n+\t\t\t * Support one (and one only) of\n+\t\t\t * METER_COLOR or DROP action.\n+\t\t\t */\n+\t\t\tif ((act->type != RTE_FLOW_ACTION_TYPE_METER_COLOR &&\n+\t\t\t\tact->type != RTE_FLOW_ACTION_TYPE_DROP) ||\n+\t\t\t\tvalid_act_found)\n+\t\t\t\treturn -rte_mtr_error_set(error,\n+\t\t\t\t\tEINVAL,\n+\t\t\t\t\tRTE_MTR_ERROR_TYPE_METER_POLICY,\n+\t\t\t\t\tNULL,\n+\t\t\t\t\t\"Action invalid\");\n+\t\t\tvalid_act_found = true;\n+\t\t}\n+\t}\n+\n+\t/* Memory allocation */\n+\tmp = calloc(1, sizeof(struct softnic_mtr_meter_policy));\n+\tif (mp == NULL)\n+\t\treturn -rte_mtr_error_set(error,\n+\t\t\tENOMEM,\n+\t\t\tRTE_MTR_ERROR_TYPE_UNSPECIFIED,\n+\t\t\tNULL,\n+\t\t\t\"Memory alloc failed\");\n+\n+\t/* Fill in */\n+\tmp->meter_policy_id = meter_policy_id;\n+\tfor (i = 0; i < RTE_COLORS; i++) {\n+\t\tmp->policer[i] = RTE_TABLE_ACTION_POLICER_DROP;\n+\t\tact = policy->actions[i];\n+\t\tif (!act)\n+\t\t\tcontinue;\n+\t\tif (act->type == RTE_FLOW_ACTION_TYPE_METER_COLOR) {\n+\t\t\trecolor = act->conf;\n+\t\t\tswitch (recolor->color) {\n+\t\t\tcase RTE_COLOR_GREEN:\n+\t\t\t\tmp->policer[i] =\n+\t\t\t\tRTE_TABLE_ACTION_POLICER_COLOR_GREEN;\n+\t\t\t\tbreak;\n+\t\t\tcase RTE_COLOR_YELLOW:\n+\t\t\t\tmp->policer[i] =\n+\t\t\t\tRTE_TABLE_ACTION_POLICER_COLOR_YELLOW;\n+\t\t\t\tbreak;\n+\t\t\tcase RTE_COLOR_RED:\n+\t\t\t\tmp->policer[i] =\n+\t\t\t\tRTE_TABLE_ACTION_POLICER_COLOR_RED;\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/* Add to list */\n+\tTAILQ_INSERT_TAIL(mpl, mp, node);\n+\n+\treturn 0;\n+}\n+\n+/* MTR meter policy delete */\n+static int\n+pmd_mtr_meter_policy_delete(struct rte_eth_dev *dev,\n+\tuint32_t meter_policy_id,\n+\tstruct rte_mtr_error *error)\n+{\n+\tstruct pmd_internals *p = dev->data->dev_private;\n+\tstruct softnic_mtr_meter_policy *mp;\n+\n+\t/* Meter policy must exist */\n+\tmp = softnic_mtr_meter_policy_find(p, meter_policy_id);\n+\tif (mp == NULL)\n+\t\treturn -rte_mtr_error_set(error,\n+\t\t\tEINVAL,\n+\t\t\tRTE_MTR_ERROR_TYPE_METER_POLICY_ID,\n+\t\t\tNULL,\n+\t\t\t\"Meter policy id invalid\");\n+\n+\t/* Check unused */\n+\tif (mp->n_users)\n+\t\treturn -rte_mtr_error_set(error,\n+\t\t\tEBUSY,\n+\t\t\tRTE_MTR_ERROR_TYPE_METER_POLICY_ID,\n+\t\t\tNULL,\n+\t\t\t\"Meter policy in use\");\n+\n+\t/* Remove from list */\n+\tTAILQ_REMOVE(&p->mtr.meter_policies, mp, node);\n+\tfree(mp);\n+\n+\treturn 0;\n+}\n+\n struct softnic_mtr *\n softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)\n {\n@@ -275,6 +401,7 @@ pmd_mtr_create(struct rte_eth_dev *dev,\n \tstruct pmd_internals *p = dev->data->dev_private;\n \tstruct softnic_mtr_list *ml = &p->mtr.mtrs;\n \tstruct softnic_mtr_meter_profile *mp;\n+\tstruct softnic_mtr_meter_policy *policy;\n \tstruct softnic_mtr *m;\n \tint status;\n \n@@ -292,6 +419,16 @@ pmd_mtr_create(struct rte_eth_dev *dev,\n \t\t\tNULL,\n \t\t\t\"Meter profile id not valid\");\n \n+\t/* Meter policy must exist */\n+\tpolicy = softnic_mtr_meter_policy_find(p, params->meter_policy_id);\n+\tif (policy == NULL) {\n+\t\treturn -rte_mtr_error_set(error,\n+\t\t\t\tEINVAL,\n+\t\t\t\tRTE_MTR_ERROR_TYPE_METER_POLICY_ID,\n+\t\t\t\tNULL,\n+\t\t\t\t\"Meter policy id invalid\");\n+\t}\n+\n \t/* Memory allocation */\n \tm = calloc(1, sizeof(struct softnic_mtr));\n \tif (m == NULL)\n@@ -310,6 +447,7 @@ pmd_mtr_create(struct rte_eth_dev *dev,\n \n \t/* Update dependencies */\n \tmp->n_users++;\n+\tpolicy->n_users++;\n \n \treturn 0;\n }\n@@ -324,6 +462,7 @@ pmd_mtr_destroy(struct rte_eth_dev *dev,\n \tstruct softnic_mtr_list *ml = &p->mtr.mtrs;\n \tstruct softnic_mtr_meter_profile *mp;\n \tstruct softnic_mtr *m;\n+\tstruct softnic_mtr_meter_policy *policy;\n \n \t/* MTR object must exist */\n \tm = softnic_mtr_find(p, mtr_id);\n@@ -351,8 +490,18 @@ pmd_mtr_destroy(struct rte_eth_dev *dev,\n \t\t\tNULL,\n \t\t\t\"MTR object meter profile invalid\");\n \n+\t/* Meter policy must exist */\n+\tpolicy = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);\n+\tif (policy == NULL)\n+\t\treturn -rte_mtr_error_set(error,\n+\t\t\tEINVAL,\n+\t\t\tRTE_MTR_ERROR_TYPE_METER_POLICY_ID,\n+\t\t\tNULL,\n+\t\t\t\"MTR object meter policy invalid\");\n+\n \t/* Update dependencies */\n \tmp->n_users--;\n+\tpolicy->n_users--;\n \n \t/* Remove from list */\n \tTAILQ_REMOVE(ml, m, node);\n@@ -514,18 +663,18 @@ pmd_mtr_meter_dscp_table_update(struct rte_eth_dev *dev,\n \treturn 0;\n }\n \n-/* MTR object policer action update */\n+/* MTR object policy update */\n static int\n-pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,\n+pmd_mtr_meter_policy_update(struct rte_eth_dev *dev,\n \tuint32_t mtr_id,\n-\tuint32_t action_mask,\n-\tenum rte_mtr_policer_action *actions,\n+\tuint32_t meter_policy_id,\n \tstruct rte_mtr_error *error)\n {\n \tstruct pmd_internals *p = dev->data->dev_private;\n \tstruct softnic_mtr *m;\n \tuint32_t i;\n \tint status;\n+\tstruct softnic_mtr_meter_policy *mp_new, *mp_old;\n \n \t/* MTR object id must be valid */\n \tm = softnic_mtr_find(p, mtr_id);\n@@ -536,28 +685,17 @@ pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,\n \t\t\tNULL,\n \t\t\t\"MTR object id not valid\");\n \n-\t/* Valid policer actions */\n-\tif (actions == NULL)\n+\tif (m->params.meter_policy_id == meter_policy_id)\n+\t\treturn 0;\n+\n+\t/* Meter policy must exist */\n+\tmp_new = softnic_mtr_meter_policy_find(p, meter_policy_id);\n+\tif (mp_new == NULL)\n \t\treturn -rte_mtr_error_set(error,\n \t\t\tEINVAL,\n-\t\t\tRTE_MTR_ERROR_TYPE_UNSPECIFIED,\n+\t\t\tRTE_MTR_ERROR_TYPE_METER_POLICY_ID,\n \t\t\tNULL,\n-\t\t\t\"Invalid actions\");\n-\n-\tfor (i = 0; i < RTE_COLORS; i++) {\n-\t\tif (action_mask & (1 << i)) {\n-\t\t\tif (actions[i] != MTR_POLICER_ACTION_COLOR_GREEN  &&\n-\t\t\t\tactions[i] != MTR_POLICER_ACTION_COLOR_YELLOW &&\n-\t\t\t\tactions[i] != MTR_POLICER_ACTION_COLOR_RED &&\n-\t\t\t\tactions[i] != MTR_POLICER_ACTION_DROP) {\n-\t\t\t\treturn -rte_mtr_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_MTR_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\" Invalid action value\");\n-\t\t\t}\n-\t\t}\n-\t}\n+\t\t\t\"Meter policy id invalid\");\n \n \t/* MTR object owner valid? */\n \tif (m->flow) {\n@@ -569,9 +707,7 @@ pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,\n \n \t\t/* Set action */\n \t\tfor (i = 0; i < RTE_COLORS; i++)\n-\t\t\tif (action_mask & (1 << i))\n-\t\t\t\taction.mtr.mtr[0].policer[i] =\n-\t\t\t\t\tsoftnic_table_action_policer(actions[i]);\n+\t\t\taction.mtr.mtr[0].policer[i] = mp_new->policer[i];\n \n \t\t/* Re-add the rule */\n \t\tstatus = softnic_pipeline_table_rule_add(p,\n@@ -595,10 +731,20 @@ pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,\n \t\t\t1, NULL, 1);\n \t}\n \n-\t/* Meter: Update policer actions */\n-\tfor (i = 0; i < RTE_COLORS; i++)\n-\t\tif (action_mask & (1 << i))\n-\t\t\tm->params.action[i] = actions[i];\n+\tmp_old = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);\n+\tif (mp_old == NULL)\n+\t\treturn -rte_mtr_error_set(error,\n+\t\t\tEINVAL,\n+\t\t\tRTE_MTR_ERROR_TYPE_METER_POLICY_ID,\n+\t\t\tNULL,\n+\t\t\t\"Old meter policy id invalid\");\n+\n+\t/* Meter: Set meter profile */\n+\tm->params.meter_policy_id = meter_policy_id;\n+\n+\t/* Update dependencies*/\n+\tmp_old->n_users--;\n+\tmp_new->n_users++;\n \n \treturn 0;\n }\n@@ -615,28 +761,40 @@ pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,\n \n /* MTR object stats read */\n static void\n-mtr_stats_convert(struct softnic_mtr *m,\n+mtr_stats_convert(struct pmd_internals *p,\n+\tstruct softnic_mtr *m,\n \tstruct rte_table_action_mtr_counters_tc *in,\n \tstruct rte_mtr_stats *out,\n \tuint64_t *out_mask)\n {\n+\tstruct softnic_mtr_meter_policy *mp;\n+\n \tmemset(&out, 0, sizeof(out));\n \t*out_mask = 0;\n \n+\t/* Meter policy must exist */\n+\tmp = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);\n+\tif (mp == NULL)\n+\t\treturn;\n+\n \tif (in->n_packets_valid) {\n \t\tuint32_t i;\n \n \t\tfor (i = 0; i < RTE_COLORS; i++) {\n-\t\t\tif (m->params.action[i] == MTR_POLICER_ACTION_COLOR_GREEN)\n+\t\t\tif (mp->policer[i] ==\n+\t\t\t\tRTE_TABLE_ACTION_POLICER_COLOR_GREEN)\n \t\t\t\tout->n_pkts[RTE_COLOR_GREEN] += in->n_packets[i];\n \n-\t\t\tif (m->params.action[i] == MTR_POLICER_ACTION_COLOR_YELLOW)\n+\t\t\tif (mp->policer[i] ==\n+\t\t\t\tRTE_TABLE_ACTION_POLICER_COLOR_YELLOW)\n \t\t\t\tout->n_pkts[RTE_COLOR_YELLOW] += in->n_packets[i];\n \n-\t\t\tif (m->params.action[i] == MTR_POLICER_ACTION_COLOR_RED)\n+\t\t\tif (mp->policer[i] ==\n+\t\t\t\tRTE_TABLE_ACTION_POLICER_COLOR_RED)\n \t\t\t\tout->n_pkts[RTE_COLOR_RED] += in->n_packets[i];\n \n-\t\t\tif (m->params.action[i] == MTR_POLICER_ACTION_DROP)\n+\t\t\tif (mp->policer[i] ==\n+\t\t\t\tRTE_TABLE_ACTION_POLICER_DROP)\n \t\t\t\tout->n_pkts_dropped += in->n_packets[i];\n \t\t}\n \n@@ -647,16 +805,20 @@ mtr_stats_convert(struct softnic_mtr *m,\n \t\tuint32_t i;\n \n \t\tfor (i = 0; i < RTE_COLORS; i++) {\n-\t\t\tif (m->params.action[i] == MTR_POLICER_ACTION_COLOR_GREEN)\n+\t\t\tif (mp->policer[i] ==\n+\t\t\t\tRTE_TABLE_ACTION_POLICER_COLOR_GREEN)\n \t\t\t\tout->n_bytes[RTE_COLOR_GREEN] += in->n_bytes[i];\n \n-\t\t\tif (m->params.action[i] == MTR_POLICER_ACTION_COLOR_YELLOW)\n+\t\t\tif (mp->policer[i] ==\n+\t\t\t\tRTE_TABLE_ACTION_POLICER_COLOR_YELLOW)\n \t\t\t\tout->n_bytes[RTE_COLOR_YELLOW] += in->n_bytes[i];\n \n-\t\t\tif (m->params.action[i] == MTR_POLICER_ACTION_COLOR_RED)\n+\t\t\tif (mp->policer[i] ==\n+\t\t\t\tRTE_TABLE_ACTION_POLICER_COLOR_RED)\n \t\t\t\tout->n_bytes[RTE_COLOR_RED] += in->n_bytes[i];\n \n-\t\t\tif (m->params.action[i] == MTR_POLICER_ACTION_DROP)\n+\t\t\tif (mp->policer[i] ==\n+\t\t\t\tRTE_TABLE_ACTION_POLICER_DROP)\n \t\t\t\tout->n_bytes_dropped += in->n_bytes[i];\n \t\t}\n \n@@ -722,7 +884,8 @@ pmd_mtr_stats_read(struct rte_eth_dev *dev,\n \t\tstruct rte_mtr_stats s;\n \t\tuint64_t s_mask = 0;\n \n-\t\tmtr_stats_convert(m,\n+\t\tmtr_stats_convert(p,\n+\t\t\tm,\n \t\t\t&counters.stats[0],\n \t\t\t&s,\n \t\t\t&s_mask);\n@@ -743,6 +906,9 @@ const struct rte_mtr_ops pmd_mtr_ops = {\n \t.meter_profile_add = pmd_mtr_meter_profile_add,\n \t.meter_profile_delete = pmd_mtr_meter_profile_delete,\n \n+\t.meter_policy_add = pmd_mtr_meter_policy_add,\n+\t.meter_policy_delete = pmd_mtr_meter_policy_delete,\n+\n \t.create = pmd_mtr_create,\n \t.destroy = pmd_mtr_destroy,\n \t.meter_enable = NULL,\n@@ -750,7 +916,7 @@ const struct rte_mtr_ops pmd_mtr_ops = {\n \n \t.meter_profile_update = pmd_mtr_meter_profile_update,\n \t.meter_dscp_table_update = pmd_mtr_meter_dscp_table_update,\n-\t.policer_actions_update = pmd_mtr_policer_actions_update,\n+\t.meter_policy_update = pmd_mtr_meter_policy_update,\n \t.stats_update = NULL,\n \n \t.stats_read = pmd_mtr_stats_read,\ndiff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h\nindex 203c4cde9a..66ae3fd1ee 100644\n--- a/lib/librte_ethdev/rte_flow.h\n+++ b/lib/librte_ethdev/rte_flow.h\n@@ -32,6 +32,7 @@\n #include <rte_ecpri.h>\n #include <rte_mbuf.h>\n #include <rte_mbuf_dyn.h>\n+#include <rte_meter.h>\n \n #ifdef __cplusplus\n extern \"C\" {\n@@ -2267,6 +2268,14 @@ enum rte_flow_action_type {\n \t * See struct rte_flow_action_modify_field.\n \t */\n \tRTE_FLOW_ACTION_TYPE_MODIFY_FIELD,\n+\n+\t/**\n+\t * Color the packet to reflect the meter color result.\n+\t * Set the meter color in the mbuf to the selected color.\n+\t *\n+\t * See struct rte_flow_action_meter_color.\n+\t */\n+\tRTE_FLOW_ACTION_TYPE_METER_COLOR,\n };\n \n /**\n@@ -2859,6 +2868,19 @@ struct rte_flow_action_set_dscp {\n  */\n struct rte_flow_shared_action;\n \n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this structure may change without prior notice\n+ *\n+ * RTE_FLOW_ACTION_TYPE_METER_COLOR\n+ *\n+ * The meter color should be set in the packet meta-data\n+ * (i.e. struct rte_mbuf::sched::color).\n+ */\n+struct rte_flow_action_meter_color {\n+\tenum rte_color color; /**< Packet color. */\n+};\n+\n /**\n  * Field IDs for MODIFY_FIELD action.\n  */\ndiff --git a/lib/librte_ethdev/rte_mtr.c b/lib/librte_ethdev/rte_mtr.c\nindex 3073ac03f2..e49fcf271c 100644\n--- a/lib/librte_ethdev/rte_mtr.c\n+++ b/lib/librte_ethdev/rte_mtr.c\n@@ -91,6 +91,40 @@ rte_mtr_meter_profile_delete(uint16_t port_id,\n \t\tmeter_profile_id, error);\n }\n \n+/* MTR meter policy validate */\n+int\n+rte_mtr_meter_policy_validate(uint16_t port_id,\n+\tstruct rte_mtr_meter_policy_params *policy,\n+\tstruct rte_mtr_error *error)\n+{\n+\tstruct rte_eth_dev *dev = &rte_eth_devices[port_id];\n+\treturn RTE_MTR_FUNC(port_id, meter_policy_validate)(dev,\n+\t\tpolicy, error);\n+}\n+\n+/* MTR meter policy add */\n+int\n+rte_mtr_meter_policy_add(uint16_t port_id,\n+\tuint32_t policy_id,\n+\tstruct rte_mtr_meter_policy_params *policy,\n+\tstruct rte_mtr_error *error)\n+{\n+\tstruct rte_eth_dev *dev = &rte_eth_devices[port_id];\n+\treturn RTE_MTR_FUNC(port_id, meter_policy_add)(dev,\n+\t\tpolicy_id, policy, error);\n+}\n+\n+/** MTR meter policy delete */\n+int\n+rte_mtr_meter_policy_delete(uint16_t port_id,\n+\tuint32_t policy_id,\n+\tstruct rte_mtr_error *error)\n+{\n+\tstruct rte_eth_dev *dev = &rte_eth_devices[port_id];\n+\treturn RTE_MTR_FUNC(port_id, meter_policy_delete)(dev,\n+\t\tpolicy_id, error);\n+}\n+\n /** MTR object create */\n int\n rte_mtr_create(uint16_t port_id,\n@@ -149,29 +183,28 @@ rte_mtr_meter_profile_update(uint16_t port_id,\n \t\tmtr_id, meter_profile_id, error);\n }\n \n-/** MTR object meter DSCP table update */\n+/** MTR object meter policy update */\n int\n-rte_mtr_meter_dscp_table_update(uint16_t port_id,\n+rte_mtr_meter_policy_update(uint16_t port_id,\n \tuint32_t mtr_id,\n-\tenum rte_color *dscp_table,\n+\tuint32_t meter_policy_id,\n \tstruct rte_mtr_error *error)\n {\n \tstruct rte_eth_dev *dev = &rte_eth_devices[port_id];\n-\treturn RTE_MTR_FUNC(port_id, meter_dscp_table_update)(dev,\n-\t\tmtr_id, dscp_table, error);\n+\treturn RTE_MTR_FUNC(port_id, meter_policy_update)(dev,\n+\t\tmtr_id, meter_policy_id, error);\n }\n \n-/** MTR object policer action update */\n+/** MTR object meter DSCP table update */\n int\n-rte_mtr_policer_actions_update(uint16_t port_id,\n+rte_mtr_meter_dscp_table_update(uint16_t port_id,\n \tuint32_t mtr_id,\n-\tuint32_t action_mask,\n-\tenum rte_mtr_policer_action *actions,\n+\tenum rte_color *dscp_table,\n \tstruct rte_mtr_error *error)\n {\n \tstruct rte_eth_dev *dev = &rte_eth_devices[port_id];\n-\treturn RTE_MTR_FUNC(port_id, policer_actions_update)(dev,\n-\t\tmtr_id, action_mask, actions, error);\n+\treturn RTE_MTR_FUNC(port_id, meter_dscp_table_update)(dev,\n+\t\tmtr_id, dscp_table, error);\n }\n \n /** MTR object enabled stats update */\ndiff --git a/lib/librte_ethdev/rte_mtr.h b/lib/librte_ethdev/rte_mtr.h\nindex ceb5dcbef1..ca6277e5a5 100644\n--- a/lib/librte_ethdev/rte_mtr.h\n+++ b/lib/librte_ethdev/rte_mtr.h\n@@ -49,6 +49,7 @@\n #include <rte_compat.h>\n #include <rte_common.h>\n #include <rte_meter.h>\n+#include <rte_flow.h>\n \n #ifdef __cplusplus\n extern \"C\" {\n@@ -200,20 +201,16 @@ struct rte_mtr_meter_profile {\n };\n \n /**\n- * Policer actions\n+ * Meter policy\n  */\n-enum rte_mtr_policer_action {\n-\t/** Recolor the packet as green. */\n-\tMTR_POLICER_ACTION_COLOR_GREEN = 0,\n-\n-\t/** Recolor the packet as yellow. */\n-\tMTR_POLICER_ACTION_COLOR_YELLOW,\n-\n-\t/** Recolor the packet as red. */\n-\tMTR_POLICER_ACTION_COLOR_RED,\n-\n-\t/** Drop the packet. */\n-\tMTR_POLICER_ACTION_DROP,\n+struct rte_mtr_meter_policy_params {\n+\t/**\n+\t * Policy action list per color.\n+\t * actions[i] potentially represents a chain of rte_flow actions\n+\t * terminated by the END action, exactly as specified by the rte_flow\n+\t * API for the flow definition, and not just a single action.\n+\t */\n+\tconst struct rte_flow_action *actions[RTE_COLORS];\n };\n \n /**\n@@ -257,13 +254,13 @@ struct rte_mtr_params {\n \t */\n \tint meter_enable;\n \n-\t/** Policer actions (per meter output color). */\n-\tenum rte_mtr_policer_action action[RTE_COLORS];\n-\n \t/** Set of stats counters to be enabled.\n \t * @see enum rte_mtr_stats_type\n \t */\n \tuint64_t stats_mask;\n+\n+\t/** Meter policy ID. */\n+\tuint32_t meter_policy_id;\n };\n \n /**\n@@ -349,6 +346,13 @@ struct rte_mtr_capabilities {\n \t */\n \tuint64_t meter_rate_max;\n \n+\t/**\n+\t * Maximum number of policy objects that can have.\n+\t * The value of 0 is invalid. Policy must be supported for meter.\n+\t * The maximum value is *n_max*.\n+\t */\n+\tuint64_t meter_policy_n_max;\n+\n \t/**\n \t * When non-zero, it indicates that color aware mode is supported for\n \t * the srTCM RFC 2697 metering algorithm.\n@@ -367,18 +371,6 @@ struct rte_mtr_capabilities {\n \t */\n \tint color_aware_trtcm_rfc4115_supported;\n \n-\t/** When non-zero, it indicates that the policer packet recolor actions\n-\t * are supported.\n-\t * @see enum rte_mtr_policer_action\n-\t */\n-\tint policer_action_recolor_supported;\n-\n-\t/** When non-zero, it indicates that the policer packet drop action is\n-\t * supported.\n-\t * @see enum rte_mtr_policer_action\n-\t */\n-\tint policer_action_drop_supported;\n-\n \t/**\n \t * srTCM rfc2697 byte mode supported.\n \t * When non-zero, it indicates that byte mode is supported for\n@@ -447,6 +439,8 @@ enum rte_mtr_error_type {\n \tRTE_MTR_ERROR_TYPE_STATS_MASK,\n \tRTE_MTR_ERROR_TYPE_STATS,\n \tRTE_MTR_ERROR_TYPE_SHARED,\n+\tRTE_MTR_ERROR_TYPE_METER_POLICY_ID,\n+\tRTE_MTR_ERROR_TYPE_METER_POLICY,\n };\n \n /**\n@@ -530,6 +524,144 @@ rte_mtr_meter_profile_delete(uint16_t port_id,\n \tuint32_t meter_profile_id,\n \tstruct rte_mtr_error *error);\n \n+/**\n+ * Check whether a meter policy can be created on a given port.\n+ *\n+ * The meter policy is validated for correctness and\n+ * whether it could be accepted by the device given sufficient resources.\n+ * The policy is checked against the current capability information\n+ * meter_policy_n_max configuration.\n+ * The policy may also optionally be validated against existing\n+ * device policy resources.\n+ * This function has no effect on the target device.\n+ *\n+ * @param[in] port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param[in] policy\n+ *   Associated action list per color.\n+ *   list NULL is legal and means no special action.\n+ *   (list terminated by the END action).\n+ * @param[out] error\n+ *   Error details. Filled in only on error, when not NULL.\n+ * @return\n+ *   0 on success, non-zero error code otherwise.\n+ */\n+__rte_experimental\n+int\n+rte_mtr_meter_policy_validate(uint16_t port_id,\n+\tstruct rte_mtr_meter_policy_params *policy,\n+\tstruct rte_mtr_error *error);\n+\n+/**\n+ * Meter policy add\n+ *\n+ * Create a new meter policy. The new policy\n+ * is used to create single or multiple MTR objects.\n+ * The same policy can be used to create multiple MTR objects.\n+ *\n+ * @param[in] port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param[in] policy_id\n+ *   Policy identifier for the new meter policy.\n+ * @param[in] policy\n+ *   Associated actions per color.\n+ *   list NULL is legal and means no special action.\n+ *   Non-NULL list must be terminated.\n+ *   (list terminated by the END action).\n+ * @param[out] error\n+ *   Error details. Filled in only on error, when not NULL.\n+ * @return\n+ *   0 on success, non-zero error code otherwise.\n+ */\n+__rte_experimental\n+int\n+rte_mtr_meter_policy_add(uint16_t port_id,\n+\tuint32_t policy_id,\n+\tstruct rte_mtr_meter_policy_params *policy,\n+\tstruct rte_mtr_error *error);\n+\n+/**\n+ * Define meter policy action list:\n+ * GREEN - GREEN, YELLOW - YELLOW, RED - RED\n+ */\n+#define rte_mtr_policy_pass_color(policy) \\\n+struct rte_mtr_meter_policy_params policy = \\\n+{ \\\n+\t.actions[RTE_COLOR_GREEN] = (struct rte_flow_action[]) { \\\n+\t\t{ \\\n+\t\t\t.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \\\n+\t\t\t.conf = &(struct rte_flow_action_meter_color) { \\\n+\t\t\t\t.color = RTE_COLOR_GREEN, \\\n+\t\t\t}, \\\n+\t\t}, \\\n+\t\t{ \\\n+\t\t\t.type = RTE_FLOW_ACTION_TYPE_END, \\\n+\t\t}, \\\n+\t}, \\\n+\t.actions[RTE_COLOR_YELLOW] = (struct rte_flow_action[]) { \\\n+\t\t{ \\\n+\t\t\t.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \\\n+\t\t\t.conf = &(struct rte_flow_action_meter_color) { \\\n+\t\t\t\t.color = RTE_COLOR_YELLOW, \\\n+\t\t\t}, \\\n+\t\t}, \\\n+\t\t{ \\\n+\t\t.type = RTE_FLOW_ACTION_TYPE_END, \\\n+\t\t}, \\\n+\t}, \\\n+\t.actions[RTE_COLOR_RED] = (struct rte_flow_action[]) { \\\n+\t\t{ \\\n+\t\t\t.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \\\n+\t\t\t.conf = &(struct rte_flow_action_meter_color) { \\\n+\t\t\t\t.color = RTE_COLOR_RED, \\\n+\t\t\t}, \\\n+\t\t}, \\\n+\t\t{ \\\n+\t\t\t.type = RTE_FLOW_ACTION_TYPE_END, \\\n+\t\t}, \\\n+\t}, \\\n+}\n+\n+/**\n+ * Define meter policy action list:\n+ * GREEN - Do nothing, YELLOW - Do nothing, RED - DROP\n+ */\n+#define rte_mtr_policy_drop_red(policy) \\\n+struct rte_mtr_meter_policy_params policy = \\\n+{ \\\n+\t.actions[RTE_COLOR_GREEN] = NULL, \\\n+\t.actions[RTE_COLOR_YELLOW] = NULL, \\\n+\t.actions[RTE_COLOR_RED] = (struct rte_flow_action[]) { \\\n+\t\t{ \\\n+\t\t\t.type = RTE_FLOW_ACTION_TYPE_DROP, \\\n+\t\t}, \\\n+\t\t{ \\\n+\t\t\t.type = RTE_FLOW_ACTION_TYPE_END, \\\n+\t\t}, \\\n+\t}, \\\n+}\n+\n+/**\n+ * Meter policy delete\n+ *\n+ * Delete an existing meter policy. This operation fails when there is\n+ * currently at least one user (i.e. MTR object) of this policy.\n+ *\n+ * @param[in] port_id\n+ *   The port identifier of the Ethernet device.\n+ * @param[in] policy_id\n+ *   Policy identifier.\n+ * @param[out] error\n+ *   Error details. Filled in only on error, when not NULL.\n+ * @return\n+ *   0 on success, non-zero error code otherwise.\n+ */\n+__rte_experimental\n+int\n+rte_mtr_meter_policy_delete(uint16_t port_id,\n+\tuint32_t policy_id,\n+\tstruct rte_mtr_error *error);\n+\n /**\n  * MTR object create\n  *\n@@ -655,18 +787,14 @@ rte_mtr_meter_profile_update(uint16_t port_id,\n \tstruct rte_mtr_error *error);\n \n /**\n- * MTR object DSCP table update\n+ * MTR object meter policy update\n  *\n  * @param[in] port_id\n  *   The port identifier of the Ethernet device.\n  * @param[in] mtr_id\n  *   MTR object ID. Needs to be valid.\n- * @param[in] dscp_table\n- *   When non-NULL: it points to a pre-allocated and pre-populated table with\n- *   exactly 64 elements providing the input color for each value of the\n- *   IPv4/IPv6 Differentiated Services Code Point (DSCP) input packet field.\n- *   When NULL: it is equivalent to setting this parameter to an “all-green”\n- *   populated table (i.e. table with all the 64 elements set to green color).\n+ * @param[in] meter_policy_id\n+ *   Meter policy ID for the current MTR object. Needs to be valid.\n  * @param[out] error\n  *   Error details. Filled in only on error, when not NULL.\n  * @return\n@@ -674,26 +802,24 @@ rte_mtr_meter_profile_update(uint16_t port_id,\n  */\n __rte_experimental\n int\n-rte_mtr_meter_dscp_table_update(uint16_t port_id,\n+rte_mtr_meter_policy_update(uint16_t port_id,\n \tuint32_t mtr_id,\n-\tenum rte_color *dscp_table,\n+\tuint32_t meter_policy_id,\n \tstruct rte_mtr_error *error);\n \n /**\n- * MTR object policer actions update\n+ * MTR object DSCP table update\n  *\n  * @param[in] port_id\n  *   The port identifier of the Ethernet device.\n  * @param[in] mtr_id\n  *   MTR object ID. Needs to be valid.\n- * @param[in] action_mask\n- *   Bit mask indicating which policer actions need to be updated. One or more\n- *   policer actions can be updated in a single function invocation. To update\n- *   the policer action associated with color C, bit (1 << C) needs to be set in\n- *   *action_mask* and element at position C in the *actions* array needs to be\n- *   valid.\n- * @param[in] actions\n- *   Pre-allocated and pre-populated array of policer actions.\n+ * @param[in] dscp_table\n+ *   When non-NULL: it points to a pre-allocated and pre-populated table with\n+ *   exactly 64 elements providing the input color for each value of the\n+ *   IPv4/IPv6 Differentiated Services Code Point (DSCP) input packet field.\n+ *   When NULL: it is equivalent to setting this parameter to an “all-green”\n+ *   populated table (i.e. table with all the 64 elements set to green color).\n  * @param[out] error\n  *   Error details. Filled in only on error, when not NULL.\n  * @return\n@@ -701,10 +827,9 @@ rte_mtr_meter_dscp_table_update(uint16_t port_id,\n  */\n __rte_experimental\n int\n-rte_mtr_policer_actions_update(uint16_t port_id,\n+rte_mtr_meter_dscp_table_update(uint16_t port_id,\n \tuint32_t mtr_id,\n-\tuint32_t action_mask,\n-\tenum rte_mtr_policer_action *actions,\n+\tenum rte_color *dscp_table,\n \tstruct rte_mtr_error *error);\n \n /**\ndiff --git a/lib/librte_ethdev/rte_mtr_driver.h b/lib/librte_ethdev/rte_mtr_driver.h\nindex a0ddc2b5f4..62273ed3a9 100644\n--- a/lib/librte_ethdev/rte_mtr_driver.h\n+++ b/lib/librte_ethdev/rte_mtr_driver.h\n@@ -41,6 +41,22 @@ typedef int (*rte_mtr_meter_profile_delete_t)(struct rte_eth_dev *dev,\n \tstruct rte_mtr_error *error);\n /**< @internal MTR meter profile delete */\n \n+typedef int (*rte_mtr_meter_policy_validate_t)(struct rte_eth_dev *dev,\n+\tstruct rte_mtr_meter_policy_params *policy,\n+\tstruct rte_mtr_error *error);\n+/**< @internal MTR meter policy validate */\n+\n+typedef int (*rte_mtr_meter_policy_add_t)(struct rte_eth_dev *dev,\n+\tuint32_t policy_id,\n+\tstruct rte_mtr_meter_policy_params *policy,\n+\tstruct rte_mtr_error *error);\n+/**< @internal MTR meter policy add */\n+\n+typedef int (*rte_mtr_meter_policy_delete_t)(struct rte_eth_dev *dev,\n+\tuint32_t policy_id,\n+\tstruct rte_mtr_error *error);\n+/**< @internal MTR meter policy delete */\n+\n typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,\n \tuint32_t mtr_id,\n \tstruct rte_mtr_params *params,\n@@ -69,18 +85,17 @@ typedef int (*rte_mtr_meter_profile_update_t)(struct rte_eth_dev *dev,\n \tstruct rte_mtr_error *error);\n /**< @internal MTR object meter profile update */\n \n-typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,\n+typedef int (*rte_mtr_meter_policy_update_t)(struct rte_eth_dev *dev,\n \tuint32_t mtr_id,\n-\tenum rte_color *dscp_table,\n+\tuint32_t meter_policy_id,\n \tstruct rte_mtr_error *error);\n-/**< @internal MTR object meter DSCP table update */\n+/**< @internal MTR object meter policy update */\n \n-typedef int (*rte_mtr_policer_actions_update_t)(struct rte_eth_dev *dev,\n+typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,\n \tuint32_t mtr_id,\n-\tuint32_t action_mask,\n-\tenum rte_mtr_policer_action *actions,\n+\tenum rte_color *dscp_table,\n \tstruct rte_mtr_error *error);\n-/**< @internal MTR object policer action update*/\n+/**< @internal MTR object meter DSCP table update */\n \n typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,\n \tuint32_t mtr_id,\n@@ -124,14 +139,23 @@ struct rte_mtr_ops {\n \t/** MTR object meter DSCP table update */\n \trte_mtr_meter_dscp_table_update_t meter_dscp_table_update;\n \n-\t/** MTR object policer action update */\n-\trte_mtr_policer_actions_update_t policer_actions_update;\n-\n \t/** MTR object enabled stats update */\n \trte_mtr_stats_update_t stats_update;\n \n \t/** MTR object stats read */\n \trte_mtr_stats_read_t stats_read;\n+\n+\t/** MTR meter policy validate */\n+\trte_mtr_meter_policy_validate_t meter_policy_validate;\n+\n+\t/** MTR meter policy add */\n+\trte_mtr_meter_policy_add_t meter_policy_add;\n+\n+\t/** MTR meter policy delete */\n+\trte_mtr_meter_policy_delete_t meter_policy_delete;\n+\n+\t/** MTR object meter policy update */\n+\trte_mtr_meter_policy_update_t meter_policy_update;\n };\n \n /**\ndiff --git a/lib/librte_ethdev/version.map b/lib/librte_ethdev/version.map\nindex 93ad388e96..b3e9b83d95 100644\n--- a/lib/librte_ethdev/version.map\n+++ b/lib/librte_ethdev/version.map\n@@ -138,7 +138,6 @@ EXPERIMENTAL {\n \trte_mtr_meter_profile_add;\n \trte_mtr_meter_profile_delete;\n \trte_mtr_meter_profile_update;\n-\trte_mtr_policer_actions_update;\n \trte_mtr_stats_read;\n \trte_mtr_stats_update;\n \n@@ -246,6 +245,10 @@ EXPERIMENTAL {\n \n \t# added in 21.05\n \trte_eth_representor_info_get;\n+\trte_mtr_meter_policy_add;\n+\trte_mtr_meter_policy_delete;\n+\trte_mtr_meter_policy_update;\n+\trte_mtr_meter_policy_validate;\n };\n \n INTERNAL {\n",
    "prefixes": [
        "v8",
        "1/2"
    ]
}