DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/2] Support meter policy API
@ 2021-04-01  6:54 Li Zhang
  2021-04-01  6:54 ` [dpdk-dev] [PATCH 1/2] ethdev: add pre-defined " Li Zhang
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Li Zhang @ 2021-04-01  6:54 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, cristian.dumitrescu, lironh
  Cc: dev, thomas, rasland, roniba

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.

RFC ("ethdev: add pre-defined meter policy API")
https://patchwork.dpdk.org/project/dpdk/patch/20210318085815.804896-1-lizh@nvidia.com/

Haifei Luo (1):
  app/testpmd: support policy actions per color

Li Zhang (1):
  ethdev: add pre-defined meter policy API

 app/test-flow-perf/main.c                     |   7 -
 app/test-pmd/cmdline.c                        |   7 +-
 app/test-pmd/cmdline_flow.c                   | 118 ++++-
 app/test-pmd/cmdline_mtr.c                    | 257 +++-------
 app/test-pmd/cmdline_mtr.h                    |   4 +-
 app/test-pmd/config.c                         |  34 ++
 app/test-pmd/testpmd.h                        |   2 +
 doc/guides/rel_notes/release_20_11.rst        |   3 +
 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   | 303 +++++++++---
 lib/librte_ethdev/rte_flow.h                  |  18 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 166 +++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   4 +
 22 files changed, 747 insertions(+), 1238 deletions(-)

-- 
2.27.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [dpdk-dev] [PATCH 1/2] ethdev: add pre-defined meter policy API
  2021-04-01  6:54 [dpdk-dev] [PATCH 0/2] Support meter policy API Li Zhang
@ 2021-04-01  6:54 ` Li Zhang
  2021-04-01  6:54 ` [dpdk-dev] [PATCH 2/2] app/testpmd: support policy actions per color Li Zhang
  2021-04-02 10:36 ` [dpdk-dev] [PATCH v2 0/2] Support meter policy API Li Zhang
  2 siblings, 0 replies; 8+ messages in thread
From: Li Zhang @ 2021-04-01  6:54 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, cristian.dumitrescu,
	lironh, Wisam Jaddo, Xiaoyun Li, Jasvinder Singh,
	Thomas Monjalon, Ferruh Yigit, Andrew Rybchenko, Ray Kinsella,
	Neil Horman
  Cc: dev, rasland, roniba, Haifei Luo

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.

Policy id 0 is default policy. Action per color as below:
green - nothing, yellow - nothing, red - drop

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.
3. Create default policy if policy id is RTE_MTR_DEFAULT_POLICY_ID.
   default policy actoins:
   green - do nothing, yellow - do nothing, red - drop

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>
---
 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/rel_notes/release_20_11.rst        |   3 +
 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   | 303 +++++++++---
 lib/librte_ethdev/rte_flow.h                  |  18 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 166 +++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   4 +
 19 files changed, 507 insertions(+), 1230 deletions(-)

diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c
index 99d0463456..66ec776017 100644
--- a/app/test-flow-perf/main.c
+++ b/app/test-flow-perf/main.c
@@ -924,13 +924,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 14110eb2e4..dcb5f9c871 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -17069,7 +17069,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/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index 7405a9864f..5a6839758a 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -663,6 +663,9 @@ API Changes
 * sched: Removed ``tb_rate``, ``tc_rate``, ``tc_period`` and ``tb_size``
   from ``struct rte_sched_subport_params``.
 
+* 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()``
 
 ABI Changes
 -----------
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 08efa5d15d..b182fb6c19 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -593,14 +593,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;
@@ -639,24 +631,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;
@@ -691,8 +671,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 615fe99b69..2d0daf631a 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -6654,52 +6654,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 59e9ce2c9e..8e4530f32c 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -838,6 +838,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. */
 };
 
@@ -1077,14 +1079,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,
@@ -1141,8 +1135,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;
@@ -1372,12 +1364,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 712f655761..4d13743ecc 100644
--- a/drivers/net/mlx5/mlx5_flow_aso.c
+++ b/drivers/net/mlx5/mlx5_flow_aso.c
@@ -809,8 +809,8 @@ mlx5_aso_meter_update_by_wqe(struct mlx5_dev_ctx_shared *sh,
 		/* Waiting for wqe resource. */
 		usleep(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;
 }
 
@@ -845,7 +845,7 @@ mlx5_aso_mtr_wait(struct mlx5_dev_ctx_shared *sh,
 		/* Waiting for CQE ready. */
 		usleep(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 c4c54d4043..ec6097b395 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. */
@@ -6011,12 +5986,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;
 }
@@ -6039,7 +6012,6 @@ flow_dv_aso_mtr_release_to_pool(struct rte_eth_dev *dev, uint32_t mtr_idx)
 	MLX5_ASSERT(aso_mtr);
 	rte_spinlock_lock(&mtrmng->mtrsl);
 	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);
 }
@@ -6081,8 +6053,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) {
 		reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, &error);
@@ -13565,433 +13537,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,
-	};
-
-	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 |
-					 LS32_MASK(MLX5_MTR_COLOR_BITS)));
-		} else {
-			flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-					color_reg_c_idx, 0,
-					LS32_MASK(MLX5_MTR_COLOR_BITS));
-			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 = LS32_MASK(priv->max_mtr_bits) << 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->esw_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 initilized, 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.
  *
@@ -14285,8 +13830,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 c2a063abdb..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->esw_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..99f5291556 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,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	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_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 = 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 = 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,8 +369,13 @@ 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;
+	struct rte_flow_action actions[RTE_COLORS];
+	struct rte_flow_action_color recolor[RTE_COLORS];
+	const struct rte_flow_action *acts[RTE_COLORS];
+	enum rte_color i;
 
 	/* Check parameters */
 	status = mtr_check(p, mtr_id, params, shared, error);
@@ -283,6 +390,46 @@ pmd_mtr_create(struct rte_eth_dev *dev,
 			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
 			NULL,
 			"Meter profile id not valid");
+	/* Meter policy must exist */
+	policy = softnic_mtr_meter_policy_find(p, params->meter_policy_id);
+	if (policy == NULL) {
+		/* Create default policy */
+		if (params->meter_policy_id == RTE_MTR_DEFAULT_POLICY_ID) {
+			/* Green - do nothing, yellow - do nothing.*/
+			for (i = 0; i < RTE_COLOR_RED; i++) {
+				actions[i].type =
+					RTE_FLOW_ACTION_TYPE_METER_COLOR;
+				recolor[i].color = i;
+				actions[i].conf = &recolor[i];
+				acts[i] = &actions[i];
+			}
+			/* Red - drop.*/
+			actions[RTE_COLOR_RED].type =
+					RTE_FLOW_ACTION_TYPE_DROP;
+			acts[RTE_COLOR_RED] = &actions[RTE_COLOR_RED];
+			status = pmd_mtr_meter_policy_create(dev,
+					RTE_MTR_DEFAULT_POLICY_ID,
+					acts,
+					error);
+			if (status)
+				return status;
+
+			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,
+					"Fail to find meter default policy");
+		} else {
+			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));
@@ -302,6 +449,7 @@ pmd_mtr_create(struct rte_eth_dev *dev,
 
 	/* Update dependencies */
 	mp->n_users++;
+	policy->n_users++;
 
 	return 0;
 }
@@ -316,6 +464,8 @@ 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;
+	int status;
 
 	/* MTR object must exist */
 	m = softnic_mtr_find(p, mtr_id);
@@ -343,8 +493,28 @@ 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--;
+
+	/* Destory default policy*/
+	if (!policy->n_users &&
+		m->params.meter_policy_id == RTE_MTR_DEFAULT_POLICY_ID) {
+		status = pmd_mtr_meter_policy_delete(dev,
+					RTE_MTR_DEFAULT_POLICY_ID,
+					error);
+		if (status)
+			return status;
+	}
 
 	/* Remove from list */
 	TAILQ_REMOVE(ml, m, node);
@@ -506,18 +676,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 +697,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 +716,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 +740,14 @@ 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);
+
+	/* 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 +764,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 +808,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 +887,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 +909,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 +919,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..60fede4983 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,13 @@ 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.
+	 *
+	 * See struct rte_flow_action_color.
+	 */
+	RTE_FLOW_ACTION_TYPE_METER_COLOR,
 };
 
 /**
@@ -2859,6 +2867,16 @@ struct rte_flow_action_set_dscp {
  */
 struct rte_flow_shared_action;
 
+/**
+ * RTE_FLOW_ACTION_TYPE_COLOR
+ *
+ * The meter color should be set in the packet meta-data
+ * (i.e. struct rte_mbuf::sched::color).
+ */
+struct rte_flow_action_color {
+	enum rte_color color; /**< Green/Yellow/Red. */
+};
+
 /**
  * Field IDs for MODIFY_FIELD action.
  */
diff --git a/lib/librte_ethdev/rte_mtr.c b/lib/librte_ethdev/rte_mtr.c
index 3073ac03f2..27041467c5 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,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	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,
+		actions, error);
+}
+
+/* MTR meter policy create */
+int
+rte_mtr_meter_policy_create(uint16_t port_id,
+	uint32_t policy_id,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	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, actions, 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..50b343dd27 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" {
@@ -174,23 +175,6 @@ struct rte_mtr_meter_profile {
 	};
 };
 
-/**
- * Policer actions
- */
-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,
-};
-
 /**
  * Parameters for each traffic metering & policing object
  *
@@ -232,13 +216,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 +308,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 +333,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 +358,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 +443,92 @@ rte_mtr_meter_profile_delete(uint16_t port_id,
 	uint32_t meter_profile_id,
 	struct rte_mtr_error *error);
 
+/**
+ * Policy id 0 is default policy.
+ * Action per color as below:
+ * green - do nothing, yellow - do nothing, red - drop
+ * It can be used without creating it by
+ * the rte_mtr_meter_policy_create function.
+ */
+#define RTE_MTR_DEFAULT_POLICY_ID 0
+
+/**
+ * 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] actions
+ *   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,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	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.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] policy_id
+ *   Policy identifier for the new meter policy.
+ * @param[in] actions
+ *   Associated actions 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_create(uint16_t port_id,
+	uint32_t policy_id,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	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 +654,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 +669,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 +694,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..98260ac40b 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,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	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,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	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..a45834b87f 100644
--- a/lib/librte_ethdev/version.map
+++ b/lib/librte_ethdev/version.map
@@ -246,6 +246,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


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [dpdk-dev] [PATCH 2/2] app/testpmd: support policy actions per color
  2021-04-01  6:54 [dpdk-dev] [PATCH 0/2] Support meter policy API Li Zhang
  2021-04-01  6:54 ` [dpdk-dev] [PATCH 1/2] ethdev: add pre-defined " Li Zhang
@ 2021-04-01  6:54 ` Li Zhang
  2021-04-02 10:36 ` [dpdk-dev] [PATCH v2 0/2] Support meter policy API Li Zhang
  2 siblings, 0 replies; 8+ messages in thread
From: Li Zhang @ 2021-04-01  6:54 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, cristian.dumitrescu,
	lironh, Xiaoyun Li
  Cc: dev, thomas, rasland, roniba, Haifei Luo

From: Haifei Luo <haifeil@nvidia.com>

add the new create meter with policy API to support it.

Signed-off-by: Haifei Luo <haifeil@nvidia.com>
---
 app/test-pmd/cmdline.c      |   6 +-
 app/test-pmd/cmdline_flow.c | 118 +++++++++++++++++++++++++++++++++++-
 app/test-pmd/cmdline_mtr.c  |  85 ++++++++++++++++++++++++--
 app/test-pmd/cmdline_mtr.h  |   3 +
 app/test-pmd/config.c       |  34 +++++++++++
 app/test-pmd/testpmd.h      |   2 +
 6 files changed, 240 insertions(+), 8 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index dcb5f9c871..029cb38786 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -705,7 +705,7 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"del port meter profile (port_id) (profile_id)\n"
 			"    meter profile delete\n\n"
 
-			"create port meter (port_id) (mtr_id) (profile_id) (meter_enable)\n"
+			"create port meter (port_id) [mtr_id] (profile_id) [policy (policy_id)] (meter_enable)\n"
 			"(g_action) (y_action) (r_action) (stats_mask) (shared)\n"
 			"(use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
 			"(dscp_tbl_entry63)]\n"
@@ -720,6 +720,9 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"del port meter (port_id) (mtr_id)\n"
 			"    meter delete\n\n"
 
+			"del port meter policy (port_id) (policy_id)\n"
+			"    meter policy delete\n\n"
+
 			"set port meter profile (port_id) (mtr_id) (profile_id)\n"
 			"    meter update meter profile\n\n"
 
@@ -17067,6 +17070,7 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_enable_port_meter,
 	(cmdline_parse_inst_t *)&cmd_disable_port_meter,
 	(cmdline_parse_inst_t *)&cmd_del_port_meter,
+	(cmdline_parse_inst_t *)&cmd_del_port_meter_policy,
 	(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_stats_mask,
diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 2c40c6996e..050290990a 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -55,6 +55,10 @@ enum index {
 	GROUP_ID,
 	PRIORITY_LEVEL,
 	SHARED_ACTION_ID,
+	POLICY_ID,
+
+	/* TOP-level command. */
+	ADD,
 
 	/* Top-level command. */
 	SET,
@@ -289,6 +293,9 @@ enum index {
 	ITEM_GENEVE_OPT_TYPE,
 	ITEM_GENEVE_OPT_LENGTH,
 	ITEM_GENEVE_OPT_DATA,
+	ITEM_POL_PORT,
+	ITEM_POL_METER,
+	ITEM_POL_POLICY,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -427,6 +434,9 @@ enum index {
 	ACTION_MODIFY_FIELD_SRC_OFFSET,
 	ACTION_MODIFY_FIELD_SRC_VALUE,
 	ACTION_MODIFY_FIELD_WIDTH,
+	ACTION_POL_G,
+	ACTION_POL_Y,
+	ACTION_POL_R,
 };
 
 /** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -806,6 +816,9 @@ struct buffer {
 		struct {
 			int destroy;
 		} aged; /**< Aged arguments. */
+		struct {
+			uint32_t policy_id;
+		} policy;/**< Policy arguments. */
 	} args; /**< Command arguments. */
 };
 
@@ -1781,6 +1794,9 @@ static int parse_ipv6_addr(struct context *, const struct token *,
 static int parse_port(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
+static int parse_mp(struct context *, const struct token *,
+			const char *, unsigned int,
+			void *, unsigned int);
 static int parse_sa(struct context *, const struct token *,
 		    const char *, unsigned int,
 		    void *, unsigned int);
@@ -1819,7 +1835,7 @@ static const struct token token_list[] = {
 	[ZERO] = {
 		.name = "ZERO",
 		.help = "null entry, abused as the entry point",
-		.next = NEXT(NEXT_ENTRY(FLOW)),
+		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
 	},
 	[END] = {
 		.name = "",
@@ -1941,6 +1957,13 @@ static const struct token token_list[] = {
 		.call = parse_int,
 		.comp = comp_none,
 	},
+	[POLICY_ID] = {
+		.name = "{policy_id}",
+		.type = "POLCIY_ID",
+		.help = "policy id",
+		.call = parse_int,
+		.comp = comp_none,
+	},
 	/* Top-level command. */
 	[FLOW] = {
 		.name = "flow",
@@ -4524,6 +4547,54 @@ static const struct token token_list[] = {
 		.help = "specify action to share",
 		.next = NEXT(next_action),
 	},
+	[ACTION_POL_G] = {
+		.name = "g_actions",
+		.help = "submit a list of associated actions for green",
+		.next = NEXT(next_action),
+		.call = parse_mp,
+	},
+	[ACTION_POL_Y] = {
+		.name = "y_actions",
+		.help = "submit a list of associated actions for yellow",
+		.next = NEXT(next_action),
+	},
+	[ACTION_POL_R] = {
+		.name = "r_actions",
+		.help = "submit a list of associated actions for red",
+		.next = NEXT(next_action),
+	},
+
+	/* Top-level command. */
+	[ADD] = {
+		.name = "add",
+		.type = "port meter policy {port_id} {arg}",
+		.help = "add port meter policy",
+		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
+		.call = parse_init,
+	},
+	/* Sub-level commands. */
+	[ITEM_POL_PORT] = {
+		.name = "port",
+		.help = "add port meter policy",
+		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
+	},
+	[ITEM_POL_METER] = {
+		.name = "meter",
+		.help = "add port meter policy",
+		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
+	},
+	[ITEM_POL_POLICY] = {
+		.name = "policy",
+		.help = "add port meter policy",
+		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
+				NEXT_ENTRY(ACTION_POL_Y),
+				NEXT_ENTRY(ACTION_POL_G),
+				NEXT_ENTRY(POLICY_ID),
+				NEXT_ENTRY(PORT_ID)),
+		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
+				ARGS_ENTRY(struct buffer, port)),
+		.call = parse_mp,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
@@ -4708,6 +4779,47 @@ parse_init(struct context *ctx, const struct token *token,
 	return len;
 }
 
+/** Parse tokens for meter policy action commands. */
+static int
+parse_mp(struct context *ctx, const struct token *token,
+	const char *str, unsigned int len,
+	void *buf, unsigned int size)
+{
+	struct buffer *out = buf;
+
+	/* Token name must match. */
+	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+		return -1;
+	/* Nothing else to do if there is no buffer. */
+	if (!out)
+		return len;
+	if (!out->command) {
+		if (ctx->curr != ITEM_POL_POLICY)
+			return -1;
+		if (sizeof(*out) > size)
+			return -1;
+		out->command = ctx->curr;
+		ctx->objdata = 0;
+		ctx->object = out;
+		ctx->objmask = NULL;
+		out->args.vc.data = (uint8_t *)out + size;
+		return len;
+	}
+	switch (ctx->curr) {
+	case ACTION_POL_G:
+		out->args.vc.actions =
+			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+					sizeof(double));
+		out->command = ctx->curr;
+		ctx->objdata = 0;
+		ctx->object = out;
+		ctx->objmask = NULL;
+		return len;
+	default:
+		return -1;
+	}
+}
+
 /** Parse tokens for shared action commands. */
 static int
 parse_sa(struct context *ctx, const struct token *token,
@@ -7665,6 +7777,10 @@ cmd_flow_parsed(const struct buffer *in)
 	case TUNNEL_LIST:
 		port_flow_tunnel_list(in->port);
 		break;
+	case ACTION_POL_G:
+		port_meter_policy_add(in->port, in->args.policy.policy_id,
+					in->args.vc.actions);
+		break;
 	default:
 		break;
 	}
diff --git a/app/test-pmd/cmdline_mtr.c b/app/test-pmd/cmdline_mtr.c
index 44394e3ea1..bdc9ae8bfe 100644
--- a/app/test-pmd/cmdline_mtr.c
+++ b/app/test-pmd/cmdline_mtr.c
@@ -37,6 +37,8 @@ print_err_msg(struct rte_mtr_error *error)
 		[RTE_MTR_ERROR_TYPE_STATS] = "stats",
 		[RTE_MTR_ERROR_TYPE_SHARED]
 			= "shared meter",
+		[RTE_MTR_ERROR_TYPE_METER_POLICY_ID] = "meter policy id",
+		[RTE_MTR_ERROR_TYPE_METER_POLICY] = "meter policy null",
 	};
 
 	const char *errstr;
@@ -56,6 +58,12 @@ print_err_msg(struct rte_mtr_error *error)
 		error->type);
 }
 
+void
+print_mtr_err_msg(struct rte_mtr_error *error)
+{
+	print_err_msg(error);
+}
+
 static int
 parse_uint(uint64_t *value, const char *str)
 {
@@ -671,6 +679,7 @@ struct cmd_create_port_meter_result {
 	uint16_t port_id;
 	uint32_t mtr_id;
 	uint32_t profile_id;
+	uint32_t policy_id;
 	cmdline_fixed_string_t meter_enable;
 	cmdline_fixed_string_t g_action;
 	cmdline_fixed_string_t y_action;
@@ -698,6 +707,9 @@ cmdline_parse_token_num_t cmd_create_port_meter_mtr_id =
 cmdline_parse_token_num_t cmd_create_port_meter_profile_id =
 	TOKEN_NUM_INITIALIZER(
 		struct cmd_create_port_meter_result, profile_id, RTE_UINT32);
+cmdline_parse_token_num_t cmd_create_port_meter_policy_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_create_port_meter_result, policy_id, RTE_UINT32);
 cmdline_parse_token_string_t cmd_create_port_meter_meter_enable =
 	TOKEN_STRING_INITIALIZER(struct cmd_create_port_meter_result,
 		meter_enable, "yes#no");
@@ -741,7 +753,7 @@ static void cmd_create_port_meter_parsed(void *parsed_result,
 	/* Meter params */
 	memset(&params, 0, sizeof(struct rte_mtr_params));
 	params.meter_profile_id = res->profile_id;
-
+	params.meter_policy_id = res->policy_id;
 	/* Parse meter input color string params */
 	ret = parse_meter_color_str(c_str, &use_prev_meter_color, &dscp_table);
 	if (ret) {
@@ -756,7 +768,6 @@ static void cmd_create_port_meter_parsed(void *parsed_result,
 		params.meter_enable = 1;
 	else
 		params.meter_enable = 0;
-
 	params.stats_mask = res->statistics_mask;
 
 	ret = rte_mtr_create(port_id, mtr_id, &params, shared, &error);
@@ -771,7 +782,6 @@ cmdline_parse_inst_t cmd_create_port_meter = {
 	.f = cmd_create_port_meter_parsed,
 	.data = NULL,
 	.help_str = "create port meter <port_id> <mtr_id> <profile_id> <meter_enable>(yes|no) "
-		"<g_action>(R|Y|G|D) <y_action>(R|Y|G|D) <r_action>(R|Y|G|D) "
 		"<stats_mask> <shared> <use_pre_meter_color> "
 		"[<dscp_tbl_entry0> <dscp_tbl_entry1> ...<dscp_tbl_entry63>]",
 	.tokens = {
@@ -781,10 +791,8 @@ cmdline_parse_inst_t cmd_create_port_meter = {
 		(void *)&cmd_create_port_meter_port_id,
 		(void *)&cmd_create_port_meter_mtr_id,
 		(void *)&cmd_create_port_meter_profile_id,
+		(void *)&cmd_create_port_meter_policy_id,
 		(void *)&cmd_create_port_meter_meter_enable,
-		(void *)&cmd_create_port_meter_g_action,
-		(void *)&cmd_create_port_meter_y_action,
-		(void *)&cmd_create_port_meter_r_action,
 		(void *)&cmd_create_port_meter_statistics_mask,
 		(void *)&cmd_create_port_meter_shared,
 		(void *)&cmd_create_port_meter_input_color,
@@ -914,6 +922,71 @@ cmdline_parse_inst_t cmd_disable_port_meter = {
 	},
 };
 
+/* *** Delete Port Meter Policy Object *** */
+struct cmd_del_port_meter_policy_result {
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t policy;
+	uint16_t port_id;
+	uint32_t policy_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_meter_policy_del =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_policy_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_meter_policy_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_policy_result, port, "port");
+cmdline_parse_token_string_t cmd_del_port_meter_policy_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_policy_result, meter, "meter");
+cmdline_parse_token_string_t cmd_del_port_meter_policy_policy =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_policy_result, policy, "policy");
+cmdline_parse_token_num_t cmd_del_port_meter_policy_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_policy_result, port_id, RTE_UINT16);
+cmdline_parse_token_num_t cmd_del_port_meter_policy_policy_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_policy_result, policy_id, RTE_UINT32);
+
+static void cmd_del_port_meter_policy_parsed(void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_del_port_meter_policy_result *res = parsed_result;
+	struct rte_mtr_error error;
+	uint32_t policy_id = res->policy_id;
+	uint16_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Delete Meter Policy*/
+	ret = rte_mtr_meter_policy_delete(port_id, policy_id, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_del_port_meter_policy = {
+	.f = cmd_del_port_meter_policy_parsed,
+	.data = NULL,
+	.help_str = "Delete port meter policy",
+	.tokens = {
+		(void *)&cmd_del_port_meter_policy_del,
+		(void *)&cmd_del_port_meter_policy_port,
+		(void *)&cmd_del_port_meter_policy_meter,
+		(void *)&cmd_del_port_meter_policy_policy,
+		(void *)&cmd_del_port_meter_policy_port_id,
+		(void *)&cmd_del_port_meter_policy_policy_id,
+		NULL,
+	},
+};
+
 /* *** Delete Port Meter Object *** */
 struct cmd_del_port_meter_result {
 	cmdline_fixed_string_t del;
diff --git a/app/test-pmd/cmdline_mtr.h b/app/test-pmd/cmdline_mtr.h
index 7e2713cea3..2415fc16c3 100644
--- a/app/test-pmd/cmdline_mtr.h
+++ b/app/test-pmd/cmdline_mtr.h
@@ -4,6 +4,7 @@
 
 #ifndef _CMDLINE_MTR_H_
 #define _CMDLINE_MTR_H_
+#include <rte_mtr.h>
 
 /* Traffic Metering and Policing */
 extern cmdline_parse_inst_t cmd_show_port_meter_cap;
@@ -15,9 +16,11 @@ extern cmdline_parse_inst_t cmd_create_port_meter;
 extern cmdline_parse_inst_t cmd_enable_port_meter;
 extern cmdline_parse_inst_t cmd_disable_port_meter;
 extern cmdline_parse_inst_t cmd_del_port_meter;
+extern cmdline_parse_inst_t cmd_del_port_meter_policy;
 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_stats_mask;
 extern cmdline_parse_inst_t cmd_show_port_meter_stats;
+void print_mtr_err_msg(struct rte_mtr_error *error);
 
 #endif /* _CMDLINE_MTR_H_ */
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index ef0b9784d0..336b9b500e 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -38,6 +38,7 @@
 #include <rte_string_fns.h>
 #include <rte_cycles.h>
 #include <rte_flow.h>
+#include <rte_mtr.h>
 #include <rte_errno.h>
 #ifdef RTE_NET_IXGBE
 #include <rte_pmd_ixgbe.h>
@@ -52,6 +53,7 @@
 #include <rte_hexdump.h>
 
 #include "testpmd.h"
+#include "cmdline_mtr.h"
 
 #define ETHDEV_FWVERS_LEN 32
 
@@ -1464,6 +1466,38 @@ action_alloc(portid_t port_id, uint32_t id,
 	return 0;
 }
 
+/** Add port meter policy */
+int
+port_meter_policy_add(portid_t port_id, uint32_t policy_id,
+			const struct rte_flow_action *actions)
+{
+	struct rte_mtr_error error;
+	const struct rte_flow_action *acts[RTE_COLORS];
+	const struct rte_flow_action *act = actions;
+	const struct rte_flow_action *start;
+	uint32_t i = 0, act_n;
+	int ret;
+
+	for (i = 0; i < RTE_COLORS; i++) {
+		for (act_n = 0, start = act;
+			act->type != RTE_FLOW_ACTION_TYPE_END; act++)
+			act_n++;
+		if (act_n && act->type == RTE_FLOW_ACTION_TYPE_END)
+			acts[i] = start;
+		else
+			acts[i] = NULL;
+		act++;
+	}
+	ret = rte_mtr_meter_policy_create(port_id,
+			policy_id,
+			acts, &error);
+	if (ret) {
+		print_mtr_err_msg(&error);
+		return -1;
+	}
+	return policy_id;
+}
+
 /** Create shared action */
 int
 port_shared_action_create(portid_t port_id, uint32_t id,
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index a87ccb0f0f..bc7cb7e9b9 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -837,6 +837,8 @@ void port_flow_tunnel_list(portid_t port_id);
 void port_flow_tunnel_destroy(portid_t port_id, uint32_t tunnel_id);
 void port_flow_tunnel_create(portid_t port_id, const struct tunnel_ops *ops);
 int port_flow_isolate(portid_t port_id, int set);
+int port_meter_policy_add(portid_t port_id, uint32_t policy_id,
+		const struct rte_flow_action *actions);
 
 void rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id);
 void tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id);
-- 
2.27.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [dpdk-dev] [PATCH v2 0/2] Support meter policy API
  2021-04-01  6:54 [dpdk-dev] [PATCH 0/2] Support meter policy API Li Zhang
  2021-04-01  6:54 ` [dpdk-dev] [PATCH 1/2] ethdev: add pre-defined " Li Zhang
  2021-04-01  6:54 ` [dpdk-dev] [PATCH 2/2] app/testpmd: support policy actions per color Li Zhang
@ 2021-04-02 10:36 ` Li Zhang
  2021-04-02 10:36   ` [dpdk-dev] [PATCH v2 1/2] ethdev: add pre-defined " Li Zhang
  2021-04-02 10:36   ` [dpdk-dev] [PATCH v2 2/2] app/testpmd: support policy actions per color Li Zhang
  2 siblings, 2 replies; 8+ messages in thread
From: Li Zhang @ 2021-04-02 10:36 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, cristian.dumitrescu, lironh
  Cc: dev, thomas, rasland, roniba

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.

RFC ("ethdev: add pre-defined meter policy API")
https://patchwork.dpdk.org/project/dpdk/patch/20210318085815.804896-1-lizh@nvidia.com/

V2: Delete default policy and change relation doc files.

Haifei Luo (1):
  app/testpmd: support policy actions per color

Li Zhang (1):
  ethdev: add pre-defined meter policy API

 app/test-flow-perf/main.c                     |   7 -
 app/test-pmd/cmdline.c                        |   7 +-
 app/test-pmd/cmdline_flow.c                   | 118 ++++-
 app/test-pmd/cmdline_mtr.c                    | 257 +++-------
 app/test-pmd/cmdline_mtr.h                    |   4 +-
 app/test-pmd/config.c                         |  34 ++
 app/test-pmd/testpmd.h                        |   2 +
 doc/guides/nics/mlx5.rst                      |  12 +
 doc/guides/prog_guide/rte_flow.rst            |  20 +
 .../traffic_metering_and_policing.rst         |   9 +-
 doc/guides/rel_notes/release_21_05.rst        |  14 +-
 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              |  15 +-
 drivers/net/mlx5/mlx5_flow_dv.c               | 463 +-----------------
 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                  |  18 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 157 ++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   4 +
 26 files changed, 750 insertions(+), 1266 deletions(-)

-- 
2.27.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [dpdk-dev] [PATCH v2 1/2] ethdev: add pre-defined meter policy API
  2021-04-02 10:36 ` [dpdk-dev] [PATCH v2 0/2] Support meter policy API Li Zhang
@ 2021-04-02 10:36   ` Li Zhang
  2021-04-08 13:55     ` Ori Kam
  2021-04-02 10:36   ` [dpdk-dev] [PATCH v2 2/2] app/testpmd: support policy actions per color Li Zhang
  1 sibling, 1 reply; 8+ messages in thread
From: Li Zhang @ 2021-04-02 10:36 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, cristian.dumitrescu,
	lironh, Wisam Jaddo, Xiaoyun Li, Jasvinder Singh,
	Thomas Monjalon, Ferruh Yigit, Andrew Rybchenko, Ray Kinsella,
	Neil Horman
  Cc: dev, rasland, roniba, Haifei Luo

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.

Policy id 0 is default policy. Action per color as below:
green - nothing, yellow - nothing, red - drop

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.
3. Create default policy if policy id is RTE_MTR_DEFAULT_POLICY_ID.
   default policy actoins:
   green - do nothing, yellow - do nothing, red - drop

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>
---
 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/nics/mlx5.rst                      |  12 +
 doc/guides/prog_guide/rte_flow.rst            |  20 +
 .../traffic_metering_and_policing.rst         |   9 +-
 doc/guides/rel_notes/release_21_05.rst        |  14 +-
 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              |  15 +-
 drivers/net/mlx5/mlx5_flow_dv.c               | 463 +-----------------
 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                  |  18 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 157 ++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   4 +
 23 files changed, 510 insertions(+), 1258 deletions(-)

diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c
index 99d0463456..66ec776017 100644
--- a/app/test-flow-perf/main.c
+++ b/app/test-flow-perf/main.c
@@ -924,13 +924,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 14110eb2e4..dcb5f9c871 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -17069,7 +17069,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/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index fa63e62a5d..6e9a68baf5 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -106,6 +106,7 @@ Features
 - E-Switch mirroring and modify.
 - 21844 flow priorities for ingress or egress flow groups greater than 0 and for any transfer
   flow group.
+- Flow metering, including meter policy API.
 
 Limitations
 -----------
@@ -403,6 +404,17 @@ Limitations
   - Green color is not supported with drop action.
   - Yellow detection is not supported.
   - Red color must be with drop action.
+  - Meter statistics are supported only for drop case.
+  - Meter yellow color detection is not supported.
+  - A meter action created with pre-defined policy must be the last action in the
+    flow except single case where the policy actions are
+    green: NULL or END,
+    yellow: NULL or END,
+    RED: DROP / END.
+  - The only supported meter policy actions:
+    green: QUEUE, RSS, PORT_ID, JUMP, MARK and SET_TAG.
+    yellow: must be empty.
+    red: must be DROP.
 
 Statistics
 ----------
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index aec2ba1ec0..63bc1ea075 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -2834,6 +2834,26 @@ 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.
+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..87b1ea6d2f 100644
--- a/doc/guides/prog_guide/traffic_metering_and_policing.rst
+++ b/doc/guides/prog_guide/traffic_metering_and_policing.rst
@@ -56,10 +56,13 @@ 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:
+* Policing: There is the meter policy for the user to use variety of actions
+  per meter output color differently. A list of rte_flow actions will be
+  provided by the user per color in the policy. Action per color in policy
+  as one example: green - do nothing, yellow - do nothing, red - drop.
 
-  * Drop the packet.
+  There is a meter_color action configured by rte_flow_action_meter_color
+  for each meter output color, which can:
 
   * Keep the same packet color: the policer output color matches the meter
     output color (essentially a no-op action).
diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst
index 3c76148b11..ca600a8fea 100644
--- a/doc/guides/rel_notes/release_21_05.rst
+++ b/doc/guides/rel_notes/release_21_05.rst
@@ -118,7 +118,19 @@ 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()``
 
 Removed Items
 -------------
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f59eb8a27d..59d2931e82 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2812,24 +2812,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 08efa5d15d..b182fb6c19 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -593,14 +593,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;
@@ -639,24 +631,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;
@@ -691,8 +671,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 615fe99b69..2d0daf631a 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -6654,52 +6654,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 59e9ce2c9e..8e4530f32c 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -838,6 +838,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. */
 };
 
@@ -1077,14 +1079,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,
@@ -1141,8 +1135,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;
@@ -1372,12 +1364,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 8d08d940b6..4d13743ecc 100644
--- a/drivers/net/mlx5/mlx5_flow_aso.c
+++ b/drivers/net/mlx5/mlx5_flow_aso.c
@@ -1,8 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2020 Mellanox Technologies, Ltd
  */
-#include <unistd.h>
-
 #include <mlx5_prm.h>
 #include <rte_malloc.h>
 #include <rte_cycles.h>
@@ -15,6 +13,7 @@
 #include "mlx5.h"
 #include "mlx5_flow.h"
 
+
 /**
  * Destroy Completion Queue used for ASO access.
  *
@@ -313,7 +312,7 @@ mlx5_aso_queue_init(struct mlx5_dev_ctx_shared *sh,
 		mlx5_aso_age_init_sq(&sh->aso_age_mng->aso_sq);
 		break;
 	case ASO_OPC_MOD_POLICER:
-		if (mlx5_aso_sq_create(sh->ctx, &sh->mtrmng->sq, 0,
+		if (mlx5_aso_sq_create(sh->ctx,&sh->mtrmng->sq, 0,
 				  sh->tx_uar, sh->pdn, MLX5_ASO_QUEUE_LOG_DESC,
 				  sh->sq_ts_format))
 			return -1;
@@ -729,7 +728,7 @@ mlx5_aso_mtrs_status_update(struct mlx5_aso_sq *sq, uint16_t aso_mtrs_nums)
 	for (i = 0; i < aso_mtrs_nums; ++i) {
 		aso_mtr = sq->elts[(sq->tail + i) & mask].mtr;
 		MLX5_ASSERT(aso_mtr);
-		(void)__atomic_compare_exchange_n(&aso_mtr->state,
+		__atomic_compare_exchange_n(&aso_mtr->state,
 				&exp_state, ASO_METER_READY,
 				false, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
 	}
@@ -810,8 +809,8 @@ mlx5_aso_meter_update_by_wqe(struct mlx5_dev_ctx_shared *sh,
 		/* Waiting for wqe resource. */
 		usleep(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;
 }
 
@@ -846,7 +845,7 @@ mlx5_aso_mtr_wait(struct mlx5_dev_ctx_shared *sh,
 		/* Waiting for CQE ready. */
 		usleep(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 9d15b597d3..ec6097b395 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. */
@@ -6011,12 +5986,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;
 }
@@ -6039,7 +6012,6 @@ flow_dv_aso_mtr_release_to_pool(struct rte_eth_dev *dev, uint32_t mtr_idx)
 	MLX5_ASSERT(aso_mtr);
 	rte_spinlock_lock(&mtrmng->mtrsl);
 	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);
 }
@@ -6081,11 +6053,10 @@ 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
 		reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, &error);
 		mtr_free->fm.meter_action =
 			mlx5_glue->dv_create_flow_action_aso
@@ -6094,7 +6065,6 @@ flow_dv_mtr_alloc(struct rte_eth_dev *dev)
 						 mtr_free->offset,
 						 (1 << MLX5_FLOW_COLOR_GREEN),
 						 reg_id - REG_C_0);
-#endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO */
 		if (!mtr_free->fm.meter_action) {
 			flow_dv_aso_mtr_release_to_pool(dev, mtr_idx);
 			return 0;
@@ -13567,433 +13537,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,
-	};
-
-	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 |
-					 LS32_MASK(MLX5_MTR_COLOR_BITS)));
-		} else {
-			flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-					color_reg_c_idx, 0,
-					LS32_MASK(MLX5_MTR_COLOR_BITS));
-			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 = LS32_MASK(priv->max_mtr_bits) << 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->esw_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.
  *
@@ -14287,8 +13830,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 c2a063abdb..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->esw_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..e3ac70f03f 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,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	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 = 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 = 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..0c5807deea 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,13 @@ 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.
+	 *
+	 * See struct rte_flow_action_meter_color.
+	 */
+	RTE_FLOW_ACTION_TYPE_METER_COLOR,
 };
 
 /**
@@ -2859,6 +2867,16 @@ struct rte_flow_action_set_dscp {
  */
 struct rte_flow_shared_action;
 
+/**
+ * RTE_FLOW_ACTION_TYPE_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..27041467c5 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,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	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,
+		actions, error);
+}
+
+/* MTR meter policy create */
+int
+rte_mtr_meter_policy_create(uint16_t port_id,
+	uint32_t policy_id,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	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, actions, 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..913c729755 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" {
@@ -174,23 +175,6 @@ struct rte_mtr_meter_profile {
 	};
 };
 
-/**
- * Policer actions
- */
-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,
-};
-
 /**
  * Parameters for each traffic metering & policing object
  *
@@ -232,13 +216,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 +308,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 +333,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 +358,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 +443,83 @@ 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] actions
+ *   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,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	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.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] policy_id
+ *   Policy identifier for the new meter policy.
+ * @param[in] actions
+ *   Associated actions 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_create(uint16_t port_id,
+	uint32_t policy_id,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	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 +645,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 +660,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 +685,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..98260ac40b 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,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	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,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	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..a45834b87f 100644
--- a/lib/librte_ethdev/version.map
+++ b/lib/librte_ethdev/version.map
@@ -246,6 +246,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


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [dpdk-dev] [PATCH v2 2/2] app/testpmd: support policy actions per color
  2021-04-02 10:36 ` [dpdk-dev] [PATCH v2 0/2] Support meter policy API Li Zhang
  2021-04-02 10:36   ` [dpdk-dev] [PATCH v2 1/2] ethdev: add pre-defined " Li Zhang
@ 2021-04-02 10:36   ` Li Zhang
  1 sibling, 0 replies; 8+ messages in thread
From: Li Zhang @ 2021-04-02 10:36 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, cristian.dumitrescu,
	lironh, Xiaoyun Li
  Cc: dev, thomas, rasland, roniba, Haifei Luo

From: Haifei Luo <haifeil@nvidia.com>

add the new create meter with policy API to support it.

Signed-off-by: Haifei Luo <haifeil@nvidia.com>
---
 app/test-pmd/cmdline.c      |   6 +-
 app/test-pmd/cmdline_flow.c | 118 +++++++++++++++++++++++++++++++++++-
 app/test-pmd/cmdline_mtr.c  |  85 ++++++++++++++++++++++++--
 app/test-pmd/cmdline_mtr.h  |   3 +
 app/test-pmd/config.c       |  34 +++++++++++
 app/test-pmd/testpmd.h      |   2 +
 6 files changed, 240 insertions(+), 8 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index dcb5f9c871..029cb38786 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -705,7 +705,7 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"del port meter profile (port_id) (profile_id)\n"
 			"    meter profile delete\n\n"
 
-			"create port meter (port_id) (mtr_id) (profile_id) (meter_enable)\n"
+			"create port meter (port_id) [mtr_id] (profile_id) [policy (policy_id)] (meter_enable)\n"
 			"(g_action) (y_action) (r_action) (stats_mask) (shared)\n"
 			"(use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
 			"(dscp_tbl_entry63)]\n"
@@ -720,6 +720,9 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"del port meter (port_id) (mtr_id)\n"
 			"    meter delete\n\n"
 
+			"del port meter policy (port_id) (policy_id)\n"
+			"    meter policy delete\n\n"
+
 			"set port meter profile (port_id) (mtr_id) (profile_id)\n"
 			"    meter update meter profile\n\n"
 
@@ -17067,6 +17070,7 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_enable_port_meter,
 	(cmdline_parse_inst_t *)&cmd_disable_port_meter,
 	(cmdline_parse_inst_t *)&cmd_del_port_meter,
+	(cmdline_parse_inst_t *)&cmd_del_port_meter_policy,
 	(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_stats_mask,
diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 2c40c6996e..050290990a 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -55,6 +55,10 @@ enum index {
 	GROUP_ID,
 	PRIORITY_LEVEL,
 	SHARED_ACTION_ID,
+	POLICY_ID,
+
+	/* TOP-level command. */
+	ADD,
 
 	/* Top-level command. */
 	SET,
@@ -289,6 +293,9 @@ enum index {
 	ITEM_GENEVE_OPT_TYPE,
 	ITEM_GENEVE_OPT_LENGTH,
 	ITEM_GENEVE_OPT_DATA,
+	ITEM_POL_PORT,
+	ITEM_POL_METER,
+	ITEM_POL_POLICY,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -427,6 +434,9 @@ enum index {
 	ACTION_MODIFY_FIELD_SRC_OFFSET,
 	ACTION_MODIFY_FIELD_SRC_VALUE,
 	ACTION_MODIFY_FIELD_WIDTH,
+	ACTION_POL_G,
+	ACTION_POL_Y,
+	ACTION_POL_R,
 };
 
 /** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -806,6 +816,9 @@ struct buffer {
 		struct {
 			int destroy;
 		} aged; /**< Aged arguments. */
+		struct {
+			uint32_t policy_id;
+		} policy;/**< Policy arguments. */
 	} args; /**< Command arguments. */
 };
 
@@ -1781,6 +1794,9 @@ static int parse_ipv6_addr(struct context *, const struct token *,
 static int parse_port(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
+static int parse_mp(struct context *, const struct token *,
+			const char *, unsigned int,
+			void *, unsigned int);
 static int parse_sa(struct context *, const struct token *,
 		    const char *, unsigned int,
 		    void *, unsigned int);
@@ -1819,7 +1835,7 @@ static const struct token token_list[] = {
 	[ZERO] = {
 		.name = "ZERO",
 		.help = "null entry, abused as the entry point",
-		.next = NEXT(NEXT_ENTRY(FLOW)),
+		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
 	},
 	[END] = {
 		.name = "",
@@ -1941,6 +1957,13 @@ static const struct token token_list[] = {
 		.call = parse_int,
 		.comp = comp_none,
 	},
+	[POLICY_ID] = {
+		.name = "{policy_id}",
+		.type = "POLCIY_ID",
+		.help = "policy id",
+		.call = parse_int,
+		.comp = comp_none,
+	},
 	/* Top-level command. */
 	[FLOW] = {
 		.name = "flow",
@@ -4524,6 +4547,54 @@ static const struct token token_list[] = {
 		.help = "specify action to share",
 		.next = NEXT(next_action),
 	},
+	[ACTION_POL_G] = {
+		.name = "g_actions",
+		.help = "submit a list of associated actions for green",
+		.next = NEXT(next_action),
+		.call = parse_mp,
+	},
+	[ACTION_POL_Y] = {
+		.name = "y_actions",
+		.help = "submit a list of associated actions for yellow",
+		.next = NEXT(next_action),
+	},
+	[ACTION_POL_R] = {
+		.name = "r_actions",
+		.help = "submit a list of associated actions for red",
+		.next = NEXT(next_action),
+	},
+
+	/* Top-level command. */
+	[ADD] = {
+		.name = "add",
+		.type = "port meter policy {port_id} {arg}",
+		.help = "add port meter policy",
+		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
+		.call = parse_init,
+	},
+	/* Sub-level commands. */
+	[ITEM_POL_PORT] = {
+		.name = "port",
+		.help = "add port meter policy",
+		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
+	},
+	[ITEM_POL_METER] = {
+		.name = "meter",
+		.help = "add port meter policy",
+		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
+	},
+	[ITEM_POL_POLICY] = {
+		.name = "policy",
+		.help = "add port meter policy",
+		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
+				NEXT_ENTRY(ACTION_POL_Y),
+				NEXT_ENTRY(ACTION_POL_G),
+				NEXT_ENTRY(POLICY_ID),
+				NEXT_ENTRY(PORT_ID)),
+		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
+				ARGS_ENTRY(struct buffer, port)),
+		.call = parse_mp,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
@@ -4708,6 +4779,47 @@ parse_init(struct context *ctx, const struct token *token,
 	return len;
 }
 
+/** Parse tokens for meter policy action commands. */
+static int
+parse_mp(struct context *ctx, const struct token *token,
+	const char *str, unsigned int len,
+	void *buf, unsigned int size)
+{
+	struct buffer *out = buf;
+
+	/* Token name must match. */
+	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+		return -1;
+	/* Nothing else to do if there is no buffer. */
+	if (!out)
+		return len;
+	if (!out->command) {
+		if (ctx->curr != ITEM_POL_POLICY)
+			return -1;
+		if (sizeof(*out) > size)
+			return -1;
+		out->command = ctx->curr;
+		ctx->objdata = 0;
+		ctx->object = out;
+		ctx->objmask = NULL;
+		out->args.vc.data = (uint8_t *)out + size;
+		return len;
+	}
+	switch (ctx->curr) {
+	case ACTION_POL_G:
+		out->args.vc.actions =
+			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+					sizeof(double));
+		out->command = ctx->curr;
+		ctx->objdata = 0;
+		ctx->object = out;
+		ctx->objmask = NULL;
+		return len;
+	default:
+		return -1;
+	}
+}
+
 /** Parse tokens for shared action commands. */
 static int
 parse_sa(struct context *ctx, const struct token *token,
@@ -7665,6 +7777,10 @@ cmd_flow_parsed(const struct buffer *in)
 	case TUNNEL_LIST:
 		port_flow_tunnel_list(in->port);
 		break;
+	case ACTION_POL_G:
+		port_meter_policy_add(in->port, in->args.policy.policy_id,
+					in->args.vc.actions);
+		break;
 	default:
 		break;
 	}
diff --git a/app/test-pmd/cmdline_mtr.c b/app/test-pmd/cmdline_mtr.c
index 44394e3ea1..bdc9ae8bfe 100644
--- a/app/test-pmd/cmdline_mtr.c
+++ b/app/test-pmd/cmdline_mtr.c
@@ -37,6 +37,8 @@ print_err_msg(struct rte_mtr_error *error)
 		[RTE_MTR_ERROR_TYPE_STATS] = "stats",
 		[RTE_MTR_ERROR_TYPE_SHARED]
 			= "shared meter",
+		[RTE_MTR_ERROR_TYPE_METER_POLICY_ID] = "meter policy id",
+		[RTE_MTR_ERROR_TYPE_METER_POLICY] = "meter policy null",
 	};
 
 	const char *errstr;
@@ -56,6 +58,12 @@ print_err_msg(struct rte_mtr_error *error)
 		error->type);
 }
 
+void
+print_mtr_err_msg(struct rte_mtr_error *error)
+{
+	print_err_msg(error);
+}
+
 static int
 parse_uint(uint64_t *value, const char *str)
 {
@@ -671,6 +679,7 @@ struct cmd_create_port_meter_result {
 	uint16_t port_id;
 	uint32_t mtr_id;
 	uint32_t profile_id;
+	uint32_t policy_id;
 	cmdline_fixed_string_t meter_enable;
 	cmdline_fixed_string_t g_action;
 	cmdline_fixed_string_t y_action;
@@ -698,6 +707,9 @@ cmdline_parse_token_num_t cmd_create_port_meter_mtr_id =
 cmdline_parse_token_num_t cmd_create_port_meter_profile_id =
 	TOKEN_NUM_INITIALIZER(
 		struct cmd_create_port_meter_result, profile_id, RTE_UINT32);
+cmdline_parse_token_num_t cmd_create_port_meter_policy_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_create_port_meter_result, policy_id, RTE_UINT32);
 cmdline_parse_token_string_t cmd_create_port_meter_meter_enable =
 	TOKEN_STRING_INITIALIZER(struct cmd_create_port_meter_result,
 		meter_enable, "yes#no");
@@ -741,7 +753,7 @@ static void cmd_create_port_meter_parsed(void *parsed_result,
 	/* Meter params */
 	memset(&params, 0, sizeof(struct rte_mtr_params));
 	params.meter_profile_id = res->profile_id;
-
+	params.meter_policy_id = res->policy_id;
 	/* Parse meter input color string params */
 	ret = parse_meter_color_str(c_str, &use_prev_meter_color, &dscp_table);
 	if (ret) {
@@ -756,7 +768,6 @@ static void cmd_create_port_meter_parsed(void *parsed_result,
 		params.meter_enable = 1;
 	else
 		params.meter_enable = 0;
-
 	params.stats_mask = res->statistics_mask;
 
 	ret = rte_mtr_create(port_id, mtr_id, &params, shared, &error);
@@ -771,7 +782,6 @@ cmdline_parse_inst_t cmd_create_port_meter = {
 	.f = cmd_create_port_meter_parsed,
 	.data = NULL,
 	.help_str = "create port meter <port_id> <mtr_id> <profile_id> <meter_enable>(yes|no) "
-		"<g_action>(R|Y|G|D) <y_action>(R|Y|G|D) <r_action>(R|Y|G|D) "
 		"<stats_mask> <shared> <use_pre_meter_color> "
 		"[<dscp_tbl_entry0> <dscp_tbl_entry1> ...<dscp_tbl_entry63>]",
 	.tokens = {
@@ -781,10 +791,8 @@ cmdline_parse_inst_t cmd_create_port_meter = {
 		(void *)&cmd_create_port_meter_port_id,
 		(void *)&cmd_create_port_meter_mtr_id,
 		(void *)&cmd_create_port_meter_profile_id,
+		(void *)&cmd_create_port_meter_policy_id,
 		(void *)&cmd_create_port_meter_meter_enable,
-		(void *)&cmd_create_port_meter_g_action,
-		(void *)&cmd_create_port_meter_y_action,
-		(void *)&cmd_create_port_meter_r_action,
 		(void *)&cmd_create_port_meter_statistics_mask,
 		(void *)&cmd_create_port_meter_shared,
 		(void *)&cmd_create_port_meter_input_color,
@@ -914,6 +922,71 @@ cmdline_parse_inst_t cmd_disable_port_meter = {
 	},
 };
 
+/* *** Delete Port Meter Policy Object *** */
+struct cmd_del_port_meter_policy_result {
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t policy;
+	uint16_t port_id;
+	uint32_t policy_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_meter_policy_del =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_policy_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_meter_policy_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_policy_result, port, "port");
+cmdline_parse_token_string_t cmd_del_port_meter_policy_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_policy_result, meter, "meter");
+cmdline_parse_token_string_t cmd_del_port_meter_policy_policy =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_policy_result, policy, "policy");
+cmdline_parse_token_num_t cmd_del_port_meter_policy_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_policy_result, port_id, RTE_UINT16);
+cmdline_parse_token_num_t cmd_del_port_meter_policy_policy_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_policy_result, policy_id, RTE_UINT32);
+
+static void cmd_del_port_meter_policy_parsed(void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	__rte_unused void *data)
+{
+	struct cmd_del_port_meter_policy_result *res = parsed_result;
+	struct rte_mtr_error error;
+	uint32_t policy_id = res->policy_id;
+	uint16_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Delete Meter Policy*/
+	ret = rte_mtr_meter_policy_delete(port_id, policy_id, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_del_port_meter_policy = {
+	.f = cmd_del_port_meter_policy_parsed,
+	.data = NULL,
+	.help_str = "Delete port meter policy",
+	.tokens = {
+		(void *)&cmd_del_port_meter_policy_del,
+		(void *)&cmd_del_port_meter_policy_port,
+		(void *)&cmd_del_port_meter_policy_meter,
+		(void *)&cmd_del_port_meter_policy_policy,
+		(void *)&cmd_del_port_meter_policy_port_id,
+		(void *)&cmd_del_port_meter_policy_policy_id,
+		NULL,
+	},
+};
+
 /* *** Delete Port Meter Object *** */
 struct cmd_del_port_meter_result {
 	cmdline_fixed_string_t del;
diff --git a/app/test-pmd/cmdline_mtr.h b/app/test-pmd/cmdline_mtr.h
index 7e2713cea3..2415fc16c3 100644
--- a/app/test-pmd/cmdline_mtr.h
+++ b/app/test-pmd/cmdline_mtr.h
@@ -4,6 +4,7 @@
 
 #ifndef _CMDLINE_MTR_H_
 #define _CMDLINE_MTR_H_
+#include <rte_mtr.h>
 
 /* Traffic Metering and Policing */
 extern cmdline_parse_inst_t cmd_show_port_meter_cap;
@@ -15,9 +16,11 @@ extern cmdline_parse_inst_t cmd_create_port_meter;
 extern cmdline_parse_inst_t cmd_enable_port_meter;
 extern cmdline_parse_inst_t cmd_disable_port_meter;
 extern cmdline_parse_inst_t cmd_del_port_meter;
+extern cmdline_parse_inst_t cmd_del_port_meter_policy;
 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_stats_mask;
 extern cmdline_parse_inst_t cmd_show_port_meter_stats;
+void print_mtr_err_msg(struct rte_mtr_error *error);
 
 #endif /* _CMDLINE_MTR_H_ */
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index ef0b9784d0..336b9b500e 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -38,6 +38,7 @@
 #include <rte_string_fns.h>
 #include <rte_cycles.h>
 #include <rte_flow.h>
+#include <rte_mtr.h>
 #include <rte_errno.h>
 #ifdef RTE_NET_IXGBE
 #include <rte_pmd_ixgbe.h>
@@ -52,6 +53,7 @@
 #include <rte_hexdump.h>
 
 #include "testpmd.h"
+#include "cmdline_mtr.h"
 
 #define ETHDEV_FWVERS_LEN 32
 
@@ -1464,6 +1466,38 @@ action_alloc(portid_t port_id, uint32_t id,
 	return 0;
 }
 
+/** Add port meter policy */
+int
+port_meter_policy_add(portid_t port_id, uint32_t policy_id,
+			const struct rte_flow_action *actions)
+{
+	struct rte_mtr_error error;
+	const struct rte_flow_action *acts[RTE_COLORS];
+	const struct rte_flow_action *act = actions;
+	const struct rte_flow_action *start;
+	uint32_t i = 0, act_n;
+	int ret;
+
+	for (i = 0; i < RTE_COLORS; i++) {
+		for (act_n = 0, start = act;
+			act->type != RTE_FLOW_ACTION_TYPE_END; act++)
+			act_n++;
+		if (act_n && act->type == RTE_FLOW_ACTION_TYPE_END)
+			acts[i] = start;
+		else
+			acts[i] = NULL;
+		act++;
+	}
+	ret = rte_mtr_meter_policy_create(port_id,
+			policy_id,
+			acts, &error);
+	if (ret) {
+		print_mtr_err_msg(&error);
+		return -1;
+	}
+	return policy_id;
+}
+
 /** Create shared action */
 int
 port_shared_action_create(portid_t port_id, uint32_t id,
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index a87ccb0f0f..bc7cb7e9b9 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -837,6 +837,8 @@ void port_flow_tunnel_list(portid_t port_id);
 void port_flow_tunnel_destroy(portid_t port_id, uint32_t tunnel_id);
 void port_flow_tunnel_create(portid_t port_id, const struct tunnel_ops *ops);
 int port_flow_isolate(portid_t port_id, int set);
+int port_meter_policy_add(portid_t port_id, uint32_t policy_id,
+		const struct rte_flow_action *actions);
 
 void rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id);
 void tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id);
-- 
2.27.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/2] ethdev: add pre-defined meter policy API
  2021-04-02 10:36   ` [dpdk-dev] [PATCH v2 1/2] ethdev: add pre-defined " Li Zhang
@ 2021-04-08 13:55     ` Ori Kam
  2021-04-08 14:37       ` Li Zhang
  0 siblings, 1 reply; 8+ messages in thread
From: Ori Kam @ 2021-04-08 13:55 UTC (permalink / raw)
  To: Li Zhang, dekelp, Slava Ovsiienko, Matan Azrad, Shahaf Shuler,
	cristian.dumitrescu, lironh, Wisam Monther, Xiaoyun Li,
	Jasvinder Singh, NBU-Contact-Thomas Monjalon, Ferruh Yigit,
	Andrew Rybchenko, Ray Kinsella, Neil Horman
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai, Haifei Luo

Hi Li,

> -----Original Message-----
> From: Li Zhang <lizh@nvidia.com>
> Sent: Friday, April 2, 2021 1:36 PM
> Subject: [PATCH v2 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.
> 
> Policy id 0 is default policy. Action per color as below:
> green - nothing, yellow - nothing, red - drop
> 
> 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.
> 3. Create default policy if policy id is RTE_MTR_DEFAULT_POLICY_ID.
>    default policy actoins:
>    green - do nothing, yellow - do nothing, red - drop
> 
> 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>
> ---
>  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/nics/mlx5.rst                      |  12 +
>  doc/guides/prog_guide/rte_flow.rst            |  20 +
>  .../traffic_metering_and_policing.rst         |   9 +-
>  doc/guides/rel_notes/release_21_05.rst        |  14 +-
>  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              |  15 +-
>  drivers/net/mlx5/mlx5_flow_dv.c               | 463 +-----------------
>  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                  |  18 +
>  lib/librte_ethdev/rte_mtr.c                   |  55 ++-
>  lib/librte_ethdev/rte_mtr.h                   | 157 ++++--
>  lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
>  lib/librte_ethdev/version.map                 |   4 +
>  23 files changed, 510 insertions(+), 1258 deletions(-)
> 
> diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c
> index 99d0463456..66ec776017 100644
> --- a/app/test-flow-perf/main.c
> +++ b/app/test-flow-perf/main.c
> @@ -924,13 +924,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",
,

[snip]

> 
>  	.stats_read = pmd_mtr_stats_read,
> diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
> index 6cc57136ac..0c5807deea 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,13 @@ 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.
> +	 *
> +	 * See struct rte_flow_action_meter_color.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_METER_COLOR,

Following previous discussion in the ML
I agree to this change with few comments:
1. This action will be experimental and we might change it later
to adjust to other rte_flow actions.
2. please make sure in the doc and comment above that it is documented
That this goes to mbuf field 
Something like:
Set the meter color in the mbuf to the selected color.
Since it doesn't color the packet for the rest of the rte_flow.

[snip]
Best
Ori

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/2] ethdev: add pre-defined meter policy API
  2021-04-08 13:55     ` Ori Kam
@ 2021-04-08 14:37       ` Li Zhang
  0 siblings, 0 replies; 8+ messages in thread
From: Li Zhang @ 2021-04-08 14:37 UTC (permalink / raw)
  To: Ori Kam, dekelp, Slava Ovsiienko, Matan Azrad, Shahaf Shuler,
	cristian.dumitrescu, lironh, Wisam Monther, Xiaoyun Li,
	Jasvinder Singh, NBU-Contact-Thomas Monjalon, Ferruh Yigit,
	Andrew Rybchenko, Ray Kinsella, Neil Horman
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai, Haifei Luo

Hi Ori,

Thank you for your comments.
I will add it into V3 patch.

Regards,
Li Zhang
> -----Original Message-----
> From: Ori Kam <orika@nvidia.com>
> Sent: Thursday, April 8, 2021 9:55 PM
> To: Li Zhang <lizh@nvidia.com>; dekelp@nvidia.com; Slava Ovsiienko
> <viacheslavo@nvidia.com>; Matan Azrad <matan@nvidia.com>; Shahaf
> Shuler <shahafs@nvidia.com>; cristian.dumitrescu@intel.com;
> lironh@marvell.com; Wisam Monther <wisamm@nvidia.com>; Xiaoyun Li
> <xiaoyun.li@intel.com>; Jasvinder Singh <jasvinder.singh@intel.com>; NBU-
> Contact-Thomas Monjalon <thomas@monjalon.net>; Ferruh Yigit
> <ferruh.yigit@intel.com>; Andrew Rybchenko
> <andrew.rybchenko@oktetlabs.ru>; Ray Kinsella <mdr@ashroe.eu>; Neil
> Horman <nhorman@tuxdriver.com>
> Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar Yanai
> <roniba@nvidia.com>; Haifei Luo <haifeil@nvidia.com>
> Subject: RE: [PATCH v2 1/2] ethdev: add pre-defined meter policy API
> 
> Hi Li,
> 
> > -----Original Message-----
> > From: Li Zhang <lizh@nvidia.com>
> > Sent: Friday, April 2, 2021 1:36 PM
> > Subject: [PATCH v2 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.
> >
> > Policy id 0 is default policy. Action per color as below:
> > green - nothing, yellow - nothing, red - drop
> >
> > 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.
> > 3. Create default policy if policy id is RTE_MTR_DEFAULT_POLICY_ID.
> >    default policy actoins:
> >    green - do nothing, yellow - do nothing, red - drop
> >
> > 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>
> > ---
> >  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/nics/mlx5.rst                      |  12 +
> >  doc/guides/prog_guide/rte_flow.rst            |  20 +
> >  .../traffic_metering_and_policing.rst         |   9 +-
> >  doc/guides/rel_notes/release_21_05.rst        |  14 +-
> >  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              |  15 +-
> >  drivers/net/mlx5/mlx5_flow_dv.c               | 463 +-----------------
> >  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                  |  18 +
> >  lib/librte_ethdev/rte_mtr.c                   |  55 ++-
> >  lib/librte_ethdev/rte_mtr.h                   | 157 ++++--
> >  lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
> >  lib/librte_ethdev/version.map                 |   4 +
> >  23 files changed, 510 insertions(+), 1258 deletions(-)
> >
> > diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c
> > index 99d0463456..66ec776017 100644
> > --- a/app/test-flow-perf/main.c
> > +++ b/app/test-flow-perf/main.c
> > @@ -924,13 +924,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",
> ,
> 
> [snip]
> 
> >
> >  	.stats_read = pmd_mtr_stats_read,
> > diff --git a/lib/librte_ethdev/rte_flow.h
> > b/lib/librte_ethdev/rte_flow.h index 6cc57136ac..0c5807deea 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,13 @@ 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.
> > +	 *
> > +	 * See struct rte_flow_action_meter_color.
> > +	 */
> > +	RTE_FLOW_ACTION_TYPE_METER_COLOR,
> 
> Following previous discussion in the ML
> I agree to this change with few comments:
> 1. This action will be experimental and we might change it later to adjust to
> other rte_flow actions.
> 2. please make sure in the doc and comment above that it is documented That
> this goes to mbuf field Something like:
> Set the meter color in the mbuf to the selected color.
> Since it doesn't color the packet for the rest of the rte_flow.
> 
> [snip]
> Best
> Ori

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2021-04-08 14:37 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-01  6:54 [dpdk-dev] [PATCH 0/2] Support meter policy API Li Zhang
2021-04-01  6:54 ` [dpdk-dev] [PATCH 1/2] ethdev: add pre-defined " Li Zhang
2021-04-01  6:54 ` [dpdk-dev] [PATCH 2/2] app/testpmd: support policy actions per color Li Zhang
2021-04-02 10:36 ` [dpdk-dev] [PATCH v2 0/2] Support meter policy API Li Zhang
2021-04-02 10:36   ` [dpdk-dev] [PATCH v2 1/2] ethdev: add pre-defined " Li Zhang
2021-04-08 13:55     ` Ori Kam
2021-04-08 14:37       ` Li Zhang
2021-04-02 10:36   ` [dpdk-dev] [PATCH v2 2/2] app/testpmd: support policy actions per color Li Zhang

DPDK patches and discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://inbox.dpdk.org/dev/0 dev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dev dev/ https://inbox.dpdk.org/dev \
		dev@dpdk.org
	public-inbox-index dev

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://inbox.dpdk.org/inbox.dpdk.dev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git