DPDK patches and discussions
 help / color / mirror / Atom feed
From: Li Zhang <lizh@nvidia.com>
To: "Dumitrescu, Cristian" <cristian.dumitrescu@intel.com>,
	"dekelp@nvidia.com" <dekelp@nvidia.com>,
	Ori Kam <orika@nvidia.com>,
	Slava Ovsiienko <viacheslavo@nvidia.com>,
	Matan Azrad <matan@nvidia.com>,
	Shahaf Shuler <shahafs@nvidia.com>,
	"lironh@marvell.com" <lironh@marvell.com>,
	Wisam Monther <wisamm@nvidia.com>,
	"Li, Xiaoyun" <xiaoyun.li@intel.com>,
	"Singh, Jasvinder" <jasvinder.singh@intel.com>,
	NBU-Contact-Thomas Monjalon <thomas@monjalon.net>,
	"Yigit, Ferruh" <ferruh.yigit@intel.com>,
	Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>,
	Ray Kinsella <mdr@ashroe.eu>, Neil Horman <nhorman@tuxdriver.com>,
	Jerin Jacob <jerinjacobk@gmail.com>,
	Hemant Agrawal <hemant.agrawal@nxp.com>
Cc: "dev@dpdk.org" <dev@dpdk.org>,
	Raslan Darawsheh <rasland@nvidia.com>,
	Roni Bar Yanai <roniba@nvidia.com>,
	Haifei Luo <haifeil@nvidia.com>,
	"Jiawei(Jonny) Wang" <jiaweiw@nvidia.com>
Subject: Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy API
Date: Wed, 14 Apr 2021 04:55:05 +0000	[thread overview]
Message-ID: <DM6PR12MB40900DAC1A159811EC6B80F0BF4E9@DM6PR12MB4090.namprd12.prod.outlook.com> (raw)
In-Reply-To: <DM6PR11MB27967E609417CFFC06CCA8C8EB4F9@DM6PR11MB2796.namprd11.prod.outlook.com>

Hi Cristian,
> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Dumitrescu, Cristian
> Sent: Tuesday, April 13, 2021 11:00 PM
> To: Li Zhang <lizh@nvidia.com>; dekelp@nvidia.com; Ori Kam
> <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; Matan
> Azrad <matan@nvidia.com>; Shahaf Shuler <shahafs@nvidia.com>;
> lironh@marvell.com; Wisam Monther <wisamm@nvidia.com>; Li, Xiaoyun
> <xiaoyun.li@intel.com>; Singh, Jasvinder <jasvinder.singh@intel.com>; NBU-
> Contact-Thomas Monjalon <thomas@monjalon.net>; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Andrew Rybchenko
> <andrew.rybchenko@oktetlabs.ru>; Ray Kinsella <mdr@ashroe.eu>; Neil
> Horman <nhorman@tuxdriver.com>; Jerin Jacob <jerinjacobk@gmail.com>;
> Hemant Agrawal <hemant.agrawal@nxp.com>
> Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar Yanai
> <roniba@nvidia.com>; Haifei Luo <haifeil@nvidia.com>; Jiawei(Jonny) Wang
> <jiaweiw@nvidia.com>
> Subject: Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy
> API
> 
> External email: Use caution opening links or attachments
> 
> 
> Hi Li,
> 
> Here are some initial comments while waiting for a new version that applies
> cleanly.
> 
> > -----Original Message-----
> > From: Li Zhang <lizh@nvidia.com>
> > Sent: Tuesday, April 13, 2021 1:14 AM
> > To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> > matan@nvidia.com; shahafs@nvidia.com; Dumitrescu, Cristian
> > <cristian.dumitrescu@intel.com>; lironh@marvell.com; Wisam Jaddo
> > <wisamm@nvidia.com>; Li, Xiaoyun <xiaoyun.li@intel.com>; Singh,
> Jasvinder
> > <jasvinder.singh@intel.com>; Thomas Monjalon <thomas@monjalon.net>;
> > Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew Rybchenko
> > <andrew.rybchenko@oktetlabs.ru>; Ray Kinsella <mdr@ashroe.eu>; Neil
> > Horman <nhorman@tuxdriver.com>
> > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com; Haifei Luo
> > <haifeil@nvidia.com>; Jiawei Wang <jiaweiw@nvidia.com>
> > Subject: [PATCH v3 1/2] ethdev: add pre-defined meter policy API
> >
> > Currently, the flow meter policy does not support multiple actions
> > per color; also the allowed action types per color are very limited.
> > In addition, the policy cannot be pre-defined.
> >
> > Due to the growing in flow actions offload abilities there is a potential
> > for the user to use variety of actions per color differently.
> > This new meter policy API comes to allow this potential in the most ethdev
> > common way using rte_flow action definition.
> > A list of rte_flow actions will be provided by the user per color
> > in order to create a meter policy.
> > In addition, the API forces to pre-define the policy before
> > the meters creation in order to allow sharing of single policy
> > with multiple meters efficiently.
> >
> > meter_policy_id is added into struct rte_mtr_params.
> > So that it can get the policy during the meters creation.
> >
> > Allow coloring the packet using a new rte_flow_action_color
> > as could be done by the old policy API.
> >
> > The next API function were added:
> > - rte_mtr_meter_policy_create
> > - rte_mtr_meter_policy_delete
> > - rte_mtr_meter_policy_update
> > - rte_mtr_meter_policy_validate
> > The next struct was changed:
> > - rte_mtr_params
> > - rte_mtr_capabilities
> > The next API was deleted:
> > - rte_mtr_policer_actions_update
> >
> > To support this API the following app were changed:
> > app/test-flow-perf: clean meter policer
> > app/testpmd: clean meter policer
> >
> > To support this API the following drivers were changed:
> > net/softnic: support meter policy API
> > 1. cleans meter rte_mtr_policer_action.
> > 2. Support policy API to get color action as policer action did.
> >    The color action will be mapped into rte_table_action_policer.
> >
> > net/mlx5: clean meter creation management
> > Cleans and breaks part of the current meter management
> > in order to allow better design with policy API.
> >
> > Signed-off-by: Li Zhang <lizh@nvidia.com>
> > Signed-off-by: Haifei Luo <haifeil@nvidia.com>
> > Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
> > Acked-by: Matan Azrad <matan@nvidia.com>
> > ---
> >  app/test-flow-perf/main.c                     |   7 -
> >  app/test-pmd/cmdline.c                        |   1 -
> >  app/test-pmd/cmdline_mtr.c                    | 172 -------
> >  app/test-pmd/cmdline_mtr.h                    |   1 -
> >  doc/guides/prog_guide/rte_flow.rst            |  21 +
> >  .../traffic_metering_and_policing.rst         |  16 +-
> >  doc/guides/rel_notes/release_21_05.rst        |  22 +-
> >  doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  18 -
> >  drivers/net/mlx5/mlx5.h                       |  24 +-
> >  drivers/net/mlx5/mlx5_flow.c                  |  46 --
> >  drivers/net/mlx5/mlx5_flow.h                  |  18 +-
> >  drivers/net/mlx5/mlx5_flow_aso.c              |   8 +-
> >  drivers/net/mlx5/mlx5_flow_dv.c               | 461 +-----------------
> >  drivers/net/mlx5/mlx5_flow_meter.c            | 369 +-------------
> >  drivers/net/softnic/rte_eth_softnic_flow.c    |  19 +-
> >  .../net/softnic/rte_eth_softnic_internals.h   |  18 +-
> >  drivers/net/softnic/rte_eth_softnic_meter.c   | 264 +++++++---
> >  lib/librte_ethdev/rte_flow.h                  |  22 +
> >  lib/librte_ethdev/rte_mtr.c                   |  55 ++-
> >  lib/librte_ethdev/rte_mtr.h                   | 215 ++++++--
> >  lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
> >  lib/librte_ethdev/version.map                 |   5 +-
> >  22 files changed, 568 insertions(+), 1258 deletions(-)
> >
> > diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c
> > index 0aef767350..c1f38cbec5 100644
> > --- a/app/test-flow-perf/main.c
> > +++ b/app/test-flow-perf/main.c
> > @@ -921,13 +921,6 @@ create_meter_rule(int port_id, uint32_t counter)
> >
> >       /*create meter*/
> >       params.meter_profile_id = default_prof_id;
> > -     params.action[RTE_COLOR_GREEN] =
> > -             MTR_POLICER_ACTION_COLOR_GREEN;
> > -     params.action[RTE_COLOR_YELLOW] =
> > -             MTR_POLICER_ACTION_COLOR_YELLOW;
> > -     params.action[RTE_COLOR_RED] =
> > -             MTR_POLICER_ACTION_DROP;
> > -
> >       ret = rte_mtr_create(port_id, counter, &params, 1, &error);
> >       if (ret != 0) {
> >               printf("Port %u create meter idx(%d) error(%d) message:
> > %s\n",
> > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> > index f44116b087..fae79d4c85 100644
> > --- a/app/test-pmd/cmdline.c
> > +++ b/app/test-pmd/cmdline.c
> > @@ -17071,7 +17071,6 @@ cmdline_parse_ctx_t main_ctx[] = {
> >       (cmdline_parse_inst_t *)&cmd_del_port_meter,
> >       (cmdline_parse_inst_t *)&cmd_set_port_meter_profile,
> >       (cmdline_parse_inst_t *)&cmd_set_port_meter_dscp_table,
> > -     (cmdline_parse_inst_t *)&cmd_set_port_meter_policer_action,
> >       (cmdline_parse_inst_t *)&cmd_set_port_meter_stats_mask,
> >       (cmdline_parse_inst_t *)&cmd_show_port_meter_stats,
> >       (cmdline_parse_inst_t *)&cmd_mcast_addr,
> > diff --git a/app/test-pmd/cmdline_mtr.c b/app/test-pmd/cmdline_mtr.c
> > index 3982787d20..44394e3ea1 100644
> > --- a/app/test-pmd/cmdline_mtr.c
> > +++ b/app/test-pmd/cmdline_mtr.c
> > @@ -146,53 +146,6 @@ parse_meter_color_str(char *c_str, uint32_t
> > *use_prev_meter_color,
> >       return 0;
> >  }
> >
> > -static int
> > -string_to_policer_action(char *s)
> > -{
> > -     if ((strcmp(s, "G") == 0) || (strcmp(s, "g") == 0))
> > -             return MTR_POLICER_ACTION_COLOR_GREEN;
> > -
> > -     if ((strcmp(s, "Y") == 0) || (strcmp(s, "y") == 0))
> > -             return MTR_POLICER_ACTION_COLOR_YELLOW;
> > -
> > -     if ((strcmp(s, "R") == 0) || (strcmp(s, "r") == 0))
> > -             return MTR_POLICER_ACTION_COLOR_RED;
> > -
> > -     if ((strcmp(s, "D") == 0) || (strcmp(s, "d") == 0))
> > -             return MTR_POLICER_ACTION_DROP;
> > -
> > -     return -1;
> > -}
> > -
> > -static int
> > -parse_policer_action_string(char *p_str, uint32_t action_mask,
> > -     enum rte_mtr_policer_action actions[])
> > -{
> > -     char *token;
> > -     int count = __builtin_popcount(action_mask);
> > -     int g_color = 0, y_color = 0, action, i;
> > -
> > -     for (i = 0; i < count; i++) {
> > -             token = strtok_r(p_str, PARSE_DELIMITER, &p_str);
> > -             if (token ==  NULL)
> > -                     return -1;
> > -
> > -             action = string_to_policer_action(token);
> > -             if (action == -1)
> > -                     return -1;
> > -
> > -             if (g_color == 0 && (action_mask & 0x1)) {
> > -                     actions[RTE_COLOR_GREEN] = action;
> > -                     g_color = 1;
> > -             } else if (y_color == 0 && (action_mask & 0x2)) {
> > -                     actions[RTE_COLOR_YELLOW] = action;
> > -                     y_color = 1;
> > -             } else
> > -                     actions[RTE_COLOR_RED] = action;
> > -     }
> > -     return 0;
> > -}
> > -
> >  static int
> >  parse_multi_token_string(char *t_str, uint16_t *port_id,
> >       uint32_t *mtr_id, enum rte_color **dscp_table)
> > @@ -302,10 +255,6 @@ static void cmd_show_port_meter_cap_parsed(void
> > *parsed_result,
> >               cap.color_aware_trtcm_rfc2698_supported);
> >       printf("cap.color_aware_trtcm_rfc4115_supported %" PRId32 "\n",
> >               cap.color_aware_trtcm_rfc4115_supported);
> > -     printf("cap.policer_action_recolor_supported %" PRId32 "\n",
> > -             cap.policer_action_recolor_supported);
> > -     printf("cap.policer_action_drop_supported %" PRId32 "\n",
> > -             cap.policer_action_drop_supported);
> >       printf("cap.stats_mask %" PRIx64 "\n", cap.stats_mask);
> >  }
> >
> > @@ -808,12 +757,6 @@ static void cmd_create_port_meter_parsed(void
> > *parsed_result,
> >       else
> >               params.meter_enable = 0;
> >
> > -     params.action[RTE_COLOR_GREEN] =
> > -             string_to_policer_action(res->g_action);
> > -     params.action[RTE_COLOR_YELLOW] =
> > -             string_to_policer_action(res->y_action);
> > -     params.action[RTE_COLOR_RED] =
> > -             string_to_policer_action(res->r_action);
> >       params.stats_mask = res->statistics_mask;
> >
> >       ret = rte_mtr_create(port_id, mtr_id, &params, shared, &error);
> > @@ -1181,121 +1124,6 @@ cmdline_parse_inst_t
> > cmd_set_port_meter_dscp_table = {
> >       },
> >  };
> >
> > -/* *** Set Port Meter Policer Action *** */
> > -struct cmd_set_port_meter_policer_action_result {
> > -     cmdline_fixed_string_t set;
> > -     cmdline_fixed_string_t port;
> > -     cmdline_fixed_string_t meter;
> > -     cmdline_fixed_string_t policer;
> > -     cmdline_fixed_string_t action;
> > -     uint16_t port_id;
> > -     uint32_t mtr_id;
> > -     uint32_t action_mask;
> > -     cmdline_multi_string_t policer_action;
> > -};
> > -
> > -cmdline_parse_token_string_t cmd_set_port_meter_policer_action_set =
> > -     TOKEN_STRING_INITIALIZER(
> > -             struct cmd_set_port_meter_policer_action_result, set,
> > "set");
> > -cmdline_parse_token_string_t cmd_set_port_meter_policer_action_port =
> > -     TOKEN_STRING_INITIALIZER(
> > -             struct cmd_set_port_meter_policer_action_result, port,
> > "port");
> > -cmdline_parse_token_string_t cmd_set_port_meter_policer_action_meter
> > =
> > -     TOKEN_STRING_INITIALIZER(
> > -             struct cmd_set_port_meter_policer_action_result, meter,
> > -             "meter");
> > -cmdline_parse_token_string_t
> > cmd_set_port_meter_policer_action_policer =
> > -     TOKEN_STRING_INITIALIZER(
> > -             struct cmd_set_port_meter_policer_action_result, policer,
> > -             "policer");
> > -cmdline_parse_token_string_t cmd_set_port_meter_policer_action_action
> > =
> > -     TOKEN_STRING_INITIALIZER(
> > -             struct cmd_set_port_meter_policer_action_result, action,
> > -             "action");
> > -cmdline_parse_token_num_t
> > cmd_set_port_meter_policer_action_port_id =
> > -     TOKEN_NUM_INITIALIZER(
> > -             struct cmd_set_port_meter_policer_action_result, port_id,
> > -             RTE_UINT16);
> > -cmdline_parse_token_num_t cmd_set_port_meter_policer_action_mtr_id
> > =
> > -     TOKEN_NUM_INITIALIZER(
> > -             struct cmd_set_port_meter_policer_action_result, mtr_id,
> > -             RTE_UINT32);
> > -cmdline_parse_token_num_t
> > cmd_set_port_meter_policer_action_action_mask =
> > -     TOKEN_NUM_INITIALIZER(
> > -             struct cmd_set_port_meter_policer_action_result,
> > action_mask,
> > -             RTE_UINT32);
> > -cmdline_parse_token_string_t
> > cmd_set_port_meter_policer_action_policer_action =
> > -     TOKEN_STRING_INITIALIZER(
> > -             struct cmd_set_port_meter_policer_action_result,
> > -             policer_action, TOKEN_STRING_MULTI);
> > -
> > -static void cmd_set_port_meter_policer_action_parsed(void
> > *parsed_result,
> > -     __rte_unused struct cmdline *cl,
> > -     __rte_unused void *data)
> > -{
> > -     struct cmd_set_port_meter_policer_action_result *res =
> > parsed_result;
> > -     enum rte_mtr_policer_action *actions;
> > -     struct rte_mtr_error error;
> > -     uint32_t mtr_id = res->mtr_id;
> > -     uint32_t action_mask = res->action_mask;
> > -     uint16_t port_id = res->port_id;
> > -     char *p_str = res->policer_action;
> > -     int ret;
> > -
> > -     if (port_id_is_invalid(port_id, ENABLED_WARN))
> > -             return;
> > -
> > -     /* Check: action mask */
> > -     if (action_mask == 0 || (action_mask & (~0x7UL))) {
> > -             printf(" Policer action mask not correct (error)\n");
> > -             return;
> > -     }
> > -
> > -     /* Allocate memory for policer actions */
> > -     actions = (enum rte_mtr_policer_action *)malloc(RTE_COLORS *
> > -             sizeof(enum rte_mtr_policer_action));
> > -     if (actions == NULL) {
> > -             printf("Memory for policer actions not allocated (error)\n");
> > -             return;
> > -     }
> > -     /* Parse policer action string */
> > -     ret = parse_policer_action_string(p_str, action_mask, actions);
> > -     if (ret) {
> > -             printf(" Policer action string parse error\n");
> > -             free(actions);
> > -             return;
> > -     }
> > -
> > -     ret = rte_mtr_policer_actions_update(port_id, mtr_id,
> > -             action_mask, actions, &error);
> > -     if (ret != 0) {
> > -             free(actions);
> > -             print_err_msg(&error);
> > -             return;
> > -     }
> > -
> > -     free(actions);
> > -}
> > -
> > -cmdline_parse_inst_t cmd_set_port_meter_policer_action = {
> > -     .f = cmd_set_port_meter_policer_action_parsed,
> > -     .data = NULL,
> > -     .help_str = "set port meter policer action <port_id> <mtr_id> "
> > -             "<action_mask> <action0> [<action1> <action2>]",
> > -     .tokens = {
> > -             (void *)&cmd_set_port_meter_policer_action_set,
> > -             (void *)&cmd_set_port_meter_policer_action_port,
> > -             (void *)&cmd_set_port_meter_policer_action_meter,
> > -             (void *)&cmd_set_port_meter_policer_action_policer,
> > -             (void *)&cmd_set_port_meter_policer_action_action,
> > -             (void *)&cmd_set_port_meter_policer_action_port_id,
> > -             (void *)&cmd_set_port_meter_policer_action_mtr_id,
> > -             (void *)&cmd_set_port_meter_policer_action_action_mask,
> > -             (void
> > *)&cmd_set_port_meter_policer_action_policer_action,
> > -             NULL,
> > -     },
> > -};
> > -
> >  /* *** Set Port Meter Stats Mask *** */
> >  struct cmd_set_port_meter_stats_mask_result {
> >       cmdline_fixed_string_t set;
> > diff --git a/app/test-pmd/cmdline_mtr.h b/app/test-pmd/cmdline_mtr.h
> > index e69d6da023..7e2713cea3 100644
> > --- a/app/test-pmd/cmdline_mtr.h
> > +++ b/app/test-pmd/cmdline_mtr.h
> > @@ -17,7 +17,6 @@ extern cmdline_parse_inst_t cmd_disable_port_meter;
> >  extern cmdline_parse_inst_t cmd_del_port_meter;
> >  extern cmdline_parse_inst_t cmd_set_port_meter_profile;
> >  extern cmdline_parse_inst_t cmd_set_port_meter_dscp_table;
> > -extern cmdline_parse_inst_t cmd_set_port_meter_policer_action;
> >  extern cmdline_parse_inst_t cmd_set_port_meter_stats_mask;
> >  extern cmdline_parse_inst_t cmd_show_port_meter_stats;
> >
> > diff --git a/doc/guides/prog_guide/rte_flow.rst
> > b/doc/guides/prog_guide/rte_flow.rst
> > index e1b93ecedf..2f5a6e0c31 100644
> > --- a/doc/guides/prog_guide/rte_flow.rst
> > +++ b/doc/guides/prog_guide/rte_flow.rst
> > @@ -2841,6 +2841,27 @@ for ``RTE_FLOW_FIELD_VALUE`` and
> > ``RTE_FLOW_FIELD_POINTER`` respectively.
> >     | ``value``     | immediate value or a pointer to this value               |
> >     +---------------+----------------------------------------------------------+
> >
> > +Action: ``METER_COLOR``
> > +^^^^^^^^^^^^^^^^^^^^^^^
> > +
> > +Color the packet to reflect the meter color result.
> > +
> > +The meter action must be configured before meter color action.
> > +Meter color action is set to a color to reflect the meter color result.
> > +Set the meter color in the mbuf to the selected color.
> > +The meter color action output color is the output color of the packet,
> > +which is set in the packet meta-data (i.e. struct ``rte_mbuf::sched::color``)
> > +
> > +.. _table_rte_flow_action_meter_color:
> > +
> > +.. table:: METER_COLOR
> > +
> > +   +-----------------+--------------+
> > +   | Field           | Value        |
> > +   +=================+==============+
> > +   | ``meter_color`` | Packet color |
> > +   +-----------------+--------------+
> > +
> >  Negative types
> >  ~~~~~~~~~~~~~~
> >
> > diff --git a/doc/guides/prog_guide/traffic_metering_and_policing.rst
> > b/doc/guides/prog_guide/traffic_metering_and_policing.rst
> > index 90c781eb1d..c0537e653c 100644
> > --- a/doc/guides/prog_guide/traffic_metering_and_policing.rst
> > +++ b/doc/guides/prog_guide/traffic_metering_and_policing.rst
> > @@ -56,18 +56,10 @@ The processing done for each input packet hitting an
> > MTR object is:
> >    color blind mode, which is equivalent to considering all input packets
> >    initially colored as green.
> >
> > -* Policing: There is a separate policer action configured for each meter
> > -  output color, which can:
> > -
> > -  * Drop the packet.
> > -
> > -  * Keep the same packet color: the policer output color matches the meter
> > -    output color (essentially a no-op action).
> > -
> > -  * Recolor the packet: the policer output color is set to a different color
> > -    than the meter output color. The policer output color is the output color
> > -    of the packet, which is set in the packet meta-data (i.e. struct
> > -    ``rte_mbuf::sched::color``).
> > +* There is a meter policy API to manage pre-defined policies for meter.
> > +  Any rte_flow action list can be configured per color for each policy.
> > +  A meter object configured with a policy executes the actions per packet
> > +  according to the packet color.
> >
> >  * Statistics: The set of counters maintained for each MTR object is
> >    configurable and subject to the implementation support. This set includes
> > diff --git a/doc/guides/rel_notes/release_21_05.rst
> > b/doc/guides/rel_notes/release_21_05.rst
> > index 113b37cddc..1b1b4368f6 100644
> > --- a/doc/guides/rel_notes/release_21_05.rst
> > +++ b/doc/guides/rel_notes/release_21_05.rst
> > @@ -161,7 +161,27 @@ New Features
> >      ``dpdk-testpmd -- --eth-link-speed N``
> >    * Added command to display Rx queue used descriptor count.
> >      ``show port (port_id) rxq (queue_id) desc used count``
> > -
> > +  * deleted the port meter policer action command .
> > +    ``set port meter policer action (port_id) (mtr_id) (action_mask) ...``
> > +  * Added command to create meter policy.
> > +    ``add port meter policy (port_id) (policy_id) g_actions {action} end
> > y_actions {action} end r_actions {action} end``
> > +  * Added command to delete meter policy.
> > +    ``del port meter policy (port_id) (policy_id)``
> > +
> > +* **Updated meter API.**
> > +
> > +  * ethdev: Deleted meter policer API to support policy API.
> > +    ``rte_mtr_policer_actions_update()``
> > +  * ethdev: Added meter API to support pre-defined policy, rte_flow action
> > list per color.
> > +    ``rte_mtr_meter_policy_create()``, ``rte_mtr_meter_policy_delete()``
> > and
> > +    ``rte_mtr_create_with_policy()``
> > +  * ethdev: Removed rte_mtr_policer_action from rte_mtr_params
> > structures.
> > +  * ethdev: Added rte_mtr_meter_policy_params structures to support
> > policy API.
> > +  * ethdev: Added meter_policy_id into rte_mtr_params structures.
> > +  * ethdev: Removed policer_action_recolor_supported and
> > policer_action_drop_supported from rte_mtr_capabilities structures.
> > +  * ethdev: Added meter_policy_n_max into rte_mtr_capabilities
> > structures.
> > +  * ethdev: Added RTE_FLOW_ACTION_TYPE_METER_COLOR in enum
> > rte_flow_action_type.
> > +  * ethdev: Added RTE_MTR_ERROR_TYPE_METER_POLICY_ID and
> > RTE_MTR_ERROR_TYPE_METER_POLICY_ID into rte_mtr_error_type.
> >
> >  Removed Items
> >  -------------
> > diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > index 36f0a328a5..3f7a1c0e33 100644
> > --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > @@ -2830,24 +2830,6 @@ Set meter dscp table for the ethernet device::
> >     testpmd> set port meter dscp table (port_id) (mtr_id) [(dscp_tbl_entry0) \
> >     (dscp_tbl_entry1)...(dscp_tbl_entry63)]
> >
> > -set port meter policer action
> > -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > -
> > -Set meter policer action for the ethernet device::
> > -
> > -   testpmd> set port meter policer action (port_id) (mtr_id) (action_mask) \
> > -   (action0) [(action1) (action1)]
> > -
> > -where:
> > -
> > -* ``action_mask``: Bit mask indicating which policer actions need to be
> > -  updated. One or more policer actions can be updated in a single function
> > -  invocation. To update the policer action associated with color C, bit
> > -  (1 << C) needs to be set in *action_mask* and element at position C
> > -  in the *actions* array needs to be valid.
> > -* ``actionx``: Policer action for the color x,
> > -  RTE_MTR_GREEN <= x < RTE_MTR_COLORS
> > -
> >  set port meter stats mask
> >  ~~~~~~~~~~~~~~~~~~~~~~~~~
> >
> > diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
> > index 9a02aa4488..a8e11023cc 100644
> > --- a/drivers/net/mlx5/mlx5.h
> > +++ b/drivers/net/mlx5/mlx5.h
> > @@ -584,14 +584,6 @@ struct mlx5_dev_shared_port {
> >  /* Modify this value if enum rte_mtr_color changes. */
> >  #define RTE_MTR_DROPPED RTE_COLORS
> >
> > -/* Meter policer statistics */
> > -struct mlx5_flow_policer_stats {
> > -     uint32_t pass_cnt;
> > -     /**< Color counter for pass. */
> > -     uint32_t drop_cnt;
> > -     /**< Color counter for drop. */
> > -};
> > -
> >  /* Meter table structure. */
> >  struct mlx5_meter_domain_info {
> >       struct mlx5_flow_tbl_resource *tbl;
> > @@ -630,24 +622,12 @@ struct mlx5_meter_domains_infos {
> >
> >  /* Meter parameter structure. */
> >  struct mlx5_flow_meter_info {
> > -     uint32_t meter_id;
> > -     /**< Meter id. */
> >       struct mlx5_flow_meter_profile *profile;
> >       /**< Meter profile parameters. */
> >       rte_spinlock_t sl; /**< Meter action spinlock. */
> > -     /** Policer actions (per meter output color). */
> > -     enum rte_mtr_policer_action action[RTE_COLORS];
> >       /** Set of stats counters to be enabled.
> >        * @see enum rte_mtr_stats_type
> >        */
> > -     uint32_t green_bytes:1;
> > -     /** Set green bytes stats to be enabled. */
> > -     uint32_t green_pkts:1;
> > -     /** Set green packets stats to be enabled. */
> > -     uint32_t red_bytes:1;
> > -     /** Set red bytes stats to be enabled. */
> > -     uint32_t red_pkts:1;
> > -     /** Set red packets stats to be enabled. */
> >       uint32_t bytes_dropped:1;
> >       /** Set bytes dropped stats to be enabled. */
> >       uint32_t pkts_dropped:1;
> > @@ -682,8 +662,8 @@ struct mlx5_flow_meter_info {
> >       uint32_t transfer:1;
> >       struct mlx5_meter_domains_infos *mfts;
> >       /**< Flow table created for this meter. */
> > -     struct mlx5_flow_policer_stats policer_stats;
> > -     /**< Meter policer statistics. */
> > +     uint32_t drop_cnt;
> > +     /**< Color counter for drop. */
> >       uint32_t ref_cnt;
> >       /**< Use count. */
> >       struct mlx5_indexed_pool *flow_ipool;
> > diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
> > index 242c6f2288..ee2c351649 100644
> > --- a/drivers/net/mlx5/mlx5_flow.c
> > +++ b/drivers/net/mlx5/mlx5_flow.c
> > @@ -6647,52 +6647,6 @@ mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev
> > *dev,
> >       return fops->destroy_mtr_tbls(dev, tbls);
> >  }
> >
> > -/**
> > - * Prepare policer rules.
> > - *
> > - * @param[in] dev
> > - *   Pointer to Ethernet device.
> > - * @param[in] fm
> > - *   Pointer to flow meter structure.
> > - * @param[in] attr
> > - *   Pointer to flow attributes.
> > - *
> > - * @return
> > - *   0 on success, -1 otherwise.
> > - */
> > -int
> > -mlx5_flow_prepare_policer_rules(struct rte_eth_dev *dev,
> > -                            struct mlx5_flow_meter_info *fm,
> > -                            const struct rte_flow_attr *attr)
> > -{
> > -     const struct mlx5_flow_driver_ops *fops;
> > -
> > -     fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
> > -     return fops->prepare_policer_rules(dev, fm, attr);
> > -}
> > -
> > -/**
> > - * Destroy policer rules.
> > - *
> > - * @param[in] fm
> > - *   Pointer to flow meter structure.
> > - * @param[in] attr
> > - *   Pointer to flow attributes.
> > - *
> > - * @return
> > - *   0 on success, -1 otherwise.
> > - */
> > -int
> > -mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,
> > -                             struct mlx5_flow_meter_info *fm,
> > -                             const struct rte_flow_attr *attr)
> > -{
> > -     const struct mlx5_flow_driver_ops *fops;
> > -
> > -     fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
> > -     return fops->destroy_policer_rules(dev, fm, attr);
> > -}
> > -
> >  /**
> >   * Allocate the needed aso flow meter id.
> >   *
> > diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
> > index cb2803d080..7fa15eef7b 100644
> > --- a/drivers/net/mlx5/mlx5_flow.h
> > +++ b/drivers/net/mlx5/mlx5_flow.h
> > @@ -839,6 +839,8 @@ struct mlx5_legacy_flow_meter {
> >       /* Must be the first in struct. */
> >       TAILQ_ENTRY(mlx5_legacy_flow_meter) next;
> >       /**< Pointer to the next flow meter structure. */
> > +     uint32_t meter_id;
> > +     /**< Meter id. */
> >       uint32_t idx; /* Index to meter object. */
> >  };
> >
> > @@ -1097,14 +1099,6 @@ typedef struct mlx5_meter_domains_infos
> > *(*mlx5_flow_create_mtr_tbls_t)
> >                                           (struct rte_eth_dev *dev);
> >  typedef int (*mlx5_flow_destroy_mtr_tbls_t)(struct rte_eth_dev *dev,
> >                                       struct mlx5_meter_domains_infos
> > *tbls);
> > -typedef int (*mlx5_flow_create_policer_rules_t)
> > -                                     (struct rte_eth_dev *dev,
> > -                                      struct mlx5_flow_meter_info *fm,
> > -                                      const struct rte_flow_attr *attr);
> > -typedef int (*mlx5_flow_destroy_policer_rules_t)
> > -                                     (struct rte_eth_dev *dev,
> > -                                      const struct mlx5_flow_meter_info
> > *fm,
> > -                                      const struct rte_flow_attr *attr);
> >  typedef uint32_t (*mlx5_flow_mtr_alloc_t)
> >                                           (struct rte_eth_dev *dev);
> >  typedef void (*mlx5_flow_mtr_free_t)(struct rte_eth_dev *dev,
> > @@ -1161,8 +1155,6 @@ struct mlx5_flow_driver_ops {
> >       mlx5_flow_query_t query;
> >       mlx5_flow_create_mtr_tbls_t create_mtr_tbls;
> >       mlx5_flow_destroy_mtr_tbls_t destroy_mtr_tbls;
> > -     mlx5_flow_create_policer_rules_t prepare_policer_rules;
> > -     mlx5_flow_destroy_policer_rules_t destroy_policer_rules;
> >       mlx5_flow_mtr_alloc_t create_meter;
> >       mlx5_flow_mtr_free_t free_meter;
> >       mlx5_flow_counter_alloc_t counter_alloc;
> > @@ -1392,12 +1384,6 @@ struct mlx5_meter_domains_infos
> > *mlx5_flow_create_mtr_tbls
> >                                       (struct rte_eth_dev *dev);
> >  int mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,
> >                              struct mlx5_meter_domains_infos *tbl);
> > -int mlx5_flow_prepare_policer_rules(struct rte_eth_dev *dev,
> > -                                struct mlx5_flow_meter_info *fm,
> > -                                const struct rte_flow_attr *attr);
> > -int mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,
> > -                                 struct mlx5_flow_meter_info *fm,
> > -                                 const struct rte_flow_attr *attr);
> >  int mlx5_flow_meter_flush(struct rte_eth_dev *dev,
> >                         struct rte_mtr_error *error);
> >  int mlx5_flow_dv_discover_counter_offset_support(struct rte_eth_dev
> > *dev);
> > diff --git a/drivers/net/mlx5/mlx5_flow_aso.c
> > b/drivers/net/mlx5/mlx5_flow_aso.c
> > index cd2cc016b9..62d2df054b 100644
> > --- a/drivers/net/mlx5/mlx5_flow_aso.c
> > +++ b/drivers/net/mlx5/mlx5_flow_aso.c
> > @@ -808,8 +808,8 @@ mlx5_aso_meter_update_by_wqe(struct
> > mlx5_dev_ctx_shared *sh,
> >               /* Waiting for wqe resource. */
> >
> >       rte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
> >       } while (--poll_wqe_times);
> > -     DRV_LOG(ERR, "Fail to send WQE for ASO meter %d",
> > -                     mtr->fm.meter_id);
> > +     DRV_LOG(ERR, "Fail to send WQE for ASO meter offset %d",
> > +                     mtr->offset);
> >       return -1;
> >  }
> >
> > @@ -844,7 +844,7 @@ mlx5_aso_mtr_wait(struct mlx5_dev_ctx_shared
> > *sh,
> >               /* Waiting for CQE ready. */
> >
> >       rte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
> >       } while (--poll_cqe_times);
> > -     DRV_LOG(ERR, "Fail to poll CQE ready for ASO meter %d",
> > -                     mtr->fm.meter_id);
> > +     DRV_LOG(ERR, "Fail to poll CQE ready for ASO meter offset %d",
> > +                     mtr->offset);
> >       return -1;
> >  }
> > diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> > b/drivers/net/mlx5/mlx5_flow_dv.c
> > index d8ea440668..af3397fb55 100644
> > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> > @@ -184,31 +184,6 @@ flow_dv_attr_init(const struct rte_flow_item *item,
> > union flow_dv_attr *attr,
> >       attr->valid = 1;
> >  }
> >
> > -/**
> > - * Convert rte_mtr_color to mlx5 color.
> > - *
> > - * @param[in] rcol
> > - *   rte_mtr_color.
> > - *
> > - * @return
> > - *   mlx5 color.
> > - */
> > -static int
> > -rte_col_2_mlx5_col(enum rte_color rcol)
> > -{
> > -     switch (rcol) {
> > -     case RTE_COLOR_GREEN:
> > -             return MLX5_FLOW_COLOR_GREEN;
> > -     case RTE_COLOR_YELLOW:
> > -             return MLX5_FLOW_COLOR_YELLOW;
> > -     case RTE_COLOR_RED:
> > -             return MLX5_FLOW_COLOR_RED;
> > -     default:
> > -             break;
> > -     }
> > -     return MLX5_FLOW_COLOR_UNDEFINED;
> > -}
> > -
> >  struct field_modify_info {
> >       uint32_t size; /* Size of field in protocol header, in bytes. */
> >       uint32_t offset; /* Offset of field in protocol header, in bytes. */
> > @@ -6025,12 +6000,10 @@ flow_dv_mtr_pool_create(struct rte_eth_dev
> > *dev,
> >       mtrmng->n_valid++;
> >       for (i = 1; i < MLX5_ASO_MTRS_PER_POOL; ++i) {
> >               pool->mtrs[i].offset = i;
> > -             pool->mtrs[i].fm.meter_id = UINT32_MAX;
> >               LIST_INSERT_HEAD(&mtrmng->meters,
> >                                               &pool->mtrs[i], next);
> >       }
> >       pool->mtrs[0].offset = 0;
> > -     pool->mtrs[0].fm.meter_id = UINT32_MAX;
> >       *mtr_free = &pool->mtrs[0];
> >       return pool;
> >  }
> > @@ -6054,7 +6027,6 @@ flow_dv_aso_mtr_release_to_pool(struct
> > rte_eth_dev *dev, uint32_t mtr_idx)
> >       rte_spinlock_lock(&mtrmng->mtrsl);
> >       memset(&aso_mtr->fm, 0, sizeof(struct mlx5_flow_meter_info));
> >       aso_mtr->state = ASO_METER_FREE;
> > -     aso_mtr->fm.meter_id = UINT32_MAX;
> >       LIST_INSERT_HEAD(&mtrmng->meters, aso_mtr, next);
> >       rte_spinlock_unlock(&mtrmng->mtrsl);
> >  }
> > @@ -6094,8 +6066,8 @@ flow_dv_mtr_alloc(struct rte_eth_dev *dev)
> >       mtr_free->state = ASO_METER_WAIT;
> >       rte_spinlock_unlock(&mtrmng->mtrsl);
> >       pool = container_of(mtr_free,
> > -                                     struct mlx5_aso_mtr_pool,
> > -                                     mtrs[mtr_free->offset]);
> > +                     struct mlx5_aso_mtr_pool,
> > +                     mtrs[mtr_free->offset]);
> >       mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, mtr_free->offset);
> >       if (!mtr_free->fm.meter_action) {
> >  #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
> > @@ -13702,433 +13674,6 @@ flow_dv_create_mtr_tbl(struct rte_eth_dev
> > *dev)
> >       return NULL;
> >  }
> >
> > -/**
> > - * Destroy the meter table matchers.
> > - * Lock free, (mutex should be acquired by caller).
> > - *
> > - * @param[in] dev
> > - *   Pointer to Ethernet device.
> > - * @param[in,out] dtb
> > - *   Pointer to DV meter table.
> > - *
> > - * @return
> > - *   Always 0.
> > - */
> > -static int
> > -flow_dv_destroy_mtr_matchers(struct rte_eth_dev *dev,
> > -                          struct mlx5_meter_domain_info *dtb)
> > -{
> > -     struct mlx5_priv *priv = dev->data->dev_private;
> > -     struct mlx5_flow_tbl_data_entry *tbl;
> > -
> > -     if (!priv->config.dv_flow_en)
> > -             return 0;
> > -     if (dtb->drop_matcher) {
> > -             tbl = container_of(dtb->drop_matcher->tbl, typeof(*tbl),
> > tbl);
> > -             mlx5_cache_unregister(&tbl->matchers,
> > -                                   &dtb->drop_matcher->entry);
> > -             dtb->drop_matcher = NULL;
> > -     }
> > -     if (dtb->color_matcher) {
> > -             tbl = container_of(dtb->color_matcher->tbl, typeof(*tbl),
> > tbl);
> > -             mlx5_cache_unregister(&tbl->matchers,
> > -                                   &dtb->color_matcher->entry);
> > -             dtb->color_matcher = NULL;
> > -     }
> > -     return 0;
> > -}
> > -
> > -/**
> > - * Create the matchers for meter table.
> > - *
> > - * @param[in] dev
> > - *   Pointer to Ethernet device.
> > - * @param[in] color_reg_c_idx
> > - *   Reg C index for color match.
> > - * @param[in] mtr_id_reg_c_idx
> > - *   Reg C index for meter_id match.
> > - * @param[in] mtr_id_mask
> > - *   Mask for meter_id match criteria.
> > - * @param[in,out] dtb
> > - *   Pointer to DV meter table.
> > - * @param[out] error
> > - *   Perform verbose error reporting if not NULL.
> > - *
> > - * @return
> > - *   0 on success, a negative errno value otherwise and rte_errno is set.
> > - */
> > -static int
> > -flow_dv_prepare_mtr_matchers(struct rte_eth_dev *dev,
> > -                          uint32_t color_reg_c_idx,
> > -                          uint32_t mtr_id_reg_c_idx,
> > -                          uint32_t mtr_id_mask,
> > -                          struct mlx5_meter_domain_info *dtb,
> > -                          struct rte_flow_error *error)
> > -{
> > -     struct mlx5_priv *priv = dev->data->dev_private;
> > -     struct mlx5_flow_tbl_data_entry *tbl_data;
> > -     struct mlx5_cache_entry *entry;
> > -     struct mlx5_flow_dv_matcher matcher = {
> > -             .mask = {
> > -                     .size = sizeof(matcher.mask.buf) -
> > -                             MLX5_ST_SZ_BYTES(fte_match_set_misc4),
> > -             },
> > -             .tbl = dtb->tbl,
> > -     };
> > -     struct mlx5_flow_dv_match_params value = {
> > -             .size = sizeof(value.buf) -
> > -                     MLX5_ST_SZ_BYTES(fte_match_set_misc4),
> > -     };
> > -     struct mlx5_flow_cb_ctx ctx = {
> > -             .error = error,
> > -             .data = &matcher,
> > -     };
> > -     uint32_t color_mask = (UINT32_C(1) << MLX5_MTR_COLOR_BITS) -
> > 1;
> > -
> > -     tbl_data = container_of(dtb->tbl, struct mlx5_flow_tbl_data_entry,
> > tbl);
> > -     if (!dtb->drop_matcher) {
> > -             /* Create matchers for Drop. */
> > -             flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
> > -                                    mtr_id_reg_c_idx, 0, mtr_id_mask);
> > -             matcher.priority = MLX5_REG_BITS * 2 - priv->max_mtr_bits;
> > -             matcher.crc = rte_raw_cksum((const void
> > *)matcher.mask.buf,
> > -                                     matcher.mask.size);
> > -             entry = mlx5_cache_register(&tbl_data->matchers, &ctx);
> > -             if (!entry) {
> > -                     DRV_LOG(ERR, "Failed to register meter drop
> > matcher.");
> > -                     return -1;
> > -             }
> > -             dtb->drop_matcher =
> > -                     container_of(entry, struct mlx5_flow_dv_matcher,
> > entry);
> > -     }
> > -     if (!dtb->color_matcher) {
> > -             /* Create matchers for Color + meter_id. */
> > -             if (priv->mtr_reg_share) {
> > -                     flow_dv_match_meta_reg(matcher.mask.buf,
> > value.buf,
> > -                                     color_reg_c_idx, 0,
> > -                                     (mtr_id_mask | color_mask));
> > -             } else {
> > -                     flow_dv_match_meta_reg(matcher.mask.buf,
> > value.buf,
> > -                                     color_reg_c_idx, 0, color_mask);
> > -                     flow_dv_match_meta_reg(matcher.mask.buf,
> > value.buf,
> > -                                     mtr_id_reg_c_idx, 0, mtr_id_mask);
> > -             }
> > -             matcher.priority = MLX5_REG_BITS - priv->max_mtr_bits;
> > -             matcher.crc = rte_raw_cksum((const void
> > *)matcher.mask.buf,
> > -                                     matcher.mask.size);
> > -             entry = mlx5_cache_register(&tbl_data->matchers, &ctx);
> > -             if (!entry) {
> > -                     DRV_LOG(ERR, "Failed to register meter color
> > matcher.");
> > -                     return -1;
> > -             }
> > -             dtb->color_matcher =
> > -                     container_of(entry, struct mlx5_flow_dv_matcher,
> > entry);
> > -     }
> > -     return 0;
> > -}
> > -
> > -/**
> > - * Destroy domain policer rule.
> > - *
> > - * @param[in] dev
> > - *   Pointer to Ethernet device.
> > - * @param[in] dt
> > - *   Pointer to domain table.
> > - */
> > -static void
> > -flow_dv_destroy_domain_policer_rule(struct rte_eth_dev *dev,
> > -                                 struct mlx5_meter_domain_info *dt)
> > -{
> > -     if (dt->drop_rule) {
> > -             claim_zero(mlx5_flow_os_destroy_flow(dt->drop_rule));
> > -             dt->drop_rule = NULL;
> > -     }
> > -     if (dt->green_rule) {
> > -             claim_zero(mlx5_flow_os_destroy_flow(dt->green_rule));
> > -             dt->green_rule = NULL;
> > -     }
> > -     flow_dv_destroy_mtr_matchers(dev, dt);
> > -     if (dt->jump_actn) {
> > -             claim_zero(mlx5_flow_os_destroy_flow_action(dt-
> > >jump_actn));
> > -             dt->jump_actn = NULL;
> > -     }
> > -}
> > -
> > -/**
> > - * Destroy policer rules.
> > - *
> > - * @param[in] dev
> > - *   Pointer to Ethernet device.
> > - * @param[in] fm
> > - *   Pointer to flow meter structure.
> > - * @param[in] attr
> > - *   Pointer to flow attributes.
> > - *
> > - * @return
> > - *   Always 0.
> > - */
> > -static int
> > -flow_dv_destroy_policer_rules(struct rte_eth_dev *dev,
> > -                           const struct mlx5_flow_meter_info *fm,
> > -                           const struct rte_flow_attr *attr)
> > -{
> > -     struct mlx5_meter_domains_infos *mtb = fm ? fm->mfts : NULL;
> > -
> > -     if (!mtb)
> > -             return 0;
> > -     if (attr->egress)
> > -             flow_dv_destroy_domain_policer_rule(dev, &mtb->egress);
> > -     if (attr->ingress)
> > -             flow_dv_destroy_domain_policer_rule(dev, &mtb-
> > >ingress);
> > -     if (attr->transfer)
> > -             flow_dv_destroy_domain_policer_rule(dev, &mtb-
> > >transfer);
> > -     return 0;
> > -}
> > -
> > -/**
> > - * Create specify domain meter policer rule.
> > - *
> > - * @param[in] dev
> > - *   Pointer to Ethernet device.
> > - * @param[in] fm
> > - *   Pointer to flow meter structure.
> > - * @param[in] mtr_idx
> > - *   meter index.
> > - * @param[in] mtb
> > - *   Pointer to DV meter table set.
> > - * @param[out] drop_rule
> > - *   The address of pointer saving drop rule.
> > - * @param[out] color_rule
> > - *   The address of pointer saving green rule.
> > - *
> > - * @return
> > - *   0 on success, -1 otherwise.
> > - */
> > -static int
> > -flow_dv_create_policer_forward_rule(struct rte_eth_dev *dev,
> > -                                 struct mlx5_flow_meter_info *fm,
> > -                                 uint32_t mtr_idx,
> > -                                 struct mlx5_meter_domain_info *dtb,
> > -                                 void **drop_rule,
> > -                                 void **green_rule)
> > -{
> > -     struct mlx5_priv *priv = dev->data->dev_private;
> > -     struct mlx5_flow_dv_match_params matcher = {
> > -             .size = sizeof(matcher.buf) -
> > -                     MLX5_ST_SZ_BYTES(fte_match_set_misc4),
> > -     };
> > -     struct mlx5_flow_dv_match_params value = {
> > -             .size = sizeof(value.buf) -
> > -                     MLX5_ST_SZ_BYTES(fte_match_set_misc4),
> > -     };
> > -     struct mlx5_meter_domains_infos *mtb = fm->mfts;
> > -     struct rte_flow_error error;
> > -     uint32_t color_reg_c = mlx5_flow_get_reg_id(dev,
> > MLX5_MTR_COLOR,
> > -                                                 0, &error);
> > -     uint32_t mtr_id_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_ID,
> > -                                                  0, &error);
> > -     uint8_t mtr_id_offset = priv->mtr_reg_share ?
> > MLX5_MTR_COLOR_BITS : 0;
> > -     uint32_t mtr_id_mask =
> > -             ((UINT32_C(1) << priv->max_mtr_bits) - 1) << mtr_id_offset;
> > -     void *actions[METER_ACTIONS];
> > -     int i;
> > -     int ret = 0;
> > -
> > -     /* Create jump action. */
> > -     if (!dtb->jump_actn)
> > -             ret = mlx5_flow_os_create_flow_action_dest_flow_tbl
> > -                             (dtb->sfx_tbl->obj, &dtb->jump_actn);
> > -     if (ret) {
> > -             DRV_LOG(ERR, "Failed to create policer jump action.");
> > -             goto error;
> > -     }
> > -     /* Prepare matchers. */
> > -     if (!dtb->drop_matcher || !dtb->color_matcher) {
> > -             ret = flow_dv_prepare_mtr_matchers(dev, color_reg_c,
> > -                                                mtr_id_reg_c,
> > mtr_id_mask,
> > -                                                dtb, &error);
> > -             if (ret) {
> > -                     DRV_LOG(ERR, "Failed to setup matchers for mtr
> > table.");
> > -                     goto error;
> > -             }
> > -     }
> > -     /* Create Drop flow, matching meter_id only. */
> > -     i = 0;
> > -     flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c,
> > -                            (mtr_idx << mtr_id_offset), UINT32_MAX);
> > -     if (mtb->drop_count)
> > -             actions[i++] = mtb->drop_count;
> > -     actions[i++] = priv->sh->dr_drop_action;
> > -     ret = mlx5_flow_os_create_flow(dtb->drop_matcher-
> > >matcher_object,
> > -                                    (void *)&value, i, actions, drop_rule);
> > -     if (ret) {
> > -             DRV_LOG(ERR, "Failed to create meter policer drop rule.");
> > -             goto error;
> > -     }
> > -     /* Create flow matching Green color + meter_id. */
> > -     i = 0;
> > -     if (priv->mtr_reg_share) {
> > -             flow_dv_match_meta_reg(matcher.buf, value.buf,
> > color_reg_c,
> > -                                    ((mtr_idx << mtr_id_offset) |
> > -
> >       rte_col_2_mlx5_col(RTE_COLOR_GREEN)),
> > -                                    UINT32_MAX);
> > -     } else {
> > -             flow_dv_match_meta_reg(matcher.buf, value.buf,
> > color_reg_c,
> > -                                    rte_col_2_mlx5_col(RTE_COLOR_GREEN),
> > -                                    UINT32_MAX);
> > -             flow_dv_match_meta_reg(matcher.buf, value.buf,
> > mtr_id_reg_c,
> > -                                    mtr_idx, UINT32_MAX);
> > -     }
> > -     if (mtb->green_count)
> > -             actions[i++] = mtb->green_count;
> > -     actions[i++] = dtb->jump_actn;
> > -     ret = mlx5_flow_os_create_flow(dtb->color_matcher-
> > >matcher_object,
> > -                                    (void *)&value, i, actions, green_rule);
> > -     if (ret) {
> > -             DRV_LOG(ERR, "Failed to create meter policer color rule.");
> > -             goto error;
> > -     }
> > -     return 0;
> > -error:
> > -     rte_errno = errno;
> > -     return -1;
> > -}
> > -
> > -/**
> > - * Prepare policer rules for all domains.
> > - * If meter already initialized, this will replace all old rules with new ones.
> > - *
> > - * @param[in] dev
> > - *   Pointer to Ethernet device.
> > - * @param[in] fm
> > - *   Pointer to flow meter structure.
> > - * @param[in] attr
> > - *   Pointer to flow attributes.
> > - *
> > - * @return
> > - *   0 on success, -1 otherwise.
> > - */
> > -static int
> > -flow_dv_prepare_policer_rules(struct rte_eth_dev *dev,
> > -                           struct mlx5_flow_meter_info *fm,
> > -                           const struct rte_flow_attr *attr)
> > -{
> > -     struct mlx5_priv *priv = dev->data->dev_private;
> > -     struct mlx5_meter_domains_infos *mtb = fm->mfts;
> > -     bool initialized = false;
> > -     struct mlx5_flow_counter *cnt;
> > -     void *egress_drop_rule = NULL;
> > -     void *egress_green_rule = NULL;
> > -     void *ingress_drop_rule = NULL;
> > -     void *ingress_green_rule = NULL;
> > -     void *transfer_drop_rule = NULL;
> > -     void *transfer_green_rule = NULL;
> > -     uint32_t mtr_idx;
> > -     int ret;
> > -
> > -     /* Get the statistics counters for green/drop. */
> > -     if (fm->policer_stats.pass_cnt) {
> > -             cnt = flow_dv_counter_get_by_idx(dev,
> > -                                     fm->policer_stats.pass_cnt,
> > -                                     NULL);
> > -             mtb->green_count = cnt->action;
> > -     } else {
> > -             mtb->green_count = NULL;
> > -     }
> > -     if (fm->policer_stats.drop_cnt) {
> > -             cnt = flow_dv_counter_get_by_idx(dev,
> > -                                     fm->policer_stats.drop_cnt,
> > -                                     NULL);
> > -             mtb->drop_count = cnt->action;
> > -     } else {
> > -             mtb->drop_count = NULL;
> > -     }
> > -     /**
> > -      * If flow meter has been initialized, all policer rules
> > -      * are created. So can get if meter initialized by checking
> > -      * any policer rule.
> > -      */
> > -     if (mtb->egress.drop_rule)
> > -             initialized = true;
> > -     if (priv->sh->meter_aso_en) {
> > -             struct mlx5_aso_mtr *aso_mtr = NULL;
> > -             struct mlx5_aso_mtr_pool *pool;
> > -
> > -             aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
> > -             pool = container_of(aso_mtr, struct mlx5_aso_mtr_pool,
> > -                                 mtrs[aso_mtr->offset]);
> > -             mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, aso_mtr-
> > >offset);
> > -     } else {
> > -             struct mlx5_legacy_flow_meter *legacy_fm;
> > -
> > -             legacy_fm = container_of(fm, struct
> > mlx5_legacy_flow_meter, fm);
> > -             mtr_idx = legacy_fm->idx;
> > -     }
> > -     if (attr->egress) {
> > -             ret = flow_dv_create_policer_forward_rule(dev,
> > -                             fm, mtr_idx, &mtb->egress,
> > -                             &egress_drop_rule, &egress_green_rule);
> > -             if (ret) {
> > -                     DRV_LOG(ERR, "Failed to create egress policer.");
> > -                     goto error;
> > -             }
> > -     }
> > -     if (attr->ingress) {
> > -             ret = flow_dv_create_policer_forward_rule(dev,
> > -                             fm, mtr_idx, &mtb->ingress,
> > -                             &ingress_drop_rule, &ingress_green_rule);
> > -             if (ret) {
> > -                     DRV_LOG(ERR, "Failed to create ingress policer.");
> > -                     goto error;
> > -             }
> > -     }
> > -     if (attr->transfer) {
> > -             ret = flow_dv_create_policer_forward_rule(dev,
> > -                             fm, mtr_idx, &mtb->transfer,
> > -                             &transfer_drop_rule,
> > &transfer_green_rule);
> > -             if (ret) {
> > -                     DRV_LOG(ERR, "Failed to create transfer policer.");
> > -                     goto error;
> > -             }
> > -     }
> > -     /* Replace old flows if existing. */
> > -     if (mtb->egress.drop_rule)
> > -             claim_zero(mlx5_flow_os_destroy_flow(mtb-
> > >egress.drop_rule));
> > -     if (mtb->egress.green_rule)
> > -             claim_zero(mlx5_flow_os_destroy_flow(mtb-
> > >egress.green_rule));
> > -     if (mtb->ingress.drop_rule)
> > -             claim_zero(mlx5_flow_os_destroy_flow(mtb-
> > >ingress.drop_rule));
> > -     if (mtb->ingress.green_rule)
> > -             claim_zero(mlx5_flow_os_destroy_flow(mtb-
> > >ingress.green_rule));
> > -     if (mtb->transfer.drop_rule)
> > -             claim_zero(mlx5_flow_os_destroy_flow(mtb-
> > >transfer.drop_rule));
> > -     if (mtb->transfer.green_rule)
> > -             claim_zero(mlx5_flow_os_destroy_flow(mtb-
> > >transfer.green_rule));
> > -     mtb->egress.drop_rule = egress_drop_rule;
> > -     mtb->egress.green_rule = egress_green_rule;
> > -     mtb->ingress.drop_rule = ingress_drop_rule;
> > -     mtb->ingress.green_rule = ingress_green_rule;
> > -     mtb->transfer.drop_rule = transfer_drop_rule;
> > -     mtb->transfer.green_rule = transfer_green_rule;
> > -     return 0;
> > -error:
> > -     if (egress_drop_rule)
> > -
> >       claim_zero(mlx5_flow_os_destroy_flow(egress_drop_rule));
> > -     if (egress_green_rule)
> > -
> >       claim_zero(mlx5_flow_os_destroy_flow(egress_green_rule));
> > -     if (ingress_drop_rule)
> > -
> >       claim_zero(mlx5_flow_os_destroy_flow(ingress_drop_rule));
> > -     if (ingress_green_rule)
> > -
> >       claim_zero(mlx5_flow_os_destroy_flow(ingress_green_rule));
> > -     if (transfer_drop_rule)
> > -
> >       claim_zero(mlx5_flow_os_destroy_flow(transfer_drop_rule));
> > -     if (transfer_green_rule)
> > -
> >       claim_zero(mlx5_flow_os_destroy_flow(transfer_green_rule));
> > -     if (!initialized)
> > -             flow_dv_destroy_policer_rules(dev, fm, attr);
> > -     return -1;
> > -}
> > -
> >  /**
> >   * Validate the batch counter support in root table.
> >   *
> > @@ -14423,8 +13968,6 @@ const struct mlx5_flow_driver_ops
> > mlx5_flow_dv_drv_ops = {
> >       .query = flow_dv_query,
> >       .create_mtr_tbls = flow_dv_create_mtr_tbl,
> >       .destroy_mtr_tbls = flow_dv_destroy_mtr_tbl,
> > -     .prepare_policer_rules = flow_dv_prepare_policer_rules,
> > -     .destroy_policer_rules = flow_dv_destroy_policer_rules,
> >       .create_meter = flow_dv_mtr_alloc,
> >       .free_meter = flow_dv_aso_mtr_release_to_pool,
> >       .counter_alloc = flow_dv_counter_allocate,
> > diff --git a/drivers/net/mlx5/mlx5_flow_meter.c
> > b/drivers/net/mlx5/mlx5_flow_meter.c
> > index 714b382d55..af0a1c18cb 100644
> > --- a/drivers/net/mlx5/mlx5_flow_meter.c
> > +++ b/drivers/net/mlx5/mlx5_flow_meter.c
> > @@ -329,7 +329,6 @@ mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
> >       cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not
> > supported. */
> >       cap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap-
> > >n_max : 0;
> >       cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */
> > -     cap->policer_action_drop_supported = 1;
> >       cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED |
> >                         RTE_MTR_STATS_N_PKTS_DROPPED;
> >       return 0;
> > @@ -436,90 +435,6 @@ mlx5_flow_meter_profile_delete(struct
> > rte_eth_dev *dev,
> >       return 0;
> >  }
> >
> > -/**
> > - * Convert wrong color setting action to verbose error.
> > - *
> > - * @param[in] action
> > - *   Policy color action.
> > - *
> > - * @return
> > - *   Verbose meter color error type.
> > - */
> > -static inline enum rte_mtr_error_type
> > -action2error(enum rte_mtr_policer_action action)
> > -{
> > -     switch (action) {
> > -     case MTR_POLICER_ACTION_COLOR_GREEN:
> > -             return RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN;
> > -     case MTR_POLICER_ACTION_COLOR_YELLOW:
> > -             return RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW;
> > -     case MTR_POLICER_ACTION_COLOR_RED:
> > -             return RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED;
> > -     default:
> > -             break;
> > -     }
> > -     return RTE_MTR_ERROR_TYPE_UNSPECIFIED;
> > -}
> > -
> > -/**
> > - * Check meter validation.
> > - *
> > - * @param[in] priv
> > - *   Pointer to mlx5 private data structure.
> > - * @param[in] meter_id
> > - *   Meter id.
> > - * @param[in] params
> > - *   Pointer to rte meter parameters.
> > - * @param[out] error
> > - *   Pointer to rte meter error structure.
> > - *
> > - * @return
> > - *   0 on success, a negative errno value otherwise and rte_errno is set.
> > - */
> > -static int
> > -mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,
> > -                      struct rte_mtr_params *params,
> > -                      struct rte_mtr_error *error)
> > -{
> > -     /* Meter must use global drop action. */
> > -     if (!priv->sh->dr_drop_action)
> > -             return -rte_mtr_error_set(error, ENOTSUP,
> > -
> > RTE_MTR_ERROR_TYPE_MTR_PARAMS,
> > -                                       NULL,
> > -                                       "No drop action ready for meter.");
> > -     /* Meter params must not be NULL. */
> > -     if (params == NULL)
> > -             return -rte_mtr_error_set(error, EINVAL,
> > -
> > RTE_MTR_ERROR_TYPE_MTR_PARAMS,
> > -                                       NULL, "Meter object params null.");
> > -     /* Previous meter color is not supported. */
> > -     if (params->use_prev_mtr_color)
> > -             return -rte_mtr_error_set(error, ENOTSUP,
> > -
> > RTE_MTR_ERROR_TYPE_MTR_PARAMS,
> > -                                       NULL,
> > -                                       "Previous meter color "
> > -                                       "not supported.");
> > -     /* Validate policer settings. */
> > -     if (params->action[RTE_COLOR_RED] !=
> > MTR_POLICER_ACTION_DROP)
> > -             return -rte_mtr_error_set
> > -                             (error, ENOTSUP,
> > -                              action2error(params-
> > >action[RTE_COLOR_RED]),
> > -                              NULL,
> > -                              "Red color only supports drop action.");
> > -     if (params->action[RTE_COLOR_GREEN] !=
> > MTR_POLICER_ACTION_COLOR_GREEN)
> > -             return -rte_mtr_error_set
> > -                             (error, ENOTSUP,
> > -                              action2error(params-
> > >action[RTE_COLOR_GREEN]),
> > -                              NULL,
> > -                              "Green color only supports recolor green
> > action.");
> > -     /* Validate meter id. */
> > -     if (mlx5_flow_meter_find(priv, meter_id, NULL))
> > -             return -rte_mtr_error_set(error, EEXIST,
> > -                                       RTE_MTR_ERROR_TYPE_MTR_ID,
> > NULL,
> > -                                       "Meter object already exists.");
> > -     return 0;
> > -}
> > -
> >  /**
> >   * Modify the flow meter action.
> >   *
> > @@ -629,167 +544,14 @@ static void
> >  mlx5_flow_meter_stats_enable_update(struct mlx5_flow_meter_info *fm,
> >                               uint64_t stats_mask)
> >  {
> > -     fm->green_bytes = (stats_mask &
> > RTE_MTR_STATS_N_BYTES_GREEN) ? 1 : 0;
> > -     fm->green_pkts = (stats_mask & RTE_MTR_STATS_N_PKTS_GREEN)
> > ? 1 : 0;
> > -     fm->red_bytes = (stats_mask & RTE_MTR_STATS_N_BYTES_RED) ? 1
> > : 0;
> > -     fm->red_pkts = (stats_mask & RTE_MTR_STATS_N_PKTS_RED) ? 1 :
> > 0;
> >       fm->bytes_dropped =
> >               (stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) ? 1 : 0;
> >       fm->pkts_dropped = (stats_mask &
> > RTE_MTR_STATS_N_PKTS_DROPPED) ? 1 : 0;
> >  }
> >
> > -/**
> > - * Create meter rules.
> > - *
> > - * @param[in] dev
> > - *   Pointer to Ethernet device.
> > - * @param[in] meter_id
> > - *   Meter id.
> > - * @param[in] params
> > - *   Pointer to rte meter parameters.
> > - * @param[in] shared
> > - *   Meter shared with other flow or not.
> > - * @param[out] error
> > - *   Pointer to rte meter error structure.
> > - *
> > - * @return
> > - *   0 on success, a negative errno value otherwise and rte_errno is set.
> > - */
> > -static int
> > -mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
> > -                    struct rte_mtr_params *params, int shared,
> > -                    struct rte_mtr_error *error)
> > -{
> > -     struct mlx5_priv *priv = dev->data->dev_private;
> > -     struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
> > -     struct mlx5_flow_meter_profile *fmp;
> > -     struct mlx5_legacy_flow_meter *legacy_fm;
> > -     struct mlx5_flow_meter_info *fm;
> > -     const struct rte_flow_attr attr = {
> > -                             .ingress = 1,
> > -                             .egress = 1,
> > -                             .transfer = priv->config.dv_esw_en ? 1 : 0,
> > -                     };
> > -     struct mlx5_indexed_pool_config flow_ipool_cfg = {
> > -             .size = 0,
> > -             .trunk_size = 64,
> > -             .need_lock = 1,
> > -             .type = "mlx5_flow_mtr_flow_id_pool",
> > -     };
> > -     struct mlx5_aso_mtr *aso_mtr;
> > -     union mlx5_l3t_data data;
> > -     uint32_t mtr_idx;
> > -     int ret;
> > -     uint8_t mtr_id_bits;
> > -     uint8_t mtr_reg_bits = priv->mtr_reg_share ?
> > -                             MLX5_MTR_IDLE_BITS_IN_COLOR_REG :
> > MLX5_REG_BITS;
> > -
> > -     if (!priv->mtr_en)
> > -             return -rte_mtr_error_set(error, ENOTSUP,
> > -
> > RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
> > -                                       "Meter is not supported");
> > -     /* Validate the parameters. */
> > -     ret = mlx5_flow_meter_validate(priv, meter_id, params, error);
> > -     if (ret)
> > -             return ret;
> > -     /* Meter profile must exist. */
> > -     fmp = mlx5_flow_meter_profile_find(priv, params-
> > >meter_profile_id);
> > -     if (fmp == NULL)
> > -             return -rte_mtr_error_set(error, ENOENT,
> > -
> > RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
> > -                                       NULL, "Meter profile id not valid.");
> > -     /* Allocate the flow meter memory. */
> > -     if (priv->sh->meter_aso_en) {
> > -             mtr_idx = mlx5_flow_mtr_alloc(dev);
> > -             if (!mtr_idx)
> > -                     return -rte_mtr_error_set(error, ENOMEM,
> > -                             RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
> > -                             "Memory alloc failed for meter.");
> > -             aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
> > -             fm = &aso_mtr->fm;
> > -     } else {
> > -             legacy_fm = mlx5_ipool_zmalloc
> > -                             (priv->sh->ipool[MLX5_IPOOL_MTR],
> > &mtr_idx);
> > -             if (legacy_fm == NULL)
> > -                     return -rte_mtr_error_set(error, ENOMEM,
> > -                             RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
> > -                             "Memory alloc failed for meter.");
> > -             legacy_fm->idx = mtr_idx;
> > -             fm = &legacy_fm->fm;
> > -     }
> > -     mtr_id_bits = MLX5_REG_BITS - __builtin_clz(mtr_idx);
> > -     if ((mtr_id_bits + priv->max_mtr_flow_bits) > mtr_reg_bits) {
> > -             DRV_LOG(ERR, "Meter number exceeds max limit.");
> > -             goto error;
> > -     }
> > -     if (mtr_id_bits > priv->max_mtr_bits)
> > -             priv->max_mtr_bits = mtr_id_bits;
> > -     /* Fill the flow meter parameters. */
> > -     fm->meter_id = meter_id;
> > -     fm->profile = fmp;
> > -     memcpy(fm->action, params->action, sizeof(params->action));
> > -     mlx5_flow_meter_stats_enable_update(fm, params->stats_mask);
> > -     /* Alloc policer counters. */
> > -     if (fm->green_bytes || fm->green_pkts) {
> > -             fm->policer_stats.pass_cnt = mlx5_counter_alloc(dev);
> > -             if (!fm->policer_stats.pass_cnt)
> > -                     goto error;
> > -     }
> > -     if (fm->red_bytes || fm->red_pkts ||
> > -         fm->bytes_dropped || fm->pkts_dropped) {
> > -             fm->policer_stats.drop_cnt = mlx5_counter_alloc(dev);
> > -             if (!fm->policer_stats.drop_cnt)
> > -                     goto error;
> > -     }
> > -     fm->mfts = mlx5_flow_create_mtr_tbls(dev);
> > -     if (!fm->mfts)
> > -             goto error;
> > -     ret = mlx5_flow_prepare_policer_rules(dev, fm, &attr);
> > -     if (ret)
> > -             goto error;
> > -     /* Add to the flow meter list. */
> > -     if (!priv->sh->meter_aso_en)
> > -             TAILQ_INSERT_TAIL(fms, legacy_fm, next);
> > -     fm->active_state = 1; /* Config meter starts as active. */
> > -     fm->is_enable = 1;
> > -     fm->shared = !!shared;
> > -     __atomic_add_fetch(&fm->profile->ref_cnt, 1,
> > __ATOMIC_RELAXED);
> > -     fm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg);
> > -     if (!fm->flow_ipool)
> > -             goto error;
> > -     rte_spinlock_init(&fm->sl);
> > -     /* If ASO meter supported, allocate ASO flow meter. */
> > -     if (priv->sh->meter_aso_en) {
> > -             aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
> > -             ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
> > -             if (ret)
> > -                     goto error;
> > -             data.dword = mtr_idx;
> > -             if (mlx5_l3t_set_entry(priv->mtr_idx_tbl, meter_id, &data))
> > -                     goto error;
> > -     }
> > -     return 0;
> > -error:
> > -     mlx5_flow_destroy_policer_rules(dev, fm, &attr);
> > -     mlx5_flow_destroy_mtr_tbls(dev, fm->mfts);
> > -     /* Free policer counters. */
> > -     if (fm->policer_stats.pass_cnt)
> > -             mlx5_counter_free(dev, fm->policer_stats.pass_cnt);
> > -     if (fm->policer_stats.drop_cnt)
> > -             mlx5_counter_free(dev, fm->policer_stats.drop_cnt);
> > -     if (priv->sh->meter_aso_en)
> > -             mlx5_flow_mtr_free(dev, mtr_idx);
> > -     else
> > -             mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR],
> > mtr_idx);
> > -     return -rte_mtr_error_set(error, -ret,
> > -                               RTE_MTR_ERROR_TYPE_UNSPECIFIED,
> > -                               NULL, "Failed to create devx meter.");
> > -}
> > -
> >  static int
> >  mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
> >                       struct mlx5_flow_meter_info *fm,
> > -                     const struct rte_flow_attr *attr,
> >                       uint32_t mtr_idx)
> >  {
> >       struct mlx5_priv *priv = dev->data->dev_private;
> > @@ -810,15 +572,12 @@ mlx5_flow_meter_params_flush(struct
> > rte_eth_dev *dev,
> >               legacy_fm = container_of(fm, struct
> > mlx5_legacy_flow_meter, fm);
> >               TAILQ_REMOVE(fms, legacy_fm, next);
> >       }
> > -     /* Free policer counters. */
> > -     if (fm->policer_stats.pass_cnt)
> > -             mlx5_counter_free(dev, fm->policer_stats.pass_cnt);
> > -     if (fm->policer_stats.drop_cnt)
> > -             mlx5_counter_free(dev, fm->policer_stats.drop_cnt);
> > +     /* Free drop counters. */
> > +     if (fm->drop_cnt)
> > +             mlx5_counter_free(dev, fm->drop_cnt);
> >       /* Free meter flow table. */
> >       if (fm->flow_ipool)
> >               mlx5_ipool_destroy(fm->flow_ipool);
> > -     mlx5_flow_destroy_policer_rules(dev, fm, attr);
> >       mlx5_flow_destroy_mtr_tbls(dev, fm->mfts);
> >       if (priv->sh->meter_aso_en)
> >               mlx5_flow_mtr_free(dev, mtr_idx);
> > @@ -847,11 +606,6 @@ mlx5_flow_meter_destroy(struct rte_eth_dev
> > *dev, uint32_t meter_id,
> >  {
> >       struct mlx5_priv *priv = dev->data->dev_private;
> >       struct mlx5_flow_meter_info *fm;
> > -     const struct rte_flow_attr attr = {
> > -                             .ingress = 1,
> > -                             .egress = 1,
> > -                             .transfer = priv->config.dv_esw_en ? 1 : 0,
> > -                     };
> >       uint32_t mtr_idx = 0;
> >
> >       if (!priv->mtr_en)
> > @@ -876,7 +630,7 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev,
> > uint32_t meter_id,
> >                               "Fail to delete ASO Meter in index table.");
> >       }
> >       /* Destroy the meter profile. */
> > -     if (mlx5_flow_meter_params_flush(dev, fm, &attr, mtr_idx))
> > +     if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
> >               return -rte_mtr_error_set(error, EINVAL,
> >
> >       RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
> >                                       NULL, "MTR object meter profile
> > invalid.");
> > @@ -1102,13 +856,6 @@ mlx5_flow_meter_stats_update(struct
> > rte_eth_dev *dev,
> >  {
> >       struct mlx5_priv *priv = dev->data->dev_private;
> >       struct mlx5_flow_meter_info *fm;
> > -     const struct rte_flow_attr attr = {
> > -                             .ingress = 1,
> > -                             .egress = 1,
> > -                             .transfer = priv->config.dv_esw_en ? 1 : 0,
> > -                     };
> > -     bool need_updated = false;
> > -     struct mlx5_flow_policer_stats old_policer_stats;
> >
> >       if (!priv->mtr_en)
> >               return -rte_mtr_error_set(error, ENOTSUP,
> > @@ -1120,69 +867,6 @@ mlx5_flow_meter_stats_update(struct
> > rte_eth_dev *dev,
> >               return -rte_mtr_error_set(error, ENOENT,
> >                                         RTE_MTR_ERROR_TYPE_MTR_ID,
> >                                         NULL, "Meter object id not valid.");
> > -     old_policer_stats.pass_cnt = 0;
> > -     old_policer_stats.drop_cnt = 0;
> > -     if (!!((RTE_MTR_STATS_N_PKTS_GREEN |
> > -                             RTE_MTR_STATS_N_BYTES_GREEN) &
> > stats_mask) !=
> > -             !!fm->policer_stats.pass_cnt) {
> > -             need_updated = true;
> > -             if (fm->policer_stats.pass_cnt) {
> > -                     old_policer_stats.pass_cnt = fm-
> > >policer_stats.pass_cnt;
> > -                     fm->policer_stats.pass_cnt = 0;
> > -             } else {
> > -                     fm->policer_stats.pass_cnt =
> > -                             mlx5_counter_alloc(dev);
> > -                     if (!fm->policer_stats.pass_cnt)
> > -                             return -rte_mtr_error_set(error, ENOMEM,
> > -
> > RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
> > -                                       "Counter alloc failed for meter.");
> > -             }
> > -     }
> > -     if (!!((RTE_MTR_STATS_N_PKTS_RED |
> > RTE_MTR_STATS_N_BYTES_RED |
> > -             RTE_MTR_STATS_N_PKTS_DROPPED |
> > RTE_MTR_STATS_N_BYTES_DROPPED) &
> > -             stats_mask) !=
> > -             !!fm->policer_stats.drop_cnt) {
> > -             need_updated = true;
> > -             if (fm->policer_stats.drop_cnt) {
> > -                     old_policer_stats.drop_cnt = fm-
> > >policer_stats.drop_cnt;
> > -                     fm->policer_stats.drop_cnt = 0;
> > -             } else {
> > -                     fm->policer_stats.drop_cnt =
> > -                             mlx5_counter_alloc(dev);
> > -                     if (!fm->policer_stats.drop_cnt)
> > -                             return -rte_mtr_error_set(error, ENOMEM,
> > -
> > RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
> > -                                       "Counter alloc failed for meter.");
> > -             }
> > -     }
> > -     if (need_updated) {
> > -             if (mlx5_flow_prepare_policer_rules(dev, fm, &attr)) {
> > -                     if (fm->policer_stats.pass_cnt &&
> > -                             fm->policer_stats.pass_cnt !=
> > -                             old_policer_stats.pass_cnt)
> > -                             mlx5_counter_free(dev,
> > -                                     fm->policer_stats.pass_cnt);
> > -                     fm->policer_stats.pass_cnt =
> > -                                     old_policer_stats.pass_cnt;
> > -                     if (fm->policer_stats.drop_cnt &&
> > -                             fm->policer_stats.drop_cnt !=
> > -                             old_policer_stats.drop_cnt)
> > -                             mlx5_counter_free(dev,
> > -                                     fm->policer_stats.drop_cnt);
> > -                     fm->policer_stats.pass_cnt =
> > -                                     old_policer_stats.pass_cnt;
> > -                     return -rte_mtr_error_set(error, ENOTSUP,
> > -                             RTE_MTR_ERROR_TYPE_UNSPECIFIED,
> > -                             NULL, "Failed to create meter policer rules.");
> > -             }
> > -             /* Free old policer counters. */
> > -             if (old_policer_stats.pass_cnt)
> > -                     mlx5_counter_free(dev,
> > -                             old_policer_stats.pass_cnt);
> > -             if (old_policer_stats.drop_cnt)
> > -                     mlx5_counter_free(dev,
> > -                             old_policer_stats.drop_cnt);
> > -     }
> >       mlx5_flow_meter_stats_enable_update(fm, stats_mask);
> >       return 0;
> >  }
> > @@ -1216,7 +900,6 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev
> > *dev,
> >  {
> >       struct mlx5_priv *priv = dev->data->dev_private;
> >       struct mlx5_flow_meter_info *fm;
> > -     struct mlx5_flow_policer_stats *ps;
> >       uint64_t pkts;
> >       uint64_t bytes;
> >       int ret = 0;
> > @@ -1231,35 +914,14 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev
> > *dev,
> >               return -rte_mtr_error_set(error, ENOENT,
> >                                         RTE_MTR_ERROR_TYPE_MTR_ID,
> >                                         NULL, "Meter object id not valid.");
> > -     ps = &fm->policer_stats;
> >       *stats_mask = 0;
> > -     if (fm->green_bytes)
> > -             *stats_mask |= RTE_MTR_STATS_N_BYTES_GREEN;
> > -     if (fm->green_pkts)
> > -             *stats_mask |= RTE_MTR_STATS_N_PKTS_GREEN;
> > -     if (fm->red_bytes)
> > -             *stats_mask |= RTE_MTR_STATS_N_BYTES_RED;
> > -     if (fm->red_pkts)
> > -             *stats_mask |= RTE_MTR_STATS_N_PKTS_RED;
> >       if (fm->bytes_dropped)
> >               *stats_mask |= RTE_MTR_STATS_N_BYTES_DROPPED;
> >       if (fm->pkts_dropped)
> >               *stats_mask |= RTE_MTR_STATS_N_PKTS_DROPPED;
> >       memset(stats, 0, sizeof(*stats));
> > -     if (ps->pass_cnt) {
> > -             ret = mlx5_counter_query(dev, ps->pass_cnt, clear, &pkts,
> > -                                              &bytes);
> > -             if (ret)
> > -                     goto error;
> > -             /* If need to read the packets, set it. */
> > -             if (fm->green_pkts)
> > -                     stats->n_pkts[RTE_COLOR_GREEN] = pkts;
> > -             /* If need to read the bytes, set it. */
> > -             if (fm->green_bytes)
> > -                     stats->n_bytes[RTE_COLOR_GREEN] = bytes;
> > -     }
> > -     if (ps->drop_cnt) {
> > -             ret = mlx5_counter_query(dev, ps->drop_cnt, clear, &pkts,
> > +     if (fm->drop_cnt) {
> > +             ret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts,
> >                                                &bytes);
> >               if (ret)
> >                       goto error;
> > @@ -1273,20 +935,18 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev
> > *dev,
> >       return 0;
> >  error:
> >       return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS,
> > NULL,
> > -                              "Failed to read policer counters.");
> > +                              "Failed to read meter drop counters.");
> >  }
> >
> >  static const struct rte_mtr_ops mlx5_flow_mtr_ops = {
> >       .capabilities_get = mlx5_flow_mtr_cap_get,
> >       .meter_profile_add = mlx5_flow_meter_profile_add,
> >       .meter_profile_delete = mlx5_flow_meter_profile_delete,
> > -     .create = mlx5_flow_meter_create,
> >       .destroy = mlx5_flow_meter_destroy,
> >       .meter_enable = mlx5_flow_meter_enable,
> >       .meter_disable = mlx5_flow_meter_disable,
> >       .meter_profile_update = mlx5_flow_meter_profile_update,
> >       .meter_dscp_table_update = NULL,
> > -     .policer_actions_update = NULL,
> >       .stats_update = mlx5_flow_meter_stats_update,
> >       .stats_read = mlx5_flow_meter_stats_read,
> >  };
> > @@ -1344,12 +1004,11 @@ mlx5_flow_meter_find(struct mlx5_priv *priv,
> > uint32_t meter_id,
> >               aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
> >               /* Remove reference taken by the mlx5_l3t_get_entry. */
> >               mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);
> > -             MLX5_ASSERT(meter_id == aso_mtr->fm.meter_id);
> >               rte_spinlock_unlock(&mtrmng->mtrsl);
> >               return &aso_mtr->fm;
> >       }
> >       TAILQ_FOREACH(legacy_fm, fms, next)
> > -             if (meter_id == legacy_fm->fm.meter_id) {
> > +             if (meter_id == legacy_fm->meter_id) {
> >                       if (mtr_idx)
> >                               *mtr_idx = legacy_fm->idx;
> >                       return &legacy_fm->fm;
> > @@ -1517,11 +1176,6 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev,
> > struct rte_mtr_error *error)
> >       struct mlx5_legacy_flow_meter *legacy_fm;
> >       struct mlx5_flow_meter_info *fm;
> >       struct mlx5_aso_mtr_pool *mtr_pool;
> > -     const struct rte_flow_attr attr = {
> > -                             .ingress = 1,
> > -                             .egress = 1,
> > -                             .transfer = priv->config.dv_esw_en ? 1 : 0,
> > -                     };
> >       void *tmp;
> >       uint32_t i, offset, mtr_idx;
> >
> > @@ -1533,9 +1187,8 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev,
> > struct rte_mtr_error *error)
> >                               offset++) {
> >                               fm = &mtr_pool->mtrs[offset].fm;
> >                               mtr_idx = MLX5_MAKE_MTR_IDX(i, offset);
> > -                             if (fm->meter_id != UINT32_MAX &&
> > -
> >       mlx5_flow_meter_params_flush(dev,
> > -                                             fm, &attr, mtr_idx))
> > +                             if (mlx5_flow_meter_params_flush(dev,
> > +                                             fm, mtr_idx))
> >                                       return -rte_mtr_error_set
> >                                       (error, EINVAL,
> >
> >       RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
> > @@ -1545,7 +1198,7 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev,
> > struct rte_mtr_error *error)
> >       } else {
> >               TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) {
> >                       fm = &legacy_fm->fm;
> > -                     if (mlx5_flow_meter_params_flush(dev, fm, &attr,
> > 0))
> > +                     if (mlx5_flow_meter_params_flush(dev, fm, 0))
> >                               return -rte_mtr_error_set(error, EINVAL,
> >
> >       RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
> >                                       NULL, "MTR object meter profile
> > invalid.");
> > diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c
> > b/drivers/net/softnic/rte_eth_softnic_flow.c
> > index 7925bad1c0..27eaf380cd 100644
> > --- a/drivers/net/softnic/rte_eth_softnic_flow.c
> > +++ b/drivers/net/softnic/rte_eth_softnic_flow.c
> > @@ -1166,6 +1166,7 @@ flow_rule_action_get(struct pmd_internals
> > *softnic,
> >  {
> >       struct softnic_table_action_profile *profile;
> >       struct softnic_table_action_profile_params *params;
> > +     struct softnic_mtr_meter_policy *policy;
> >       int n_jump_queue_rss_drop = 0;
> >       int n_count = 0;
> >       int n_mark = 0;
> > @@ -1621,15 +1622,25 @@ flow_rule_action_get(struct pmd_internals
> > *softnic,
> >                                       return -1;
> >                               }
> >                       }
> > -
> > +                     /* Meter policy must exist */
> > +                     policy = softnic_mtr_meter_policy_find(softnic,
> > +                                     m->params.meter_policy_id);
> > +                     if (policy == NULL) {
> > +                             rte_flow_error_set(error,
> > +                                             EINVAL,
> > +
> >       RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> > +                                             NULL,
> > +                                             "METER: fail to find meter
> > policy");
> > +                             return -1;
> > +                     }
> >                       /* RTE_TABLE_ACTION_METER */
> >                       rule_action->mtr.mtr[0].meter_profile_id =
> > meter_profile_id;
> >                       rule_action->mtr.mtr[0].policer[RTE_COLOR_GREEN]
> > =
> > -                             softnic_table_action_policer(m-
> > >params.action[RTE_COLOR_GREEN]);
> > +                             policy->policer[RTE_COLOR_GREEN];
> >                       rule_action-
> > >mtr.mtr[0].policer[RTE_COLOR_YELLOW] =
> > -                             softnic_table_action_policer(m-
> > >params.action[RTE_COLOR_YELLOW]);
> > +                             policy->policer[RTE_COLOR_YELLOW];
> >                       rule_action->mtr.mtr[0].policer[RTE_COLOR_RED] =
> > -                             softnic_table_action_policer(m-
> > >params.action[RTE_COLOR_RED]);
> > +                             policy->policer[RTE_COLOR_RED];
> >                       rule_action->mtr.tc_mask = 1;
> >                       rule_action->action_mask |= 1 <<
> > RTE_TABLE_ACTION_MTR;
> >                       break;
> > diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h
> > b/drivers/net/softnic/rte_eth_softnic_internals.h
> > index faf90a5a8c..1b3186ef0b 100644
> > --- a/drivers/net/softnic/rte_eth_softnic_internals.h
> > +++ b/drivers/net/softnic/rte_eth_softnic_internals.h
> > @@ -83,6 +83,16 @@ struct softnic_mtr_meter_profile {
> >
> >  TAILQ_HEAD(softnic_mtr_meter_profile_list, softnic_mtr_meter_profile);
> >
> > +/* MTR meter policy */
> > +struct softnic_mtr_meter_policy {
> > +     TAILQ_ENTRY(softnic_mtr_meter_policy) node;
> > +     uint32_t meter_policy_id;
> > +     enum rte_table_action_policer policer[RTE_COLORS];
> > +     uint32_t n_users;
> > +};
> > +
> > +TAILQ_HEAD(softnic_mtr_meter_policy_list, softnic_mtr_meter_policy);
> > +
> >  /* MTR meter object */
> >  struct softnic_mtr {
> >       TAILQ_ENTRY(softnic_mtr) node;
> > @@ -95,6 +105,7 @@ TAILQ_HEAD(softnic_mtr_list, softnic_mtr);
> >
> >  struct mtr_internals {
> >       struct softnic_mtr_meter_profile_list meter_profiles;
> > +     struct softnic_mtr_meter_policy_list meter_policies;
> >       struct softnic_mtr_list mtrs;
> >  };
> >
> > @@ -678,6 +689,10 @@ struct softnic_mtr_meter_profile *
> >  softnic_mtr_meter_profile_find(struct pmd_internals *p,
> >       uint32_t meter_profile_id);
> >
> > +struct softnic_mtr_meter_policy *
> > +softnic_mtr_meter_policy_find(struct pmd_internals *p,
> > +     uint32_t meter_policy_id);
> > +
> >  extern const struct rte_mtr_ops pmd_mtr_ops;
> >
> >  /**
> > @@ -841,9 +856,6 @@ softnic_table_action_profile_create(struct
> > pmd_internals *p,
> >       const char *name,
> >       struct softnic_table_action_profile_params *params);
> >
> > -enum rte_table_action_policer
> > -softnic_table_action_policer(enum rte_mtr_policer_action action);
> > -
> >  /**
> >   * Pipeline
> >   */
> > diff --git a/drivers/net/softnic/rte_eth_softnic_meter.c
> > b/drivers/net/softnic/rte_eth_softnic_meter.c
> > index 31a2a0e6d9..2a05a85cdb 100644
> > --- a/drivers/net/softnic/rte_eth_softnic_meter.c
> > +++ b/drivers/net/softnic/rte_eth_softnic_meter.c
> > @@ -65,27 +65,6 @@ softnic_mtr_meter_profile_find(struct pmd_internals
> > *p,
> >       return NULL;
> >  }
> >
> > -enum rte_table_action_policer
> > -softnic_table_action_policer(enum rte_mtr_policer_action action)
> > -{
> > -     switch (action) {
> > -     case MTR_POLICER_ACTION_COLOR_GREEN:
> > -             return RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
> > -
> > -             /* FALLTHROUGH */
> > -     case MTR_POLICER_ACTION_COLOR_YELLOW:
> > -             return RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
> > -
> > -             /* FALLTHROUGH */
> > -     case MTR_POLICER_ACTION_COLOR_RED:
> > -             return RTE_TABLE_ACTION_POLICER_COLOR_RED;
> > -
> > -             /* FALLTHROUGH */
> > -     default:
> > -             return RTE_TABLE_ACTION_POLICER_DROP;
> > -     }
> > -}
> > -
> >  static int
> >  meter_profile_check(struct rte_eth_dev *dev,
> >       uint32_t meter_profile_id,
> > @@ -200,6 +179,129 @@ pmd_mtr_meter_profile_delete(struct
> > rte_eth_dev *dev,
> >       return 0;
> >  }
> >
> > +struct softnic_mtr_meter_policy *
> > +softnic_mtr_meter_policy_find(struct pmd_internals *p,
> > +     uint32_t meter_policy_id)
> > +{
> > +     struct softnic_mtr_meter_policy_list *mpl = &p-
> > >mtr.meter_policies;
> > +     struct softnic_mtr_meter_policy *mp;
> > +
> > +     TAILQ_FOREACH(mp, mpl, node)
> > +             if (meter_policy_id == mp->meter_policy_id)
> > +                     return mp;
> > +
> > +     return NULL;
> > +}
> > +
> > +/* MTR meter policy create */
> > +static int
> > +pmd_mtr_meter_policy_create(struct rte_eth_dev *dev,
> > +     uint32_t meter_policy_id,
> > +     struct rte_mtr_meter_policy_params *policy,
> > +     struct rte_mtr_error *error)
> > +{
> > +     struct pmd_internals *p = dev->data->dev_private;
> > +     struct softnic_mtr_meter_policy_list *mpl = &p-
> > >mtr.meter_policies;
> > +     struct softnic_mtr_meter_policy *mp;
> > +     const struct rte_flow_action *act;
> > +     const struct rte_flow_action_meter_color *recolor;
> > +     uint32_t i;
> > +
> > +     /* Meter policy ID must be valid. */
> > +     if (meter_policy_id == UINT32_MAX)
> > +             return -rte_mtr_error_set(error,
> > +                     EINVAL,
> > +                     RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
> > +                     NULL,
> > +                     "Meter policy id not valid");
> > +
> > +     for (i = 0; i < RTE_COLORS; i++) {
> > +             act = policy->actions[i];
> > +             if (act && act->type !=
> > RTE_FLOW_ACTION_TYPE_METER_COLOR &&
> > +                     act->type != RTE_FLOW_ACTION_TYPE_DROP)
> > +                     return -rte_mtr_error_set(error,
> > +                             EINVAL,
> > +                             RTE_MTR_ERROR_TYPE_METER_POLICY,
> > +                             NULL,
> > +                             "Action invalid");
> > +     }
> > +
> > +     /* Memory allocation */
> > +     mp = calloc(1, sizeof(struct softnic_mtr_meter_policy));
> > +     if (mp == NULL)
> > +             return -rte_mtr_error_set(error,
> > +                     ENOMEM,
> > +                     RTE_MTR_ERROR_TYPE_UNSPECIFIED,
> > +                     NULL,
> > +                     "Memory alloc failed");
> > +
> > +     /* Fill in */
> > +     mp->meter_policy_id = meter_policy_id;
> > +     for (i = 0; i < RTE_COLORS; i++) {
> > +             mp->policer[i] = RTE_TABLE_ACTION_POLICER_DROP;
> > +             act = policy->actions[i];
> > +             if (!act)
> > +                     continue;
> > +             if (act->type == RTE_FLOW_ACTION_TYPE_METER_COLOR) {
> > +                     recolor = act->conf;
> > +                     switch (recolor->color) {
> > +                     case RTE_COLOR_GREEN:
> > +                             mp->policer[i] =
> > +
> >       RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
> > +                             break;
> > +                     case RTE_COLOR_YELLOW:
> > +                             mp->policer[i] =
> > +
> >       RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
> > +                             break;
> > +                     case RTE_COLOR_RED:
> > +                             mp->policer[i] =
> > +                             RTE_TABLE_ACTION_POLICER_COLOR_RED;
> > +                             break;
> > +                     default:
> > +                             break;
> > +                     }
> > +             }
> > +     }
> > +
> > +     /* Add to list */
> > +     TAILQ_INSERT_TAIL(mpl, mp, node);
> > +
> > +     return 0;
> > +}
> > +
> > +/* MTR meter policy delete */
> > +static int
> > +pmd_mtr_meter_policy_delete(struct rte_eth_dev *dev,
> > +     uint32_t meter_policy_id,
> > +     struct rte_mtr_error *error)
> > +{
> > +     struct pmd_internals *p = dev->data->dev_private;
> > +     struct softnic_mtr_meter_policy *mp;
> > +
> > +     /* Meter policy must exist */
> > +     mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
> > +     if (mp == NULL)
> > +             return -rte_mtr_error_set(error,
> > +                     EINVAL,
> > +                     RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
> > +                     NULL,
> > +                     "Meter policy id invalid");
> > +
> > +     /* Check unused */
> > +     if (mp->n_users)
> > +             return -rte_mtr_error_set(error,
> > +                     EBUSY,
> > +                     RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
> > +                     NULL,
> > +                     "Meter policy in use");
> > +
> > +     /* Remove from list */
> > +     TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
> > +     free(mp);
> > +
> > +     return 0;
> > +}
> > +
> >  struct softnic_mtr *
> >  softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
> >  {
> > @@ -267,6 +369,7 @@ pmd_mtr_create(struct rte_eth_dev *dev,
> >       struct pmd_internals *p = dev->data->dev_private;
> >       struct softnic_mtr_list *ml = &p->mtr.mtrs;
> >       struct softnic_mtr_meter_profile *mp;
> > +     struct softnic_mtr_meter_policy *policy;
> >       struct softnic_mtr *m;
> >       int status;
> >
> > @@ -284,6 +387,16 @@ pmd_mtr_create(struct rte_eth_dev *dev,
> >                       NULL,
> >                       "Meter profile id not valid");
> >
> > +     /* Meter policy must exist */
> > +     policy = softnic_mtr_meter_policy_find(p, params-
> > >meter_policy_id);
> > +     if (policy == NULL) {
> > +             return -rte_mtr_error_set(error,
> > +                             EINVAL,
> > +                             RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
> > +                             NULL,
> > +                             "Meter policy id invalid");
> > +     }
> > +
> >       /* Memory allocation */
> >       m = calloc(1, sizeof(struct softnic_mtr));
> >       if (m == NULL)
> > @@ -302,6 +415,7 @@ pmd_mtr_create(struct rte_eth_dev *dev,
> >
> >       /* Update dependencies */
> >       mp->n_users++;
> > +     policy->n_users++;
> >
> >       return 0;
> >  }
> > @@ -316,6 +430,7 @@ pmd_mtr_destroy(struct rte_eth_dev *dev,
> >       struct softnic_mtr_list *ml = &p->mtr.mtrs;
> >       struct softnic_mtr_meter_profile *mp;
> >       struct softnic_mtr *m;
> > +     struct softnic_mtr_meter_policy *policy;
> >
> >       /* MTR object must exist */
> >       m = softnic_mtr_find(p, mtr_id);
> > @@ -343,8 +458,18 @@ pmd_mtr_destroy(struct rte_eth_dev *dev,
> >                       NULL,
> >                       "MTR object meter profile invalid");
> >
> > +     /* Meter policy must exist */
> > +     policy = softnic_mtr_meter_policy_find(p, m-
> > >params.meter_policy_id);
> > +     if (policy == NULL)
> > +             return -rte_mtr_error_set(error,
> > +                     EINVAL,
> > +                     RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
> > +                     NULL,
> > +                     "MTR object meter policy invalid");
> > +
> >       /* Update dependencies */
> >       mp->n_users--;
> > +     policy->n_users--;
> >
> >       /* Remove from list */
> >       TAILQ_REMOVE(ml, m, node);
> > @@ -506,18 +631,18 @@ pmd_mtr_meter_dscp_table_update(struct
> > rte_eth_dev *dev,
> >       return 0;
> >  }
> >
> > -/* MTR object policer action update */
> > +/* MTR object policy update */
> >  static int
> > -pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,
> > +pmd_mtr_meter_policy_update(struct rte_eth_dev *dev,
> >       uint32_t mtr_id,
> > -     uint32_t action_mask,
> > -     enum rte_mtr_policer_action *actions,
> > +     uint32_t meter_policy_id,
> >       struct rte_mtr_error *error)
> >  {
> >       struct pmd_internals *p = dev->data->dev_private;
> >       struct softnic_mtr *m;
> >       uint32_t i;
> >       int status;
> > +     struct softnic_mtr_meter_policy *mp_new, *mp_old;
> >
> >       /* MTR object id must be valid */
> >       m = softnic_mtr_find(p, mtr_id);
> > @@ -527,29 +652,14 @@ pmd_mtr_policer_actions_update(struct
> > rte_eth_dev *dev,
> >                       RTE_MTR_ERROR_TYPE_MTR_ID,
> >                       NULL,
> >                       "MTR object id not valid");
> > -
> > -     /* Valid policer actions */
> > -     if (actions == NULL)
> > +     /* Meter policy must exist */
> > +     mp_new = softnic_mtr_meter_policy_find(p, meter_policy_id);
> > +     if (mp_new == NULL)
> >               return -rte_mtr_error_set(error,
> >                       EINVAL,
> > -                     RTE_MTR_ERROR_TYPE_UNSPECIFIED,
> > +                     RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
> >                       NULL,
> > -                     "Invalid actions");
> > -
> > -     for (i = 0; i < RTE_COLORS; i++) {
> > -             if (action_mask & (1 << i)) {
> > -                     if (actions[i] !=
> > MTR_POLICER_ACTION_COLOR_GREEN  &&
> > -                             actions[i] !=
> > MTR_POLICER_ACTION_COLOR_YELLOW &&
> > -                             actions[i] !=
> > MTR_POLICER_ACTION_COLOR_RED &&
> > -                             actions[i] != MTR_POLICER_ACTION_DROP) {
> > -                             return -rte_mtr_error_set(error,
> > -                                     EINVAL,
> > -
> >       RTE_MTR_ERROR_TYPE_UNSPECIFIED,
> > -                                     NULL,
> > -                                     " Invalid action value");
> > -                     }
> > -             }
> > -     }
> > +                     "Meter policy id invalid");
> >
> >       /* MTR object owner valid? */
> >       if (m->flow) {
> > @@ -561,9 +671,7 @@ pmd_mtr_policer_actions_update(struct
> > rte_eth_dev *dev,
> >
> >               /* Set action */
> >               for (i = 0; i < RTE_COLORS; i++)
> > -                     if (action_mask & (1 << i))
> > -                             action.mtr.mtr[0].policer[i] =
> > -
> >       softnic_table_action_policer(actions[i]);
> > +                     action.mtr.mtr[0].policer[i] = mp_new->policer[i];
> >
> >               /* Re-add the rule */
> >               status = softnic_pipeline_table_rule_add(p,
> > @@ -587,10 +695,20 @@ pmd_mtr_policer_actions_update(struct
> > rte_eth_dev *dev,
> >                       1, NULL, 1);
> >       }
> >
> > -     /* Meter: Update policer actions */
> > -     for (i = 0; i < RTE_COLORS; i++)
> > -             if (action_mask & (1 << i))
> > -                     m->params.action[i] = actions[i];
> > +     mp_old = softnic_mtr_meter_policy_find(p, m-
> > >params.meter_policy_id);
> > +     if (mp_old == NULL)
> > +             return -rte_mtr_error_set(error,
> > +                     EINVAL,
> > +                     RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
> > +                     NULL,
> > +                     "Old meter policy id invalid");
> > +
> > +     /* Meter: Set meter profile */
> > +     m->params.meter_policy_id = meter_policy_id;
> > +
> > +     /* Update dependencies*/
> > +     mp_old->n_users--;
> > +     mp_new->n_users++;
> >
> >       return 0;
> >  }
> > @@ -607,28 +725,40 @@ pmd_mtr_policer_actions_update(struct
> > rte_eth_dev *dev,
> >
> >  /* MTR object stats read */
> >  static void
> > -mtr_stats_convert(struct softnic_mtr *m,
> > +mtr_stats_convert(struct pmd_internals *p,
> > +     struct softnic_mtr *m,
> >       struct rte_table_action_mtr_counters_tc *in,
> >       struct rte_mtr_stats *out,
> >       uint64_t *out_mask)
> >  {
> > +     struct softnic_mtr_meter_policy *mp;
> > +
> >       memset(&out, 0, sizeof(out));
> >       *out_mask = 0;
> >
> > +     /* Meter policy must exist */
> > +     mp = softnic_mtr_meter_policy_find(p, m-
> > >params.meter_policy_id);
> > +     if (mp == NULL)
> > +             return;
> > +
> >       if (in->n_packets_valid) {
> >               uint32_t i;
> >
> >               for (i = 0; i < RTE_COLORS; i++) {
> > -                     if (m->params.action[i] ==
> > MTR_POLICER_ACTION_COLOR_GREEN)
> > +                     if (mp->policer[i] ==
> > +
> >       RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
> >                               out->n_pkts[RTE_COLOR_GREEN] += in-
> > >n_packets[i];
> >
> > -                     if (m->params.action[i] ==
> > MTR_POLICER_ACTION_COLOR_YELLOW)
> > +                     if (mp->policer[i] ==
> > +
> >       RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
> >                               out->n_pkts[RTE_COLOR_YELLOW] += in-
> > >n_packets[i];
> >
> > -                     if (m->params.action[i] ==
> > MTR_POLICER_ACTION_COLOR_RED)
> > +                     if (mp->policer[i] ==
> > +                             RTE_TABLE_ACTION_POLICER_COLOR_RED)
> >                               out->n_pkts[RTE_COLOR_RED] += in-
> > >n_packets[i];
> >
> > -                     if (m->params.action[i] ==
> > MTR_POLICER_ACTION_DROP)
> > +                     if (mp->policer[i] ==
> > +                             RTE_TABLE_ACTION_POLICER_DROP)
> >                               out->n_pkts_dropped += in->n_packets[i];
> >               }
> >
> > @@ -639,16 +769,20 @@ mtr_stats_convert(struct softnic_mtr *m,
> >               uint32_t i;
> >
> >               for (i = 0; i < RTE_COLORS; i++) {
> > -                     if (m->params.action[i] ==
> > MTR_POLICER_ACTION_COLOR_GREEN)
> > +                     if (mp->policer[i] ==
> > +
> >       RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
> >                               out->n_bytes[RTE_COLOR_GREEN] += in-
> > >n_bytes[i];
> >
> > -                     if (m->params.action[i] ==
> > MTR_POLICER_ACTION_COLOR_YELLOW)
> > +                     if (mp->policer[i] ==
> > +
> >       RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
> >                               out->n_bytes[RTE_COLOR_YELLOW] += in-
> > >n_bytes[i];
> >
> > -                     if (m->params.action[i] ==
> > MTR_POLICER_ACTION_COLOR_RED)
> > +                     if (mp->policer[i] ==
> > +                             RTE_TABLE_ACTION_POLICER_COLOR_RED)
> >                               out->n_bytes[RTE_COLOR_RED] += in-
> > >n_bytes[i];
> >
> > -                     if (m->params.action[i] ==
> > MTR_POLICER_ACTION_DROP)
> > +                     if (mp->policer[i] ==
> > +                             RTE_TABLE_ACTION_POLICER_DROP)
> >                               out->n_bytes_dropped += in->n_bytes[i];
> >               }
> >
> > @@ -714,7 +848,8 @@ pmd_mtr_stats_read(struct rte_eth_dev *dev,
> >               struct rte_mtr_stats s;
> >               uint64_t s_mask = 0;
> >
> > -             mtr_stats_convert(m,
> > +             mtr_stats_convert(p,
> > +                     m,
> >                       &counters.stats[0],
> >                       &s,
> >                       &s_mask);
> > @@ -735,6 +870,9 @@ const struct rte_mtr_ops pmd_mtr_ops = {
> >       .meter_profile_add = pmd_mtr_meter_profile_add,
> >       .meter_profile_delete = pmd_mtr_meter_profile_delete,
> >
> > +     .meter_policy_create = pmd_mtr_meter_policy_create,
> > +     .meter_policy_delete = pmd_mtr_meter_policy_delete,
> > +
> >       .create = pmd_mtr_create,
> >       .destroy = pmd_mtr_destroy,
> >       .meter_enable = NULL,
> > @@ -742,7 +880,7 @@ const struct rte_mtr_ops pmd_mtr_ops = {
> >
> >       .meter_profile_update = pmd_mtr_meter_profile_update,
> >       .meter_dscp_table_update = pmd_mtr_meter_dscp_table_update,
> > -     .policer_actions_update = pmd_mtr_policer_actions_update,
> > +     .meter_policy_update = pmd_mtr_meter_policy_update,
> >       .stats_update = NULL,
> >
> >       .stats_read = pmd_mtr_stats_read,
> > diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
> > index 6cc57136ac..d4fd36dd0e 100644
> > --- a/lib/librte_ethdev/rte_flow.h
> > +++ b/lib/librte_ethdev/rte_flow.h
> > @@ -32,6 +32,7 @@
> >  #include <rte_ecpri.h>
> >  #include <rte_mbuf.h>
> >  #include <rte_mbuf_dyn.h>
> > +#include <rte_meter.h>
> >
> >  #ifdef __cplusplus
> >  extern "C" {
> > @@ -2267,6 +2268,14 @@ enum rte_flow_action_type {
> >        * See struct rte_flow_action_modify_field.
> >        */
> >       RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
> > +
> > +     /**
> > +      * Color the packet to reflect the meter color result.
> > +      * Set the meter color in the mbuf to the selected color.
> > +      *
> > +      * See struct rte_flow_action_meter_color.
> > +      */
> > +     RTE_FLOW_ACTION_TYPE_METER_COLOR,
> >  };
> >
> >  /**
> > @@ -2859,6 +2868,19 @@ struct rte_flow_action_set_dscp {
> >   */
> >  struct rte_flow_shared_action;
> >
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this structure may change without prior notice
> > + *
> > + * RTE_FLOW_ACTION_TYPE_METER_COLOR
> > + *
> > + * The meter color should be set in the packet meta-data
> > + * (i.e. struct rte_mbuf::sched::color).
> > + */
> > +struct rte_flow_action_meter_color {
> > +     enum rte_color color; /**< Packet color. */
> > +};
> > +
> >  /**
> >   * Field IDs for MODIFY_FIELD action.
> >   */
> > diff --git a/lib/librte_ethdev/rte_mtr.c b/lib/librte_ethdev/rte_mtr.c
> > index 3073ac03f2..9b03cf1d50 100644
> > --- a/lib/librte_ethdev/rte_mtr.c
> > +++ b/lib/librte_ethdev/rte_mtr.c
> > @@ -91,6 +91,40 @@ rte_mtr_meter_profile_delete(uint16_t port_id,
> >               meter_profile_id, error);
> >  }
> >
> > +/* MTR meter policy validate */
> > +int
> > +rte_mtr_meter_policy_validate(uint16_t port_id,
> > +     struct rte_mtr_meter_policy_params *policy,
> > +     struct rte_mtr_error *error)
> > +{
> > +     struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> > +     return RTE_MTR_FUNC(port_id, meter_policy_validate)(dev,
> > +             policy, error);
> > +}
> > +
> > +/* MTR meter policy create */
> > +int
> > +rte_mtr_meter_policy_create(uint16_t port_id,
> > +     uint32_t policy_id,
> > +     struct rte_mtr_meter_policy_params *policy,
> > +     struct rte_mtr_error *error)
> > +{
> > +     struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> > +     return RTE_MTR_FUNC(port_id, meter_policy_create)(dev,
> > +             policy_id, policy, error);
> > +}
> > +
> > +/** MTR meter policy delete */
> > +int
> > +rte_mtr_meter_policy_delete(uint16_t port_id,
> > +     uint32_t policy_id,
> > +     struct rte_mtr_error *error)
> > +{
> > +     struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> > +     return RTE_MTR_FUNC(port_id, meter_policy_delete)(dev,
> > +             policy_id, error);
> > +}
> > +
> >  /** MTR object create */
> >  int
> >  rte_mtr_create(uint16_t port_id,
> > @@ -149,29 +183,28 @@ rte_mtr_meter_profile_update(uint16_t port_id,
> >               mtr_id, meter_profile_id, error);
> >  }
> >
> > -/** MTR object meter DSCP table update */
> > +/** MTR object meter policy update */
> >  int
> > -rte_mtr_meter_dscp_table_update(uint16_t port_id,
> > +rte_mtr_meter_policy_update(uint16_t port_id,
> >       uint32_t mtr_id,
> > -     enum rte_color *dscp_table,
> > +     uint32_t meter_policy_id,
> >       struct rte_mtr_error *error)
> >  {
> >       struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> > -     return RTE_MTR_FUNC(port_id, meter_dscp_table_update)(dev,
> > -             mtr_id, dscp_table, error);
> > +     return RTE_MTR_FUNC(port_id, meter_policy_update)(dev,
> > +             mtr_id, meter_policy_id, error);
> >  }
> >
> > -/** MTR object policer action update */
> > +/** MTR object meter DSCP table update */
> >  int
> > -rte_mtr_policer_actions_update(uint16_t port_id,
> > +rte_mtr_meter_dscp_table_update(uint16_t port_id,
> >       uint32_t mtr_id,
> > -     uint32_t action_mask,
> > -     enum rte_mtr_policer_action *actions,
> > +     enum rte_color *dscp_table,
> >       struct rte_mtr_error *error)
> >  {
> >       struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> > -     return RTE_MTR_FUNC(port_id, policer_actions_update)(dev,
> > -             mtr_id, action_mask, actions, error);
> > +     return RTE_MTR_FUNC(port_id, meter_dscp_table_update)(dev,
> > +             mtr_id, dscp_table, error);
> >  }
> >
> >  /** MTR object enabled stats update */
> > diff --git a/lib/librte_ethdev/rte_mtr.h b/lib/librte_ethdev/rte_mtr.h
> > index 916a09c5c3..9f6f5e1a45 100644
> > --- a/lib/librte_ethdev/rte_mtr.h
> > +++ b/lib/librte_ethdev/rte_mtr.h
> > @@ -49,6 +49,7 @@
> >  #include <rte_compat.h>
> >  #include <rte_common.h>
> >  #include <rte_meter.h>
> > +#include <rte_flow.h>
> >
> >  #ifdef __cplusplus
> >  extern "C" {
> > @@ -175,20 +176,16 @@ struct rte_mtr_meter_profile {
> >  };
> >
> >  /**
> > - * Policer actions
> > + * Meter policy
> >   */
> > -enum rte_mtr_policer_action {
> > -     /** Recolor the packet as green. */
> > -     MTR_POLICER_ACTION_COLOR_GREEN = 0,
> > -
> > -     /** Recolor the packet as yellow. */
> > -     MTR_POLICER_ACTION_COLOR_YELLOW,
> > -
> > -     /** Recolor the packet as red. */
> > -     MTR_POLICER_ACTION_COLOR_RED,
> > -
> > -     /** Drop the packet. */
> > -     MTR_POLICER_ACTION_DROP,
> > +struct rte_mtr_meter_policy_params {
> > +     /**
> > +      * Policy action list per color.
> > +      * actions[i] potentially represents a chain of rte_flow actions
> > +      * terminated by the END action, exactly as specified by the rte_flow
> > +      * API for the flow definition, and not just a single action.
> > +      */
> > +     const struct rte_flow_action *actions[RTE_COLORS];
> >  };
> >
> >  /**
> > @@ -232,13 +229,13 @@ struct rte_mtr_params {
> >        */
> >       int meter_enable;
> >
> > -     /** Policer actions (per meter output color). */
> > -     enum rte_mtr_policer_action action[RTE_COLORS];
> > -
> >       /** Set of stats counters to be enabled.
> >        * @see enum rte_mtr_stats_type
> >        */
> >       uint64_t stats_mask;
> > +
> > +     /** Meter policy ID. */
> > +     uint32_t meter_policy_id;
> >  };
> >
> >  /**
> > @@ -324,6 +321,13 @@ struct rte_mtr_capabilities {
> >        */
> >       uint64_t meter_rate_max;
> >
> > +     /**
> > +      * Maximum number of policy objects that can have.
> > +      * The value of 0 is invalid. Policy must be supported for meter.
> > +      * The maximum value is *n_max*.
> > +      */
> > +     uint64_t meter_policy_n_max;
> > +
> >       /**
> >        * When non-zero, it indicates that color aware mode is supported
> > for
> >        * the srTCM RFC 2697 metering algorithm.
> > @@ -342,18 +346,6 @@ struct rte_mtr_capabilities {
> >        */
> >       int color_aware_trtcm_rfc4115_supported;
> >
> > -     /** When non-zero, it indicates that the policer packet recolor
> > actions
> > -      * are supported.
> > -      * @see enum rte_mtr_policer_action
> > -      */
> > -     int policer_action_recolor_supported;
> > -
> > -     /** When non-zero, it indicates that the policer packet drop action is
> > -      * supported.
> > -      * @see enum rte_mtr_policer_action
> > -      */
> > -     int policer_action_drop_supported;
> > -
> >       /** Set of supported statistics counter types.
> >        * @see enum rte_mtr_stats_type
> >        */
> > @@ -379,6 +371,8 @@ enum rte_mtr_error_type {
> >       RTE_MTR_ERROR_TYPE_STATS_MASK,
> >       RTE_MTR_ERROR_TYPE_STATS,
> >       RTE_MTR_ERROR_TYPE_SHARED,
> > +     RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
> > +     RTE_MTR_ERROR_TYPE_METER_POLICY,
> >  };
> >
> >  /**
> > @@ -462,6 +456,136 @@ rte_mtr_meter_profile_delete(uint16_t port_id,
> >       uint32_t meter_profile_id,
> >       struct rte_mtr_error *error);
> >
> > +/**
> > + * Check whether a meter policy can be created on a given port.
> > + *
> > + * The meter policy is validated for correctness and
> > + * whether it could be accepted by the device given sufficient resources.
> > + * The policy is checked against the current capability information
> > + * meter_policy_n_max configuration.
> > + * The policy may also optionally be validated against existing
> > + * device policy resources.
> > + * This function has no effect on the target device.
> > + *
> > + * @param[in] port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param[in] policy
> > + *   Associated action list per color.
> > + *   list NULL is legal and means no special action.
> > + *   (list terminated by the END action).
> > + * @param[out] error
> > + *   Error details. Filled in only on error, when not NULL.
> > + * @return
> > + *   0 on success, non-zero error code otherwise.
> > + */
> > +__rte_experimental
> > +int
> > +rte_mtr_meter_policy_validate(uint16_t port_id,
> > +     struct rte_mtr_meter_policy_params *policy,
> > +     struct rte_mtr_error *error);
> > +
> > +/**
> > + * Meter policy add
> > + *
> > + * Create a new meter policy. The new policy
> > + * is used to create single or multiple MTR objects.
> > + *
> 
> Maybe tweak the explanation a bit: The same policy can be used to create
> multiple MTR objects.
> 
Thanks, will add in V5 patch.

> > + * Two common examples to define meter policy action list:
> > + * Example #1: GREEN - GREEN, YELLOW - YELLOW, RED - RED
> > + *   struct rte_mtr_meter_policy_params policy_0 =
> > + *                                   (struct
> > rte_mtr_meter_policy_params) {
> > + *           .actions[RTE_COLOR_GREEN] = (struct rte_flow_action[]) {
> > + *                   {
> > + *                           .type =
> > RTE_FLOW_ACTION_TYPE_METER_COLOR,
> > + *                           .conf = &(struct
> > rte_flow_action_meter_color) {
> > + *                                   .color = RTE_COLOR_GREEN,
> > + *                           },
> > + *                   },
> > + *                   {
> > + *                           .type = RTE_FLOW_ACTION_TYPE_END,
> > + *                   },
> > + *           },
> > + *           .actions[RTE_COLOR_YELLOW] = (struct rte_flow_action[]) {
> > + *                   {
> > + *                           .type =
> > RTE_FLOW_ACTION_TYPE_METER_COLOR,
> > + *                           .conf = &(struct
> > rte_flow_action_meter_color) {
> > + *                                   .color = RTE_COLOR_YELLOW,
> > + *                           },
> > + *                   },
> > + *                   {
> > + *                   .type = RTE_FLOW_ACTION_TYPE_END,
> > + *                   },
> > + *           },
> > + *           .actions[RTE_COLOR_RED] = (struct rte_flow_action[]) {
> > + *                   {
> > + *                           .type =
> > RTE_FLOW_ACTION_TYPE_METER_COLOR,
> > + *                           .conf = &(struct
> > rte_flow_action_meter_color) {
> > + *                                   .color = RTE_COLOR_RED,
> > + *                           },
> > + *                   },
> > + *                   {
> > + *                           .type = RTE_FLOW_ACTION_TYPE_END,
> > + *                   },
> > + *           },
> > + *   };
> > + *
> > + * Example #2: GREEN - Do nothing, YELLOW - Do nothing, RED - DROP
> > + *   struct rte_mtr_meter_policy_params policy_1 =
> > + *                                   (struct
> > rte_mtr_meter_policy_params) {
> > + *           .actions[RTE_COLOR_GREEN] = NULL,
> > + *           .actions[RTE_COLOR_YELLOW] = NULL,
> > + *           .actions[RTE_COLOR_RED] = (struct rte_flow_action[]) {
> > + *                   {
> > + *                           .type = RTE_FLOW_ACTION_TYPE_DROP,
> > + *                   },
> > + *                   {
> > + *                           .type = RTE_FLOW_ACTION_TYPE_END,
> > + *                   },
> > + *           },
> > + *   };
> > + *
> 
> These two example policies should be available to be used straight away,
> please make them real data structures, not comments.
> 
> I suggest their names as: pass_color_policy_params and
> drop_red_policy_params.
>
Thanks. Will change the names. But it can not be real data structures, since it just one example define and no use code.
It will bring build as below:
error: 'drop_red_policy_params' defined but not used.
 User can copy these example to his .c file when it using rte_mtr_meter_policy_add().

> > + * @param[in] port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param[in] policy_id
> > + *   Policy identifier for the new meter policy.
> > + * @param[in] policy
> > + *   Associated actions per color.
> > + *   list NULL is legal and means no special action.
> > + *   Non-NULL list must be terminated.
> > + *   (list terminated by the END action).
> > + * @param[out] error
> > + *   Error details. Filled in only on error, when not NULL.
> > + * @return
> > + *   0 on success, non-zero error code otherwise.
> > + */
> > +__rte_experimental
> > +int
> > +rte_mtr_meter_policy_create(uint16_t port_id,
> 
> The name of this function at the top of its description is mentioned as "meter
> policy add", while this function name here is policy create, please align the
> two.
> 
> Since we already have other API functions in this file for profiles/policies with
> the naming convention of add/delete as opposed to create/destroy
> (rte_mtr_meter_profile_add  and rte_mtr_meter_profile_delete), please let's
> use the existing convention and call these ones rte_mtr_meter_policy_add
> and rte_mtr_meter_policy_delete.
> 
Thanks, will change it in V5 patch.

> > +     uint32_t policy_id,
> > +     struct rte_mtr_meter_policy_params *policy,
> > +     struct rte_mtr_error *error);
> > +
> > +/**
> > + * Meter policy delete
> > + *
> > + * Delete an existing meter policy. This operation fails when there is
> > + * currently at least one user (i.e. MTR object) of this policy.
> > + *
> > + * @param[in] port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param[in] policy_id
> > + *   Policy identifier.
> > + * @param[out] error
> > + *   Error details. Filled in only on error, when not NULL.
> > + * @return
> > + *   0 on success, non-zero error code otherwise.
> > + */
> > +__rte_experimental
> > +int
> > +rte_mtr_meter_policy_delete(uint16_t port_id,
> > +     uint32_t policy_id,
> > +     struct rte_mtr_error *error);
> > +
> >  /**
> >   * MTR object create
> >   *
> > @@ -587,18 +711,14 @@ rte_mtr_meter_profile_update(uint16_t port_id,
> >       struct rte_mtr_error *error);
> >
> >  /**
> > - * MTR object DSCP table update
> > + * MTR object meter policy update
> >   *
> >   * @param[in] port_id
> >   *   The port identifier of the Ethernet device.
> >   * @param[in] mtr_id
> >   *   MTR object ID. Needs to be valid.
> > - * @param[in] dscp_table
> > - *   When non-NULL: it points to a pre-allocated and pre-populated table
> > with
> > - *   exactly 64 elements providing the input color for each value of the
> > - *   IPv4/IPv6 Differentiated Services Code Point (DSCP) input packet field.
> > - *   When NULL: it is equivalent to setting this parameter to an “all-green”
> > - *   populated table (i.e. table with all the 64 elements set to green color).
> > + * @param[in] meter_policy_id
> > + *   Meter policy ID for the current MTR object. Needs to be valid.
> >   * @param[out] error
> >   *   Error details. Filled in only on error, when not NULL.
> >   * @return
> > @@ -606,26 +726,24 @@ rte_mtr_meter_profile_update(uint16_t port_id,
> >   */
> >  __rte_experimental
> >  int
> > -rte_mtr_meter_dscp_table_update(uint16_t port_id,
> > +rte_mtr_meter_policy_update(uint16_t port_id,
> >       uint32_t mtr_id,
> > -     enum rte_color *dscp_table,
> > +     uint32_t meter_policy_id,
> >       struct rte_mtr_error *error);
> >
> >  /**
> > - * MTR object policer actions update
> > + * MTR object DSCP table update
> >   *
> >   * @param[in] port_id
> >   *   The port identifier of the Ethernet device.
> >   * @param[in] mtr_id
> >   *   MTR object ID. Needs to be valid.
> > - * @param[in] action_mask
> > - *   Bit mask indicating which policer actions need to be updated. One or
> > more
> > - *   policer actions can be updated in a single function invocation. To update
> > - *   the policer action associated with color C, bit (1 << C) needs to be set in
> > - *   *action_mask* and element at position C in the *actions* array needs to
> > be
> > - *   valid.
> > - * @param[in] actions
> > - *   Pre-allocated and pre-populated array of policer actions.
> > + * @param[in] dscp_table
> > + *   When non-NULL: it points to a pre-allocated and pre-populated table
> > with
> > + *   exactly 64 elements providing the input color for each value of the
> > + *   IPv4/IPv6 Differentiated Services Code Point (DSCP) input packet field.
> > + *   When NULL: it is equivalent to setting this parameter to an “all-green”
> > + *   populated table (i.e. table with all the 64 elements set to green color).
> >   * @param[out] error
> >   *   Error details. Filled in only on error, when not NULL.
> >   * @return
> > @@ -633,10 +751,9 @@ rte_mtr_meter_dscp_table_update(uint16_t
> > port_id,
> >   */
> >  __rte_experimental
> >  int
> > -rte_mtr_policer_actions_update(uint16_t port_id,
> > +rte_mtr_meter_dscp_table_update(uint16_t port_id,
> >       uint32_t mtr_id,
> > -     uint32_t action_mask,
> > -     enum rte_mtr_policer_action *actions,
> > +     enum rte_color *dscp_table,
> >       struct rte_mtr_error *error);
> >
> >  /**
> > diff --git a/lib/librte_ethdev/rte_mtr_driver.h
> > b/lib/librte_ethdev/rte_mtr_driver.h
> > index a0ddc2b5f4..462a1e862c 100644
> > --- a/lib/librte_ethdev/rte_mtr_driver.h
> > +++ b/lib/librte_ethdev/rte_mtr_driver.h
> > @@ -41,6 +41,22 @@ typedef int (*rte_mtr_meter_profile_delete_t)(struct
> > rte_eth_dev *dev,
> >       struct rte_mtr_error *error);
> >  /**< @internal MTR meter profile delete */
> >
> > +typedef int (*rte_mtr_meter_policy_validate_t)(struct rte_eth_dev *dev,
> > +     struct rte_mtr_meter_policy_params *policy,
> > +     struct rte_mtr_error *error);
> > +/**< @internal MTR meter policy validate */
> > +
> > +typedef int (*rte_mtr_meter_policy_create_t)(struct rte_eth_dev *dev,
> > +     uint32_t policy_id,
> > +     struct rte_mtr_meter_policy_params *policy,
> > +     struct rte_mtr_error *error);
> > +/**< @internal MTR meter policy add */
> > +
> > +typedef int (*rte_mtr_meter_policy_delete_t)(struct rte_eth_dev *dev,
> > +     uint32_t policy_id,
> > +     struct rte_mtr_error *error);
> > +/**< @internal MTR meter policy delete */
> > +
> >  typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,
> >       uint32_t mtr_id,
> >       struct rte_mtr_params *params,
> > @@ -69,18 +85,17 @@ typedef int
> > (*rte_mtr_meter_profile_update_t)(struct rte_eth_dev *dev,
> >       struct rte_mtr_error *error);
> >  /**< @internal MTR object meter profile update */
> >
> > -typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev
> > *dev,
> > +typedef int (*rte_mtr_meter_policy_update_t)(struct rte_eth_dev *dev,
> >       uint32_t mtr_id,
> > -     enum rte_color *dscp_table,
> > +     uint32_t meter_policy_id,
> >       struct rte_mtr_error *error);
> > -/**< @internal MTR object meter DSCP table update */
> > +/**< @internal MTR object meter policy update */
> >
> > -typedef int (*rte_mtr_policer_actions_update_t)(struct rte_eth_dev *dev,
> > +typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev
> > *dev,
> >       uint32_t mtr_id,
> > -     uint32_t action_mask,
> > -     enum rte_mtr_policer_action *actions,
> > +     enum rte_color *dscp_table,
> >       struct rte_mtr_error *error);
> > -/**< @internal MTR object policer action update*/
> > +/**< @internal MTR object meter DSCP table update */
> >
> >  typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
> >       uint32_t mtr_id,
> > @@ -124,14 +139,23 @@ struct rte_mtr_ops {
> >       /** MTR object meter DSCP table update */
> >       rte_mtr_meter_dscp_table_update_t meter_dscp_table_update;
> >
> > -     /** MTR object policer action update */
> > -     rte_mtr_policer_actions_update_t policer_actions_update;
> > -
> >       /** MTR object enabled stats update */
> >       rte_mtr_stats_update_t stats_update;
> >
> >       /** MTR object stats read */
> >       rte_mtr_stats_read_t stats_read;
> > +
> > +     /** MTR meter policy validate */
> > +     rte_mtr_meter_policy_validate_t meter_policy_validate;
> > +
> > +     /** MTR meter policy create */
> > +     rte_mtr_meter_policy_create_t meter_policy_create;
> > +
> > +     /** MTR meter policy delete */
> > +     rte_mtr_meter_policy_delete_t meter_policy_delete;
> > +
> > +     /** MTR object meter policy update */
> > +     rte_mtr_meter_policy_update_t meter_policy_update;
> >  };
> >
> >  /**
> > diff --git a/lib/librte_ethdev/version.map b/lib/librte_ethdev/version.map
> > index 93ad388e96..0045baff8c 100644
> > --- a/lib/librte_ethdev/version.map
> > +++ b/lib/librte_ethdev/version.map
> > @@ -138,7 +138,6 @@ EXPERIMENTAL {
> >       rte_mtr_meter_profile_add;
> >       rte_mtr_meter_profile_delete;
> >       rte_mtr_meter_profile_update;
> > -     rte_mtr_policer_actions_update;
> >       rte_mtr_stats_read;
> >       rte_mtr_stats_update;
> >
> > @@ -246,6 +245,10 @@ EXPERIMENTAL {
> >
> >       # added in 21.05
> >       rte_eth_representor_info_get;
> > +     rte_mtr_meter_policy_create;
> > +     rte_mtr_meter_policy_delete;
> > +     rte_mtr_meter_policy_update;
> > +     rte_mtr_meter_policy_validate;
> >  };
> >
> >  INTERNAL {
> > --
> > 2.27.0
> 
> Regards,
> Cristian

  reply	other threads:[~2021-04-14  4:55 UTC|newest]

Thread overview: 78+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-18  8:58 [dpdk-dev] [PATCH 1/2] [RFC]: " Li Zhang
2021-03-18  8:58 ` [dpdk-dev] [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by the drivers Li Zhang
2021-03-23 21:33   ` Dumitrescu, Cristian
2021-03-25  8:21     ` Matan Azrad
2021-03-25 23:16       ` Ajit Khaparde
2021-03-29 19:56         ` Matan Azrad
2021-03-27 13:15       ` Jerin Jacob
2021-03-29 20:10         ` Matan Azrad
2021-03-31 10:22           ` Jerin Jacob
2021-03-23 21:02 ` [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API Dumitrescu, Cristian
2021-03-25  6:56   ` Matan Azrad
2021-03-29  9:23     ` Ori Kam
2021-03-29 16:24       ` Dumitrescu, Cristian
2021-04-01 13:13         ` Ori Kam
2021-04-01 13:35           ` Dumitrescu, Cristian
2021-04-01 14:22             ` Ori Kam
2021-03-29 16:08     ` Dumitrescu, Cristian
2021-03-29 20:43       ` Matan Azrad
2021-03-31 15:46         ` Dumitrescu, Cristian
2021-04-04 13:48           ` Matan Azrad
2021-03-29 10:38 ` Jerin Jacob
2021-03-29 20:31   ` Matan Azrad
2021-03-31 10:50     ` Jerin Jacob
2021-04-13  0:14 ` [dpdk-dev] [PATCH v3 0/2] Support " Li Zhang
2021-04-13  0:14   ` [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined " Li Zhang
2021-04-13 14:19     ` Dumitrescu, Cristian
2021-04-14  3:23       ` Li Zhang
2021-04-13 14:59     ` Dumitrescu, Cristian
2021-04-14  4:55       ` Li Zhang [this message]
2021-04-14  8:02         ` Thomas Monjalon
2021-04-14  8:31           ` Matan Azrad
2021-04-14  8:47           ` Asaf Penso
2021-04-14  8:59             ` Li Zhang
2021-04-14  9:04             ` Thomas Monjalon
2021-04-14 14:00             ` Dumitrescu, Cristian
2021-04-14 16:21               ` Li Zhang
2021-04-13 16:25     ` Kinsella, Ray
2021-04-13  0:14   ` [dpdk-dev] [PATCH v3 2/2] app/testpmd: support policy actions per color Li Zhang
2021-04-14  3:12 ` [dpdk-dev] [PATCH v4 0/2] Support meter policy API Li Zhang
2021-04-14  3:12   ` [dpdk-dev] [PATCH v4 1/2] ethdev: add pre-defined " Li Zhang
2021-04-14  3:12   ` [dpdk-dev] [PATCH v4 2/2] app/testpmd: support policy actions per color Li Zhang
2021-04-14  6:32 ` [dpdk-dev] [PATCH v5 0/2] Support meter policy API Li Zhang
2021-04-14  6:32   ` [dpdk-dev] [PATCH v5 1/2] ethdev: add pre-defined " Li Zhang
2021-04-14  6:32   ` [dpdk-dev] [PATCH v5 2/2] app/testpmd: support policy actions per color Li Zhang
2021-04-14  8:57 ` [dpdk-dev] [PATCH v6 0/2] Support meter policy API Li Zhang
2021-04-14  8:57   ` [dpdk-dev] [PATCH v6 1/2] ethdev: add pre-defined " Li Zhang
2021-04-14 16:16     ` Dumitrescu, Cristian
2021-04-15  1:59       ` Li Zhang
2021-04-14 22:21     ` Singh, Jasvinder
2021-04-15  2:00       ` Li Zhang
2021-04-14  8:58   ` [dpdk-dev] [PATCH v6 2/2] app/testpmd: support policy actions per color Li Zhang
2021-04-15  4:54 ` [dpdk-dev] [PATCH v7 0/2] Support meter policy API Li Zhang
2021-04-15  4:54   ` [dpdk-dev] [PATCH v7 1/2] ethdev: add pre-defined " Li Zhang
2021-04-15  4:54   ` [dpdk-dev] [PATCH v7 2/2] app/testpmd: support policy actions per color Li Zhang
2021-04-15  9:20 ` [dpdk-dev] [PATCH v8 0/2] Support meter policy API Li Zhang
2021-04-15  9:20   ` [dpdk-dev] [PATCH v8 1/2] ethdev: add pre-defined " Li Zhang
2021-04-15 15:13     ` Ori Kam
2021-04-19 12:34     ` Singh, Jasvinder
2021-04-19 16:13       ` Jiawei(Jonny) Wang
2021-04-15  9:20   ` [dpdk-dev] [PATCH v8 2/2] app/testpmd: support policy actions per color Li Zhang
2021-04-19 16:08   ` [dpdk-dev] [PATCH v9 0/2] Support meter policy API Jiawei Wang
2021-04-19 16:08     ` [dpdk-dev] [PATCH v9 1/2] ethdev: add pre-defined " Jiawei Wang
2021-04-20 11:18       ` Dumitrescu, Cristian
2021-04-20 12:55         ` Asaf Penso
2021-04-20 21:01           ` Dumitrescu, Cristian
2021-04-19 16:08     ` [dpdk-dev] [PATCH v9 2/2] app/testpmd: support policy actions per color Jiawei Wang
2021-04-20 11:36     ` [dpdk-dev] [PATCH v9 0/2] Support meter policy API Ferruh Yigit
2021-04-20 14:08       ` Jiawei(Jonny) Wang
2021-04-20 14:04     ` [dpdk-dev] [PATCH v10 " Jiawei Wang
2021-04-20 14:04       ` [dpdk-dev] [PATCH v10 1/2] ethdev: add pre-defined " Jiawei Wang
2021-04-20 17:12         ` Ajit Khaparde
2021-04-21 19:43         ` Thomas Monjalon
2021-04-22  1:29           ` Li Zhang
2021-04-20 14:04       ` [dpdk-dev] [PATCH v10 2/2] app/testpmd: support policy actions per color Jiawei Wang
2021-04-20 17:14         ` Ajit Khaparde
2021-04-21 10:23       ` [dpdk-dev] [PATCH v10 0/2] Support meter policy API Ferruh Yigit
2021-04-20 17:56 ` [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined " Stephen Hemminger
2021-04-21  2:49   ` Li Zhang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DM6PR12MB40900DAC1A159811EC6B80F0BF4E9@DM6PR12MB4090.namprd12.prod.outlook.com \
    --to=lizh@nvidia.com \
    --cc=andrew.rybchenko@oktetlabs.ru \
    --cc=cristian.dumitrescu@intel.com \
    --cc=dekelp@nvidia.com \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@intel.com \
    --cc=haifeil@nvidia.com \
    --cc=hemant.agrawal@nxp.com \
    --cc=jasvinder.singh@intel.com \
    --cc=jerinjacobk@gmail.com \
    --cc=jiaweiw@nvidia.com \
    --cc=lironh@marvell.com \
    --cc=matan@nvidia.com \
    --cc=mdr@ashroe.eu \
    --cc=nhorman@tuxdriver.com \
    --cc=orika@nvidia.com \
    --cc=rasland@nvidia.com \
    --cc=roniba@nvidia.com \
    --cc=shahafs@nvidia.com \
    --cc=thomas@monjalon.net \
    --cc=viacheslavo@nvidia.com \
    --cc=wisamm@nvidia.com \
    --cc=xiaoyun.li@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).