All of lore.kernel.org
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
@ 2021-03-18  8:58 Li Zhang
  2021-03-18  8:58 ` [dpdk-dev] [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by the drivers Li Zhang
                   ` (9 more replies)
  0 siblings, 10 replies; 78+ messages in thread
From: Li Zhang @ 2021-03-18  8:58 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, lironh,
	jasvinder.singh, Thomas Monjalon, Ferruh Yigit, Andrew Rybchenko,
	Cristian Dumitrescu
  Cc: dev, rasland, roniba

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 15813 bytes --]

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 - no action, yellow - no action, 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_add
- 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

Signed-off-by: Li Zhang <lizh@nvidia.com>
---
 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 |  45 ++++++--
 4 files changed, 210 insertions(+), 74 deletions(-)

diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
index 669e677e91..5f38aa7fa4 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -31,6 +31,7 @@
 #include <rte_ecpri.h>
 #include <rte_mbuf.h>
 #include <rte_mbuf_dyn.h>
+#include <rte_meter.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -2236,6 +2237,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_COlOR,
 };
 
 /**
@@ -2828,6 +2836,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..fccec3760b 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 add */
+int
+rte_mtr_meter_policy_add(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_add)(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..07961f2777 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
 	 */
@@ -462,6 +441,94 @@ 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 - no action, yellow - no action, red - drop
+ * It can be used without creating it by the rte_mtr_meter_policy_add 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] policy_id
+ *   Policy identifier for the new meter policy.
+ * @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,
+	uint32_t policy_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_add(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..1ad8fb4c40 100644
--- a/lib/librte_ethdev/rte_mtr_driver.h
+++ b/lib/librte_ethdev/rte_mtr_driver.h
@@ -41,6 +41,23 @@ 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,
+	uint32_t policy_id,
+	const struct rte_flow_action *actions[RTE_COLORS],
+	struct rte_mtr_error *error);
+/**< @internal MTR meter policy validate */
+
+typedef int (*rte_mtr_meter_policy_add_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 +86,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 +140,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 add */
+	rte_mtr_meter_policy_add_t meter_policy_add;
+
+	/** 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;
 };
 
 /**
-- 
2.21.0


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

* [dpdk-dev] [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by the drivers
  2021-03-18  8:58 [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API Li Zhang
@ 2021-03-18  8:58 ` Li Zhang
  2021-03-23 21:33   ` Dumitrescu, Cristian
  2021-03-23 21:02 ` [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API Dumitrescu, Cristian
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 78+ messages in thread
From: Li Zhang @ 2021-03-18  8:58 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, lironh,
	jasvinder.singh, Thomas Monjalon, Ferruh Yigit, Andrew Rybchenko,
	Cristian Dumitrescu
  Cc: dev, rasland, roniba

Currently, all the meter objects are managed by the user IDs:
meter, profile and policy.
Hence, each PMD should manage data-structure in order to
map each API ID to the private PMD management structure.

From the application side, it has all the picture how meter
is going to be assigned to flows and can easily use direct
mapping even when the meter handler is provided by the PMDs.

Also, this is the approach of the rte_flow API handles:
the flow handle and the shared action handle
is provided by the PMDs.

Use drivers handlers in order to manage all the meter API objects.

The following API will be changed:
- rte_mtr_meter_profile_add
- rte_mtr_meter_profile_delete
- rte_mtr_meter_policy_validate
- rte_mtr_meter_policy_add
- rte_mtr_meter_policy_delete
- rte_mtr_create
- rte_mtr_destroy
- rte_mtr_meter_disable
- rte_mtr_meter_enable
- rte_mtr_meter_profile_update
- rte_mtr_meter_policy_update
- rte_mtr_meter_dscp_table_update
- rte_mtr_stats_update
- rte_mtr_stats_read
The next struct will be changed:
- rte_flow_action_meter
- rte_mtr_params

Signed-off-by: Li Zhang <lizh@nvidia.com>
---
 lib/librte_ethdev/rte_flow.h       |   9 ++-
 lib/librte_ethdev/rte_mtr.c        |  77 ++++++++++++----------
 lib/librte_ethdev/rte_mtr.h        | 102 +++++++++++++++--------------
 lib/librte_ethdev/rte_mtr_driver.h |  36 +++++-----
 4 files changed, 122 insertions(+), 102 deletions(-)

diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
index 5f38aa7fa4..6d2b86592d 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -2480,6 +2480,13 @@ struct rte_flow_action_port_id {
 	uint32_t id; /**< DPDK port ID. */
 };
 
+/**
+ * Opaque type returned after successfully creating a meter.
+ *
+ * This handle can be used to manage the related meter (e.g. to destroy it).
+ */
+struct rte_mtr;
+
 /**
  * RTE_FLOW_ACTION_TYPE_METER
  *
@@ -2489,7 +2496,7 @@ struct rte_flow_action_port_id {
  * next item with their color set by the MTR object.
  */
 struct rte_flow_action_meter {
-	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create(). */
+	struct rte_mtr *mtr; /**< MTR object created with rte_mtr_create(). */
 };
 
 /**
diff --git a/lib/librte_ethdev/rte_mtr.c b/lib/librte_ethdev/rte_mtr.c
index fccec3760b..e407c6f956 100644
--- a/lib/librte_ethdev/rte_mtr.c
+++ b/lib/librte_ethdev/rte_mtr.c
@@ -57,6 +57,19 @@ rte_mtr_ops_get(uint16_t port_id, struct rte_mtr_error *error)
 	ops->func;					\
 })
 
+#define RTE_MTR_FUNC_PTR(port_id, func)			\
+({							\
+	const struct rte_mtr_ops *ops =			\
+		rte_mtr_ops_get(port_id, error);	\
+	if (ops == NULL)				\
+		return NULL;				\
+							\
+	if (ops->func == NULL)				\
+		return NULL;				\
+							\
+	ops->func;					\
+})
+
 /* MTR capabilities get */
 int
 rte_mtr_capabilities_get(uint16_t port_id,
@@ -69,26 +82,25 @@ rte_mtr_capabilities_get(uint16_t port_id,
 }
 
 /* MTR meter profile add */
-int
+struct rte_mtr_profile *
 rte_mtr_meter_profile_add(uint16_t port_id,
-	uint32_t meter_profile_id,
 	struct rte_mtr_meter_profile *profile,
 	struct rte_mtr_error *error)
 {
 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
-	return RTE_MTR_FUNC(port_id, meter_profile_add)(dev,
-		meter_profile_id, profile, error);
+	return RTE_MTR_FUNC_PTR(port_id, meter_profile_add)(dev,
+		profile, error);
 }
 
 /** MTR meter profile delete */
 int
 rte_mtr_meter_profile_delete(uint16_t port_id,
-	uint32_t meter_profile_id,
+	struct rte_mtr_profile *profile,
 	struct rte_mtr_error *error)
 {
 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
 	return RTE_MTR_FUNC(port_id, meter_profile_delete)(dev,
-		meter_profile_id, error);
+		profile, error);
 }
 
 /* MTR meter policy validate */
@@ -103,126 +115,123 @@ rte_mtr_meter_policy_validate(uint16_t port_id,
 }
 
 /* MTR meter policy add */
-int
+struct rte_mtr_policy *
 rte_mtr_meter_policy_add(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_add)(dev,
-		policy_id, actions, error);
+	return RTE_MTR_FUNC_PTR(port_id, meter_policy_add)(dev,
+		actions, error);
 }
 
 /** MTR meter policy delete */
 int
 rte_mtr_meter_policy_delete(uint16_t port_id,
-	uint32_t policy_id,
+	struct rte_mtr_policy *policy,
 	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);
+		policy, error);
 }
 
 /** MTR object create */
-int
+struct rte_mtr *
 rte_mtr_create(uint16_t port_id,
-	uint32_t mtr_id,
 	struct rte_mtr_params *params,
 	int shared,
 	struct rte_mtr_error *error)
 {
 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
-	return RTE_MTR_FUNC(port_id, create)(dev,
-		mtr_id, params, shared, error);
+	return RTE_MTR_FUNC_PTR(port_id, create)(dev, params, shared, error);
 }
 
 /** MTR object destroy */
 int
 rte_mtr_destroy(uint16_t port_id,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	struct rte_mtr_error *error)
 {
 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
 	return RTE_MTR_FUNC(port_id, destroy)(dev,
-		mtr_id, error);
+		mtr, error);
 }
 
 /** MTR object meter enable */
 int
 rte_mtr_meter_enable(uint16_t port_id,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	struct rte_mtr_error *error)
 {
 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
 	return RTE_MTR_FUNC(port_id, meter_enable)(dev,
-		mtr_id, error);
+		mtr, error);
 }
 
 /** MTR object meter disable */
 int
 rte_mtr_meter_disable(uint16_t port_id,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	struct rte_mtr_error *error)
 {
 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
 	return RTE_MTR_FUNC(port_id, meter_disable)(dev,
-		mtr_id, error);
+		mtr, error);
 }
 
 /** MTR object meter profile update */
 int
 rte_mtr_meter_profile_update(uint16_t port_id,
-	uint32_t mtr_id,
-	uint32_t meter_profile_id,
+	struct rte_mtr *mtr,
+	struct rte_mtr_profile *profile,
 	struct rte_mtr_error *error)
 {
 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
 	return RTE_MTR_FUNC(port_id, meter_profile_update)(dev,
-		mtr_id, meter_profile_id, error);
+		mtr, profile, error);
 }
 
 /** MTR object meter policy update */
 int
 rte_mtr_meter_policy_update(uint16_t port_id,
-	uint32_t mtr_id,
-	uint32_t meter_policy_id,
+	struct rte_mtr *mtr,
+	struct rte_mtr_policy *policy,
 	struct rte_mtr_error *error)
 {
 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
 	return RTE_MTR_FUNC(port_id, meter_policy_update)(dev,
-		mtr_id, meter_policy_id, error);
+		mtr, policy, error);
 }
 
 /** MTR object meter DSCP table update */
 int
 rte_mtr_meter_dscp_table_update(uint16_t port_id,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	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, meter_dscp_table_update)(dev,
-		mtr_id, dscp_table, error);
+		mtr, dscp_table, error);
 }
 
 /** MTR object enabled stats update */
 int
 rte_mtr_stats_update(uint16_t port_id,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	uint64_t stats_mask,
 	struct rte_mtr_error *error)
 {
 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
 	return RTE_MTR_FUNC(port_id, stats_update)(dev,
-		mtr_id, stats_mask, error);
+		mtr, stats_mask, error);
 }
 
 /** MTR object stats read */
 int
 rte_mtr_stats_read(uint16_t port_id,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	struct rte_mtr_stats *stats,
 	uint64_t *stats_mask,
 	int clear,
@@ -230,5 +239,5 @@ rte_mtr_stats_read(uint16_t port_id,
 {
 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
 	return RTE_MTR_FUNC(port_id, stats_read)(dev,
-		mtr_id, stats, stats_mask, clear, error);
+		mtr, stats, stats_mask, clear, error);
 }
diff --git a/lib/librte_ethdev/rte_mtr.h b/lib/librte_ethdev/rte_mtr.h
index 07961f2777..2b20e55079 100644
--- a/lib/librte_ethdev/rte_mtr.h
+++ b/lib/librte_ethdev/rte_mtr.h
@@ -181,8 +181,8 @@ struct rte_mtr_meter_profile {
  * @see enum rte_mtr_stats_type
  */
 struct rte_mtr_params {
-	/** Meter profile ID. */
-	uint32_t meter_profile_id;
+	/** Meter profile. */
+	struct rte_mtr_profile *profile;
 
 	/** Meter input color in case of MTR object chaining. When non-zero: if
 	 * a previous MTR object is enabled in the same flow, then the color
@@ -221,8 +221,8 @@ struct rte_mtr_params {
 	 */
 	uint64_t stats_mask;
 
-	/** Meter policy ID. */
-	uint32_t meter_policy_id;
+	/** Meter policy. */
+	struct rte_mtr_policy *policy;
 };
 
 /**
@@ -395,28 +395,32 @@ rte_mtr_capabilities_get(uint16_t port_id,
 	struct rte_mtr_capabilities *cap,
 	struct rte_mtr_error *error);
 
+/**
+ * Opaque type returned after successfully creating a profile.
+ *
+ * This handle can be used to manage the related profile (e.g. to destroy it).
+ */
+struct rte_mtr_profile;
+
 /**
  * Meter profile add
  *
- * Create a new meter profile with ID set to *meter_profile_id*. The new profile
+ * Create a new meter profile. The new profile
  * is used to create one or several MTR objects.
  *
  * @param[in] port_id
  *   The port identifier of the Ethernet device.
- * @param[in] meter_profile_id
- *   ID for the new meter profile. Needs to be unused by any of the existing
- *   meter profiles added for the current port.
  * @param[in] profile
  *   Meter profile parameters. Needs to be pre-allocated and valid.
  * @param[out] error
  *   Error details. Filled in only on error, when not NULL.
  * @return
- *   0 on success, non-zero error code otherwise.
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to the positive version of one of the error codes.
  */
 __rte_experimental
-int
+struct rte_mtr_profile *
 rte_mtr_meter_profile_add(uint16_t port_id,
-	uint32_t meter_profile_id,
 	struct rte_mtr_meter_profile *profile,
 	struct rte_mtr_error *error);
 
@@ -428,8 +432,8 @@ rte_mtr_meter_profile_add(uint16_t port_id,
  *
  * @param[in] port_id
  *   The port identifier of the Ethernet device.
- * @param[in] meter_profile_id
- *   Meter profile ID. Needs to be the valid.
+ * @param[in] profile
+ *   Meter profile pointer. Needs to be the valid.
  * @param[out] error
  *   Error details. Filled in only on error, when not NULL.
  * @return
@@ -438,16 +442,15 @@ rte_mtr_meter_profile_add(uint16_t port_id,
 __rte_experimental
 int
 rte_mtr_meter_profile_delete(uint16_t port_id,
-	uint32_t meter_profile_id,
+	struct rte_mtr_profile *profile,
 	struct rte_mtr_error *error);
 
 /**
- * Policy id 0 is default policy.
- * Action per color as below:
- * green - no action, yellow - no action, red - drop
- * It can be used without creating it by the rte_mtr_meter_policy_add function.
+ * Opaque type returned after successfully creating a policy.
+ *
+ * This handle can be used to manage the related policy (e.g. to destroy it).
  */
-#define RTE_MTR_DEFAULT_POLICY_ID 0
+struct rte_mtr_policy;
 
 /**
  * Check whether a meter policy can be created on a given port.
@@ -478,7 +481,6 @@ rte_mtr_meter_profile_delete(uint16_t port_id,
 __rte_experimental
 int
 rte_mtr_meter_policy_validate(uint16_t port_id,
-	uint32_t policy_id,
 	const struct rte_flow_action *actions[RTE_COLORS],
 	struct rte_mtr_error *error);
 
@@ -490,8 +492,6 @@ rte_mtr_meter_policy_validate(uint16_t port_id,
  *
  * @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.
@@ -499,12 +499,12 @@ rte_mtr_meter_policy_validate(uint16_t port_id,
  * @param[out] error
  *   Error details. Filled in only on error, when not NULL.
  * @return
- *   0 on success, non-zero error code otherwise.
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to the positive version of one of the error codes.
  */
 __rte_experimental
-int
+struct rte_mtr_policy *
 rte_mtr_meter_policy_add(uint16_t port_id,
-	uint32_t policy_id,
 	const struct rte_flow_action *actions[RTE_COLORS],
 	struct rte_mtr_error *error);
 
@@ -516,8 +516,8 @@ rte_mtr_meter_policy_add(uint16_t port_id,
  *
  * @param[in] port_id
  *   The port identifier of the Ethernet device.
- * @param[in] policy_id
- *   Policy identifier.
+ * @param[in] policy
+ *   Policy pointer. Needs to be valid.
  * @param[out] error
  *   Error details. Filled in only on error, when not NULL.
  * @return
@@ -526,20 +526,28 @@ rte_mtr_meter_policy_add(uint16_t port_id,
 __rte_experimental
 int
 rte_mtr_meter_policy_delete(uint16_t port_id,
-	uint32_t policy_id,
+	struct rte_mtr_policy *policy,
 	struct rte_mtr_error *error);
 
+/**
+ * Opaque type returned after successfully creating a meter.
+ *
+ * This handle can be used to manage the related meter (e.g. to destroy it).
+ */
+struct rte_mtr;
+
 /**
  * MTR object create
  *
  * Create a new MTR object for the current port. This object is run as part of
  * associated flow action for traffic metering and policing.
+ * Policy pointer NULL is default policy.
+ * Action per color as below:
+ * green - no action, yellow - no action, red - drop
+ * It can be used without creating it by the rte_mtr_meter_policy_add function.
  *
  * @param[in] port_id
  *   The port identifier of the Ethernet device.
- * @param[in] mtr_id
- *   MTR object ID. Needs to be unused by any of the existing MTR objects.
- *   created for the current port.
  * @param[in] params
  *   MTR object params. Needs to be pre-allocated and valid.
  * @param[in] shared
@@ -548,14 +556,14 @@ rte_mtr_meter_policy_delete(uint16_t port_id,
  * @param[out] error
  *   Error details. Filled in only on error, when not NULL.
  * @return
- *   0 on success, non-zero error code otherwise.
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to the positive version of one of the error codes.
  *
  * @see enum rte_flow_action_type::RTE_FLOW_ACTION_TYPE_METER
  */
 __rte_experimental
-int
+struct rte_mtr *
 rte_mtr_create(uint16_t port_id,
-	uint32_t mtr_id,
 	struct rte_mtr_params *params,
 	int shared,
 	struct rte_mtr_error *error);
@@ -568,8 +576,8 @@ rte_mtr_create(uint16_t port_id,
  *
  * @param[in] port_id
  *   The port identifier of the Ethernet device.
- * @param[in] mtr_id
- *   MTR object ID. Needs to be valid.
+ * @param[in] mtr
+ *   MTR pointer. Needs to be valid.
  *   created for the current port.
  * @param[out] error
  *   Error details. Filled in only on error, when not NULL.
@@ -579,7 +587,7 @@ rte_mtr_create(uint16_t port_id,
 __rte_experimental
 int
 rte_mtr_destroy(uint16_t port_id,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	struct rte_mtr_error *error);
 
 /**
@@ -607,7 +615,7 @@ rte_mtr_destroy(uint16_t port_id,
 __rte_experimental
 int
 rte_mtr_meter_disable(uint16_t port_id,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	struct rte_mtr_error *error);
 
 /**
@@ -629,7 +637,7 @@ rte_mtr_meter_disable(uint16_t port_id,
 __rte_experimental
 int
 rte_mtr_meter_enable(uint16_t port_id,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	struct rte_mtr_error *error);
 
 /**
@@ -649,8 +657,8 @@ rte_mtr_meter_enable(uint16_t port_id,
 __rte_experimental
 int
 rte_mtr_meter_profile_update(uint16_t port_id,
-	uint32_t mtr_id,
-	uint32_t meter_profile_id,
+	struct rte_mtr *mtr,
+	struct rte_mtr_profile *profile,
 	struct rte_mtr_error *error);
 
 /**
@@ -660,8 +668,6 @@ rte_mtr_meter_profile_update(uint16_t port_id,
  *   The port identifier of the Ethernet device.
  * @param[in] mtr_id
  *   MTR object ID. Needs to be valid.
- * @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
@@ -670,8 +676,8 @@ rte_mtr_meter_profile_update(uint16_t port_id,
 __rte_experimental
 int
 rte_mtr_meter_policy_update(uint16_t port_id,
-	uint32_t mtr_id,
-	uint32_t meter_policy_id,
+	struct rte_mtr *mtr,
+	struct rte_mtr_policy *policy,
 	struct rte_mtr_error *error);
 
 /**
@@ -695,7 +701,7 @@ rte_mtr_meter_policy_update(uint16_t port_id,
 __rte_experimental
 int
 rte_mtr_meter_dscp_table_update(uint16_t port_id,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	enum rte_color *dscp_table,
 	struct rte_mtr_error *error);
 
@@ -720,7 +726,7 @@ rte_mtr_meter_dscp_table_update(uint16_t port_id,
 __rte_experimental
 int
 rte_mtr_stats_update(uint16_t port_id,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	uint64_t stats_mask,
 	struct rte_mtr_error *error);
 
@@ -752,7 +758,7 @@ rte_mtr_stats_update(uint16_t port_id,
 __rte_experimental
 int
 rte_mtr_stats_read(uint16_t port_id,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	struct rte_mtr_stats *stats,
 	uint64_t *stats_mask,
 	int clear,
diff --git a/lib/librte_ethdev/rte_mtr_driver.h b/lib/librte_ethdev/rte_mtr_driver.h
index 1ad8fb4c40..d7a8853b51 100644
--- a/lib/librte_ethdev/rte_mtr_driver.h
+++ b/lib/librte_ethdev/rte_mtr_driver.h
@@ -30,82 +30,80 @@ typedef int (*rte_mtr_capabilities_get_t)(struct rte_eth_dev *dev,
 	struct rte_mtr_error *error);
 /**< @internal MTR capabilities get */
 
-typedef int (*rte_mtr_meter_profile_add_t)(struct rte_eth_dev *dev,
-	uint32_t meter_profile_id,
+typedef struct rte_mtr_profile *(*rte_mtr_meter_profile_add_t)
+	(struct rte_eth_dev *dev,
 	struct rte_mtr_meter_profile *profile,
 	struct rte_mtr_error *error);
 /**< @internal MTR meter profile add */
 
 typedef int (*rte_mtr_meter_profile_delete_t)(struct rte_eth_dev *dev,
-	uint32_t meter_profile_id,
+	struct rte_mtr_profile *profile,
 	struct rte_mtr_error *error);
 /**< @internal MTR meter profile delete */
 
 typedef int (*rte_mtr_meter_policy_validate_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 validate */
 
-typedef int (*rte_mtr_meter_policy_add_t)(struct rte_eth_dev *dev,
-	uint32_t policy_id,
+typedef struct rte_mtr_policy *(*rte_mtr_meter_policy_add_t)
+	(struct rte_eth_dev *dev,
 	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_policy *policy,
 	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,
+typedef struct rte_mtr *(*rte_mtr_create_t)(struct rte_eth_dev *dev,
 	struct rte_mtr_params *params,
 	int shared,
 	struct rte_mtr_error *error);
 /**< @internal MTR object create */
 
 typedef int (*rte_mtr_destroy_t)(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	struct rte_mtr_error *error);
 /**< @internal MTR object destroy */
 
 typedef int (*rte_mtr_meter_enable_t)(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	struct rte_mtr_error *error);
 /**< @internal MTR object meter enable */
 
 typedef int (*rte_mtr_meter_disable_t)(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	struct rte_mtr_error *error);
 /**< @internal MTR object meter disable */
 
 typedef int (*rte_mtr_meter_profile_update_t)(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	uint32_t meter_profile_id,
+	struct rte_mtr *mtr,
+	struct rte_mtr_profile *profile,
 	struct rte_mtr_error *error);
 /**< @internal MTR object meter profile update */
 
 typedef int (*rte_mtr_meter_policy_update_t)(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	uint32_t meter_policy_id,
+	struct rte_mtr *mtr,
+	struct rte_mtr_policy *policy,
 	struct rte_mtr_error *error);
 /**< @internal MTR object meter policy update */
 
 typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	enum rte_color *dscp_table,
 	struct rte_mtr_error *error);
 /**< @internal MTR object meter DSCP table update */
 
 typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	uint64_t stats_mask,
 	struct rte_mtr_error *error);
 /**< @internal MTR object enabled stats update */
 
 typedef int (*rte_mtr_stats_read_t)(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
+	struct rte_mtr *mtr,
 	struct rte_mtr_stats *stats,
 	uint64_t *stats_mask,
 	int clear,
-- 
2.21.0


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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-03-18  8:58 [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API Li Zhang
  2021-03-18  8:58 ` [dpdk-dev] [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by the drivers Li Zhang
@ 2021-03-23 21:02 ` Dumitrescu, Cristian
  2021-03-25  6:56   ` Matan Azrad
  2021-03-29 10:38 ` Jerin Jacob
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 78+ messages in thread
From: Dumitrescu, Cristian @ 2021-03-23 21:02 UTC (permalink / raw)
  To: Li Zhang, dekelp, orika, viacheslavo, matan, shahafs, lironh,
	Singh, Jasvinder, Thomas Monjalon, Yigit, Ferruh,
	Andrew Rybchenko, Jerin Jacob, Hemant Agrawal, Ajit Khaparde
  Cc: dev, rasland, roniba

Hi Li and Matan,

Thank you for your proposal, some comments below.

I am also adding Jerin and Hemant to this thread, as they also participated in the definition of the rte_mtr API in 2017. Also Ajit expressed some interest in a previous email.

> -----Original Message-----
> From: Li Zhang <lizh@nvidia.com>
> Sent: Thursday, March 18, 2021 8:58 AM
> To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu, Cristian
> <cristian.dumitrescu@intel.com>
> Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> Subject: [PATCH 1/2] [RFC]: 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 - no action, yellow - no action, red - drop
> 
> Allow coloring the packet using a new rte_flow_action_color
> as could be done by the old policy API,
> 

The proposal essentially is to define the meter policy based on rte_flow actions rather than a reduced action set defined specifically just for meter object. This makes sense to me.

> The next API function were added:
> - rte_mtr_meter_policy_add
> - 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
> 
> Signed-off-by: Li Zhang <lizh@nvidia.com>
> ---
>  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 |  45 ++++++--
>  4 files changed, 210 insertions(+), 74 deletions(-)
> 
> diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
> index 669e677e91..5f38aa7fa4 100644
> --- a/lib/librte_ethdev/rte_flow.h
> +++ b/lib/librte_ethdev/rte_flow.h
> @@ -31,6 +31,7 @@
>  #include <rte_ecpri.h>
>  #include <rte_mbuf.h>
>  #include <rte_mbuf_dyn.h>
> +#include <rte_meter.h>
> 
>  #ifdef __cplusplus
>  extern "C" {
> @@ -2236,6 +2237,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_COlOR,

Typo here, it should be RTE_FLOW_ACTION_TYPE_COLOR.

>  };
> 
>  /**
> @@ -2828,6 +2836,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. */

I would avoid expanding the list of colors in the comment, as we might have to support more than 3 colors in the future. I would simply write: "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..fccec3760b 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 add */
> +int
> +rte_mtr_meter_policy_add(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_add)(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..07961f2777 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
>  	 */
> @@ -462,6 +441,94 @@ 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.

I suggest you do not redundantly specify the value of the default policy ID in the comment. Replace by "Default policy ID."

> + * Action per color as below:
> + * green - no action, yellow - no action, red - drop

This does not make sense to me as the default policy. The default policy should be "no change", i.e. green -> green (no change), yellow -> yellow (no change), red -> red (no change).

I suggest we avoid the "no action" statement, as it might be confusing.

> + * It can be used without creating it by the rte_mtr_meter_policy_add
> 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] policy_id
> + *   Policy identifier for the new meter policy.
> + * @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,
> +	uint32_t policy_id,
> +	const struct rte_flow_action *actions[RTE_COLORS],
> +	struct rte_mtr_error *error);
> +

This entire proposal is about defining a meter policy, yet there is no structure defining what exactly the meter policy is!

Please let's use the following structure for the policy parameters for the policy validate/add/delete API functions:

struct rte_mtr_meter_policy_params {
	struct rte_flow_action *actions[RTE_COLORS];
};

This would also give us the chance to document the policy concept in detail once and not repeat the same explanation over and over. For example, we need to explain clearly that actions[i] potentially represents a chain of rte_flow actions terminated by the END action, exactly as specified by the rte_flow API for the flow definition, and not just a single action. This is very important and yet not entirely clear from the above description.

This would also give us the chance to add more attributes to the meter policy later, if/when needed, with minimal impact to the API.

> +/**
> + * 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_add(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..1ad8fb4c40 100644
> --- a/lib/librte_ethdev/rte_mtr_driver.h
> +++ b/lib/librte_ethdev/rte_mtr_driver.h
> @@ -41,6 +41,23 @@ 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,
> +	uint32_t policy_id,
> +	const struct rte_flow_action *actions[RTE_COLORS],
> +	struct rte_mtr_error *error);
> +/**< @internal MTR meter policy validate */
> +
> +typedef int (*rte_mtr_meter_policy_add_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 +86,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 +140,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 add */
> +	rte_mtr_meter_policy_add_t meter_policy_add;
> +
> +	/** 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;
>  };
> 
>  /**
> --
> 2.21.0

Regards,
Cristian

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

* Re: [dpdk-dev] [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by the drivers
  2021-03-18  8:58 ` [dpdk-dev] [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by the drivers Li Zhang
@ 2021-03-23 21:33   ` Dumitrescu, Cristian
  2021-03-25  8:21     ` Matan Azrad
  0 siblings, 1 reply; 78+ messages in thread
From: Dumitrescu, Cristian @ 2021-03-23 21:33 UTC (permalink / raw)
  To: Li Zhang, dekelp, orika, viacheslavo, matan, shahafs, lironh,
	Singh, Jasvinder, Thomas Monjalon, Yigit, Ferruh,
	Andrew Rybchenko, Jerin Jacob, Hemant Agrawal, Ajit Khaparde,
	Richardson, Bruce, Doherty, Declan
  Cc: dev, rasland, roniba

Hi Li and Matan,

> -----Original Message-----
> From: Li Zhang <lizh@nvidia.com>
> Sent: Thursday, March 18, 2021 8:58 AM
> To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu, Cristian
> <cristian.dumitrescu@intel.com>
> Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> Subject: [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by the
> drivers
> 
> Currently, all the meter objects are managed by the user IDs:
> meter, profile and policy.
> Hence, each PMD should manage data-structure in order to
> map each API ID to the private PMD management structure.
> 
> From the application side, it has all the picture how meter
> is going to be assigned to flows and can easily use direct
> mapping even when the meter handler is provided by the PMDs.
> 
> Also, this is the approach of the rte_flow API handles:
> the flow handle and the shared action handle
> is provided by the PMDs.
> 
> Use drivers handlers in order to manage all the meter API objects.
> 

This seems to be take 2 of the discussion that we already had  in this thread: https://mails.dpdk.org/archives/dev/2021-March/200710.html, so apologies for mostly summarizing my previous feedback here.

I am against this proposal because:
1. We already discussed this topic of user-provided handles vs. driver-provided handles at length on this exact email list back in 2017, when we first introduced this API, and I don't see any real reason to revisit the decision we took then.
2. For me, it is more natural and it also helps the application to simplify its data structures if the user provides its own IDs rather than the user having to deal with the IDs provided by the driver.
3. It is much easier and portable to pass numeric and string-based IDs around (e.g. between processes) as opposed to pointer-based IDs, as pointers are only valid in one address space and not in others. There are several DPDK APIs that moved away from pointer handles to string IDs.
4. The mapping of user IDs to internal pointers within the driver is IMO not a big issue in terms of memory footprint or API call rate. Matan also confirmed this in the above thread when saying tis is not about either driver memory footprint or API call speed, as this mapping is easy to optimize.

And last but not least, this change obviously propagates in every API function, so it would result in big churn in API, all drivers and all apps (including testpmd, etc) implementing it (for IMO no real benefit). Yes, this API is experimental and therefore we can operate changes in it, but I'd rather see incremental and converging improvements rather than this.

If you guys insist with this proposal, I would like to get more opinions from other vendors and contributors from within our DPDK community.

> The following API will be changed:
> - rte_mtr_meter_profile_add
> - rte_mtr_meter_profile_delete
> - rte_mtr_meter_policy_validate
> - rte_mtr_meter_policy_add
> - rte_mtr_meter_policy_delete
> - rte_mtr_create
> - rte_mtr_destroy
> - rte_mtr_meter_disable
> - rte_mtr_meter_enable
> - rte_mtr_meter_profile_update
> - rte_mtr_meter_policy_update
> - rte_mtr_meter_dscp_table_update
> - rte_mtr_stats_update
> - rte_mtr_stats_read
> The next struct will be changed:
> - rte_flow_action_meter
> - rte_mtr_params
> 
> Signed-off-by: Li Zhang <lizh@nvidia.com>
> ---
>  lib/librte_ethdev/rte_flow.h       |   9 ++-
>  lib/librte_ethdev/rte_mtr.c        |  77 ++++++++++++----------
>  lib/librte_ethdev/rte_mtr.h        | 102 +++++++++++++++--------------
>  lib/librte_ethdev/rte_mtr_driver.h |  36 +++++-----
>  4 files changed, 122 insertions(+), 102 deletions(-)
> 
> diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
> index 5f38aa7fa4..6d2b86592d 100644
> --- a/lib/librte_ethdev/rte_flow.h
> +++ b/lib/librte_ethdev/rte_flow.h
> @@ -2480,6 +2480,13 @@ struct rte_flow_action_port_id {
>  	uint32_t id; /**< DPDK port ID. */
>  };
> 
> +/**
> + * Opaque type returned after successfully creating a meter.
> + *
> + * This handle can be used to manage the related meter (e.g. to destroy it).
> + */
> +struct rte_mtr;
> +
>  /**
>   * RTE_FLOW_ACTION_TYPE_METER
>   *
> @@ -2489,7 +2496,7 @@ struct rte_flow_action_port_id {
>   * next item with their color set by the MTR object.
>   */
>  struct rte_flow_action_meter {
> -	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create().
> */
> +	struct rte_mtr *mtr; /**< MTR object created with rte_mtr_create().
> */
>  };
> 
>  /**
> diff --git a/lib/librte_ethdev/rte_mtr.c b/lib/librte_ethdev/rte_mtr.c
> index fccec3760b..e407c6f956 100644
> --- a/lib/librte_ethdev/rte_mtr.c
> +++ b/lib/librte_ethdev/rte_mtr.c
> @@ -57,6 +57,19 @@ rte_mtr_ops_get(uint16_t port_id, struct
> rte_mtr_error *error)
>  	ops->func;					\
>  })
> 
> +#define RTE_MTR_FUNC_PTR(port_id, func)			\
> +({							\
> +	const struct rte_mtr_ops *ops =			\
> +		rte_mtr_ops_get(port_id, error);	\
> +	if (ops == NULL)				\
> +		return NULL;				\
> +							\
> +	if (ops->func == NULL)				\
> +		return NULL;				\
> +							\
> +	ops->func;					\
> +})
> +
>  /* MTR capabilities get */
>  int
>  rte_mtr_capabilities_get(uint16_t port_id,
> @@ -69,26 +82,25 @@ rte_mtr_capabilities_get(uint16_t port_id,
>  }
> 
>  /* MTR meter profile add */
> -int
> +struct rte_mtr_profile *
>  rte_mtr_meter_profile_add(uint16_t port_id,
> -	uint32_t meter_profile_id,
>  	struct rte_mtr_meter_profile *profile,
>  	struct rte_mtr_error *error)
>  {
>  	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> -	return RTE_MTR_FUNC(port_id, meter_profile_add)(dev,
> -		meter_profile_id, profile, error);
> +	return RTE_MTR_FUNC_PTR(port_id, meter_profile_add)(dev,
> +		profile, error);
>  }
> 
>  /** MTR meter profile delete */
>  int
>  rte_mtr_meter_profile_delete(uint16_t port_id,
> -	uint32_t meter_profile_id,
> +	struct rte_mtr_profile *profile,
>  	struct rte_mtr_error *error)
>  {
>  	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
>  	return RTE_MTR_FUNC(port_id, meter_profile_delete)(dev,
> -		meter_profile_id, error);
> +		profile, error);
>  }
> 
>  /* MTR meter policy validate */
> @@ -103,126 +115,123 @@ rte_mtr_meter_policy_validate(uint16_t port_id,
>  }
> 
>  /* MTR meter policy add */
> -int
> +struct rte_mtr_policy *
>  rte_mtr_meter_policy_add(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_add)(dev,
> -		policy_id, actions, error);
> +	return RTE_MTR_FUNC_PTR(port_id, meter_policy_add)(dev,
> +		actions, error);
>  }
> 
>  /** MTR meter policy delete */
>  int
>  rte_mtr_meter_policy_delete(uint16_t port_id,
> -	uint32_t policy_id,
> +	struct rte_mtr_policy *policy,
>  	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);
> +		policy, error);
>  }
> 
>  /** MTR object create */
> -int
> +struct rte_mtr *
>  rte_mtr_create(uint16_t port_id,
> -	uint32_t mtr_id,
>  	struct rte_mtr_params *params,
>  	int shared,
>  	struct rte_mtr_error *error)
>  {
>  	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> -	return RTE_MTR_FUNC(port_id, create)(dev,
> -		mtr_id, params, shared, error);
> +	return RTE_MTR_FUNC_PTR(port_id, create)(dev, params, shared,
> error);
>  }
> 
>  /** MTR object destroy */
>  int
>  rte_mtr_destroy(uint16_t port_id,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	struct rte_mtr_error *error)
>  {
>  	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
>  	return RTE_MTR_FUNC(port_id, destroy)(dev,
> -		mtr_id, error);
> +		mtr, error);
>  }
> 
>  /** MTR object meter enable */
>  int
>  rte_mtr_meter_enable(uint16_t port_id,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	struct rte_mtr_error *error)
>  {
>  	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
>  	return RTE_MTR_FUNC(port_id, meter_enable)(dev,
> -		mtr_id, error);
> +		mtr, error);
>  }
> 
>  /** MTR object meter disable */
>  int
>  rte_mtr_meter_disable(uint16_t port_id,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	struct rte_mtr_error *error)
>  {
>  	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
>  	return RTE_MTR_FUNC(port_id, meter_disable)(dev,
> -		mtr_id, error);
> +		mtr, error);
>  }
> 
>  /** MTR object meter profile update */
>  int
>  rte_mtr_meter_profile_update(uint16_t port_id,
> -	uint32_t mtr_id,
> -	uint32_t meter_profile_id,
> +	struct rte_mtr *mtr,
> +	struct rte_mtr_profile *profile,
>  	struct rte_mtr_error *error)
>  {
>  	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
>  	return RTE_MTR_FUNC(port_id, meter_profile_update)(dev,
> -		mtr_id, meter_profile_id, error);
> +		mtr, profile, error);
>  }
> 
>  /** MTR object meter policy update */
>  int
>  rte_mtr_meter_policy_update(uint16_t port_id,
> -	uint32_t mtr_id,
> -	uint32_t meter_policy_id,
> +	struct rte_mtr *mtr,
> +	struct rte_mtr_policy *policy,
>  	struct rte_mtr_error *error)
>  {
>  	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
>  	return RTE_MTR_FUNC(port_id, meter_policy_update)(dev,
> -		mtr_id, meter_policy_id, error);
> +		mtr, policy, error);
>  }
> 
>  /** MTR object meter DSCP table update */
>  int
>  rte_mtr_meter_dscp_table_update(uint16_t port_id,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	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, meter_dscp_table_update)(dev,
> -		mtr_id, dscp_table, error);
> +		mtr, dscp_table, error);
>  }
> 
>  /** MTR object enabled stats update */
>  int
>  rte_mtr_stats_update(uint16_t port_id,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	uint64_t stats_mask,
>  	struct rte_mtr_error *error)
>  {
>  	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
>  	return RTE_MTR_FUNC(port_id, stats_update)(dev,
> -		mtr_id, stats_mask, error);
> +		mtr, stats_mask, error);
>  }
> 
>  /** MTR object stats read */
>  int
>  rte_mtr_stats_read(uint16_t port_id,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	struct rte_mtr_stats *stats,
>  	uint64_t *stats_mask,
>  	int clear,
> @@ -230,5 +239,5 @@ rte_mtr_stats_read(uint16_t port_id,
>  {
>  	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
>  	return RTE_MTR_FUNC(port_id, stats_read)(dev,
> -		mtr_id, stats, stats_mask, clear, error);
> +		mtr, stats, stats_mask, clear, error);
>  }
> diff --git a/lib/librte_ethdev/rte_mtr.h b/lib/librte_ethdev/rte_mtr.h
> index 07961f2777..2b20e55079 100644
> --- a/lib/librte_ethdev/rte_mtr.h
> +++ b/lib/librte_ethdev/rte_mtr.h
> @@ -181,8 +181,8 @@ struct rte_mtr_meter_profile {
>   * @see enum rte_mtr_stats_type
>   */
>  struct rte_mtr_params {
> -	/** Meter profile ID. */
> -	uint32_t meter_profile_id;
> +	/** Meter profile. */
> +	struct rte_mtr_profile *profile;
> 
>  	/** Meter input color in case of MTR object chaining. When non-
> zero: if
>  	 * a previous MTR object is enabled in the same flow, then the color
> @@ -221,8 +221,8 @@ struct rte_mtr_params {
>  	 */
>  	uint64_t stats_mask;
> 
> -	/** Meter policy ID. */
> -	uint32_t meter_policy_id;
> +	/** Meter policy. */
> +	struct rte_mtr_policy *policy;
>  };
> 
>  /**
> @@ -395,28 +395,32 @@ rte_mtr_capabilities_get(uint16_t port_id,
>  	struct rte_mtr_capabilities *cap,
>  	struct rte_mtr_error *error);
> 
> +/**
> + * Opaque type returned after successfully creating a profile.
> + *
> + * This handle can be used to manage the related profile (e.g. to destroy it).
> + */
> +struct rte_mtr_profile;
> +
>  /**
>   * Meter profile add
>   *
> - * Create a new meter profile with ID set to *meter_profile_id*. The new
> profile
> + * Create a new meter profile. The new profile
>   * is used to create one or several MTR objects.
>   *
>   * @param[in] port_id
>   *   The port identifier of the Ethernet device.
> - * @param[in] meter_profile_id
> - *   ID for the new meter profile. Needs to be unused by any of the existing
> - *   meter profiles added for the current port.
>   * @param[in] profile
>   *   Meter profile parameters. Needs to be pre-allocated and valid.
>   * @param[out] error
>   *   Error details. Filled in only on error, when not NULL.
>   * @return
> - *   0 on success, non-zero error code otherwise.
> + *   A valid handle in case of success, NULL otherwise and rte_errno is set
> + *   to the positive version of one of the error codes.
>   */
>  __rte_experimental
> -int
> +struct rte_mtr_profile *
>  rte_mtr_meter_profile_add(uint16_t port_id,
> -	uint32_t meter_profile_id,
>  	struct rte_mtr_meter_profile *profile,
>  	struct rte_mtr_error *error);
> 
> @@ -428,8 +432,8 @@ rte_mtr_meter_profile_add(uint16_t port_id,
>   *
>   * @param[in] port_id
>   *   The port identifier of the Ethernet device.
> - * @param[in] meter_profile_id
> - *   Meter profile ID. Needs to be the valid.
> + * @param[in] profile
> + *   Meter profile pointer. Needs to be the valid.
>   * @param[out] error
>   *   Error details. Filled in only on error, when not NULL.
>   * @return
> @@ -438,16 +442,15 @@ rte_mtr_meter_profile_add(uint16_t port_id,
>  __rte_experimental
>  int
>  rte_mtr_meter_profile_delete(uint16_t port_id,
> -	uint32_t meter_profile_id,
> +	struct rte_mtr_profile *profile,
>  	struct rte_mtr_error *error);
> 
>  /**
> - * Policy id 0 is default policy.
> - * Action per color as below:
> - * green - no action, yellow - no action, red - drop
> - * It can be used without creating it by the rte_mtr_meter_policy_add
> function.
> + * Opaque type returned after successfully creating a policy.
> + *
> + * This handle can be used to manage the related policy (e.g. to destroy it).
>   */
> -#define RTE_MTR_DEFAULT_POLICY_ID 0
> +struct rte_mtr_policy;
> 
>  /**
>   * Check whether a meter policy can be created on a given port.
> @@ -478,7 +481,6 @@ rte_mtr_meter_profile_delete(uint16_t port_id,
>  __rte_experimental
>  int
>  rte_mtr_meter_policy_validate(uint16_t port_id,
> -	uint32_t policy_id,
>  	const struct rte_flow_action *actions[RTE_COLORS],
>  	struct rte_mtr_error *error);
> 
> @@ -490,8 +492,6 @@ rte_mtr_meter_policy_validate(uint16_t port_id,
>   *
>   * @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.
> @@ -499,12 +499,12 @@ rte_mtr_meter_policy_validate(uint16_t port_id,
>   * @param[out] error
>   *   Error details. Filled in only on error, when not NULL.
>   * @return
> - *   0 on success, non-zero error code otherwise.
> + *   A valid handle in case of success, NULL otherwise and rte_errno is set
> + *   to the positive version of one of the error codes.
>   */
>  __rte_experimental
> -int
> +struct rte_mtr_policy *
>  rte_mtr_meter_policy_add(uint16_t port_id,
> -	uint32_t policy_id,
>  	const struct rte_flow_action *actions[RTE_COLORS],
>  	struct rte_mtr_error *error);
> 
> @@ -516,8 +516,8 @@ rte_mtr_meter_policy_add(uint16_t port_id,
>   *
>   * @param[in] port_id
>   *   The port identifier of the Ethernet device.
> - * @param[in] policy_id
> - *   Policy identifier.
> + * @param[in] policy
> + *   Policy pointer. Needs to be valid.
>   * @param[out] error
>   *   Error details. Filled in only on error, when not NULL.
>   * @return
> @@ -526,20 +526,28 @@ rte_mtr_meter_policy_add(uint16_t port_id,
>  __rte_experimental
>  int
>  rte_mtr_meter_policy_delete(uint16_t port_id,
> -	uint32_t policy_id,
> +	struct rte_mtr_policy *policy,
>  	struct rte_mtr_error *error);
> 
> +/**
> + * Opaque type returned after successfully creating a meter.
> + *
> + * This handle can be used to manage the related meter (e.g. to destroy it).
> + */
> +struct rte_mtr;
> +
>  /**
>   * MTR object create
>   *
>   * Create a new MTR object for the current port. This object is run as part of
>   * associated flow action for traffic metering and policing.
> + * Policy pointer NULL is default policy.
> + * Action per color as below:
> + * green - no action, yellow - no action, red - drop
> + * It can be used without creating it by the rte_mtr_meter_policy_add
> function.
>   *
>   * @param[in] port_id
>   *   The port identifier of the Ethernet device.
> - * @param[in] mtr_id
> - *   MTR object ID. Needs to be unused by any of the existing MTR objects.
> - *   created for the current port.
>   * @param[in] params
>   *   MTR object params. Needs to be pre-allocated and valid.
>   * @param[in] shared
> @@ -548,14 +556,14 @@ rte_mtr_meter_policy_delete(uint16_t port_id,
>   * @param[out] error
>   *   Error details. Filled in only on error, when not NULL.
>   * @return
> - *   0 on success, non-zero error code otherwise.
> + *   A valid handle in case of success, NULL otherwise and rte_errno is set
> + *   to the positive version of one of the error codes.
>   *
>   * @see enum rte_flow_action_type::RTE_FLOW_ACTION_TYPE_METER
>   */
>  __rte_experimental
> -int
> +struct rte_mtr *
>  rte_mtr_create(uint16_t port_id,
> -	uint32_t mtr_id,
>  	struct rte_mtr_params *params,
>  	int shared,
>  	struct rte_mtr_error *error);
> @@ -568,8 +576,8 @@ rte_mtr_create(uint16_t port_id,
>   *
>   * @param[in] port_id
>   *   The port identifier of the Ethernet device.
> - * @param[in] mtr_id
> - *   MTR object ID. Needs to be valid.
> + * @param[in] mtr
> + *   MTR pointer. Needs to be valid.
>   *   created for the current port.
>   * @param[out] error
>   *   Error details. Filled in only on error, when not NULL.
> @@ -579,7 +587,7 @@ rte_mtr_create(uint16_t port_id,
>  __rte_experimental
>  int
>  rte_mtr_destroy(uint16_t port_id,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	struct rte_mtr_error *error);
> 
>  /**
> @@ -607,7 +615,7 @@ rte_mtr_destroy(uint16_t port_id,
>  __rte_experimental
>  int
>  rte_mtr_meter_disable(uint16_t port_id,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	struct rte_mtr_error *error);
> 
>  /**
> @@ -629,7 +637,7 @@ rte_mtr_meter_disable(uint16_t port_id,
>  __rte_experimental
>  int
>  rte_mtr_meter_enable(uint16_t port_id,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	struct rte_mtr_error *error);
> 
>  /**
> @@ -649,8 +657,8 @@ rte_mtr_meter_enable(uint16_t port_id,
>  __rte_experimental
>  int
>  rte_mtr_meter_profile_update(uint16_t port_id,
> -	uint32_t mtr_id,
> -	uint32_t meter_profile_id,
> +	struct rte_mtr *mtr,
> +	struct rte_mtr_profile *profile,
>  	struct rte_mtr_error *error);
> 
>  /**
> @@ -660,8 +668,6 @@ rte_mtr_meter_profile_update(uint16_t port_id,
>   *   The port identifier of the Ethernet device.
>   * @param[in] mtr_id
>   *   MTR object ID. Needs to be valid.
> - * @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
> @@ -670,8 +676,8 @@ rte_mtr_meter_profile_update(uint16_t port_id,
>  __rte_experimental
>  int
>  rte_mtr_meter_policy_update(uint16_t port_id,
> -	uint32_t mtr_id,
> -	uint32_t meter_policy_id,
> +	struct rte_mtr *mtr,
> +	struct rte_mtr_policy *policy,
>  	struct rte_mtr_error *error);
> 
>  /**
> @@ -695,7 +701,7 @@ rte_mtr_meter_policy_update(uint16_t port_id,
>  __rte_experimental
>  int
>  rte_mtr_meter_dscp_table_update(uint16_t port_id,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	enum rte_color *dscp_table,
>  	struct rte_mtr_error *error);
> 
> @@ -720,7 +726,7 @@ rte_mtr_meter_dscp_table_update(uint16_t port_id,
>  __rte_experimental
>  int
>  rte_mtr_stats_update(uint16_t port_id,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	uint64_t stats_mask,
>  	struct rte_mtr_error *error);
> 
> @@ -752,7 +758,7 @@ rte_mtr_stats_update(uint16_t port_id,
>  __rte_experimental
>  int
>  rte_mtr_stats_read(uint16_t port_id,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	struct rte_mtr_stats *stats,
>  	uint64_t *stats_mask,
>  	int clear,
> diff --git a/lib/librte_ethdev/rte_mtr_driver.h
> b/lib/librte_ethdev/rte_mtr_driver.h
> index 1ad8fb4c40..d7a8853b51 100644
> --- a/lib/librte_ethdev/rte_mtr_driver.h
> +++ b/lib/librte_ethdev/rte_mtr_driver.h
> @@ -30,82 +30,80 @@ typedef int (*rte_mtr_capabilities_get_t)(struct
> rte_eth_dev *dev,
>  	struct rte_mtr_error *error);
>  /**< @internal MTR capabilities get */
> 
> -typedef int (*rte_mtr_meter_profile_add_t)(struct rte_eth_dev *dev,
> -	uint32_t meter_profile_id,
> +typedef struct rte_mtr_profile *(*rte_mtr_meter_profile_add_t)
> +	(struct rte_eth_dev *dev,
>  	struct rte_mtr_meter_profile *profile,
>  	struct rte_mtr_error *error);
>  /**< @internal MTR meter profile add */
> 
>  typedef int (*rte_mtr_meter_profile_delete_t)(struct rte_eth_dev *dev,
> -	uint32_t meter_profile_id,
> +	struct rte_mtr_profile *profile,
>  	struct rte_mtr_error *error);
>  /**< @internal MTR meter profile delete */
> 
>  typedef int (*rte_mtr_meter_policy_validate_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 validate */
> 
> -typedef int (*rte_mtr_meter_policy_add_t)(struct rte_eth_dev *dev,
> -	uint32_t policy_id,
> +typedef struct rte_mtr_policy *(*rte_mtr_meter_policy_add_t)
> +	(struct rte_eth_dev *dev,
>  	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_policy *policy,
>  	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,
> +typedef struct rte_mtr *(*rte_mtr_create_t)(struct rte_eth_dev *dev,
>  	struct rte_mtr_params *params,
>  	int shared,
>  	struct rte_mtr_error *error);
>  /**< @internal MTR object create */
> 
>  typedef int (*rte_mtr_destroy_t)(struct rte_eth_dev *dev,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	struct rte_mtr_error *error);
>  /**< @internal MTR object destroy */
> 
>  typedef int (*rte_mtr_meter_enable_t)(struct rte_eth_dev *dev,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	struct rte_mtr_error *error);
>  /**< @internal MTR object meter enable */
> 
>  typedef int (*rte_mtr_meter_disable_t)(struct rte_eth_dev *dev,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	struct rte_mtr_error *error);
>  /**< @internal MTR object meter disable */
> 
>  typedef int (*rte_mtr_meter_profile_update_t)(struct rte_eth_dev *dev,
> -	uint32_t mtr_id,
> -	uint32_t meter_profile_id,
> +	struct rte_mtr *mtr,
> +	struct rte_mtr_profile *profile,
>  	struct rte_mtr_error *error);
>  /**< @internal MTR object meter profile update */
> 
>  typedef int (*rte_mtr_meter_policy_update_t)(struct rte_eth_dev *dev,
> -	uint32_t mtr_id,
> -	uint32_t meter_policy_id,
> +	struct rte_mtr *mtr,
> +	struct rte_mtr_policy *policy,
>  	struct rte_mtr_error *error);
>  /**< @internal MTR object meter policy update */
> 
>  typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev
> *dev,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	enum rte_color *dscp_table,
>  	struct rte_mtr_error *error);
>  /**< @internal MTR object meter DSCP table update */
> 
>  typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	uint64_t stats_mask,
>  	struct rte_mtr_error *error);
>  /**< @internal MTR object enabled stats update */
> 
>  typedef int (*rte_mtr_stats_read_t)(struct rte_eth_dev *dev,
> -	uint32_t mtr_id,
> +	struct rte_mtr *mtr,
>  	struct rte_mtr_stats *stats,
>  	uint64_t *stats_mask,
>  	int clear,
> --
> 2.21.0

Regards,
Cristian

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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-03-23 21:02 ` [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API Dumitrescu, Cristian
@ 2021-03-25  6:56   ` Matan Azrad
  2021-03-29  9:23     ` Ori Kam
  2021-03-29 16:08     ` Dumitrescu, Cristian
  0 siblings, 2 replies; 78+ messages in thread
From: Matan Azrad @ 2021-03-25  6:56 UTC (permalink / raw)
  To: Dumitrescu, Cristian, Li Zhang, Dekel Peled, Ori Kam,
	Slava Ovsiienko, Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Jerin Jacob, Hemant Agrawal, Ajit Khaparde
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai

Hi Cristian

Thank you for your important review!
I agree with all your comments except one, please see inline.

From: Dumitrescu, Cristian
> Hi Li and Matan,
> 
> Thank you for your proposal, some comments below.
> 
> I am also adding Jerin and Hemant to this thread, as they also participated in
> the definition of the rte_mtr API in 2017. Also Ajit expressed some interest in a
> previous email.
> 
> > -----Original Message-----
> > From: Li Zhang <lizh@nvidia.com>
> > Sent: Thursday, March 18, 2021 8:58 AM
> > To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu, Cristian
> > <cristian.dumitrescu@intel.com>
> > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > Subject: [PATCH 1/2] [RFC]: 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 - no action, yellow - no action, red - drop
> >
> > Allow coloring the packet using a new rte_flow_action_color as could
> > be done by the old policy API,
> >
> 
> The proposal essentially is to define the meter policy based on rte_flow actions
> rather than a reduced action set defined specifically just for meter object. This
> makes sense to me.
> 
> > The next API function were added:
> > - rte_mtr_meter_policy_add
> > - 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
> >
> > Signed-off-by: Li Zhang <lizh@nvidia.com>
> > ---
> >  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 |  45 ++++++--
> >  4 files changed, 210 insertions(+), 74 deletions(-)
> >
> > diff --git a/lib/librte_ethdev/rte_flow.h
> > b/lib/librte_ethdev/rte_flow.h index 669e677e91..5f38aa7fa4 100644
> > --- a/lib/librte_ethdev/rte_flow.h
> > +++ b/lib/librte_ethdev/rte_flow.h
> > @@ -31,6 +31,7 @@
> >  #include <rte_ecpri.h>
> >  #include <rte_mbuf.h>
> >  #include <rte_mbuf_dyn.h>
> > +#include <rte_meter.h>
> >
> >  #ifdef __cplusplus
> >  extern "C" {
> > @@ -2236,6 +2237,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_COlOR,
> 
> Typo here, it should be RTE_FLOW_ACTION_TYPE_COLOR.
> 
> >  };
> >
> >  /**
> > @@ -2828,6 +2836,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. */
> 
> I would avoid expanding the list of colors in the comment, as we might have to
> support more than 3 colors in the future. I would simply write: "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..fccec3760b 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 add */
> > +int
> > +rte_mtr_meter_policy_add(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_add)(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..07961f2777 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
> >        */
> > @@ -462,6 +441,94 @@ 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.
> 
> I suggest you do not redundantly specify the value of the default policy ID in the
> comment. Replace by "Default policy ID."
> 
> > + * Action per color as below:
> > + * green - no action, yellow - no action, red - drop
> 
> This does not make sense to me as the default policy. The default policy should
> be "no change", i.e. green -> green (no change), yellow -> yellow (no change),
> red -> red (no change).

Can you explain why it doesn't make sense to you?

Meter with "no change" for all colors has no effect on the packets so it is redundant action which just costs performance and resources - probably never be used.

The most common usage for meter is to drop all the packets come above the defined rate limit - so it makes sense to take this behavior as default.


> I suggest we avoid the "no action" statement, as it might be confusing.

Maybe "do nothing" is better?


> > + * It can be used without creating it by the rte_mtr_meter_policy_add
> > 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] policy_id
> > + *   Policy identifier for the new meter policy.
> > + * @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,
> > +     uint32_t policy_id,
> > +     const struct rte_flow_action *actions[RTE_COLORS],
> > +     struct rte_mtr_error *error);
> > +
> 
> This entire proposal is about defining a meter policy, yet there is no structure
> defining what exactly the meter policy is!
> 
> Please let's use the following structure for the policy parameters for the policy
> validate/add/delete API functions:
> 
> struct rte_mtr_meter_policy_params {
>         struct rte_flow_action *actions[RTE_COLORS]; };
> 
> This would also give us the chance to document the policy concept in detail
> once and not repeat the same explanation over and over. For example, we
> need to explain clearly that actions[i] potentially represents a chain of rte_flow
> actions terminated by the END action, exactly as specified by the rte_flow API
> for the flow definition, and not just a single action. This is very important and
> yet not entirely clear from the above description.
> 
> This would also give us the chance to add more attributes to the meter policy
> later, if/when needed, with minimal impact to the API.
> 
> > +/**
> > + * 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_add(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..1ad8fb4c40 100644
> > --- a/lib/librte_ethdev/rte_mtr_driver.h
> > +++ b/lib/librte_ethdev/rte_mtr_driver.h
> > @@ -41,6 +41,23 @@ 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,
> > +     uint32_t policy_id,
> > +     const struct rte_flow_action *actions[RTE_COLORS],
> > +     struct rte_mtr_error *error);
> > +/**< @internal MTR meter policy validate */
> > +
> > +typedef int (*rte_mtr_meter_policy_add_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 +86,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 +140,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 add */
> > +     rte_mtr_meter_policy_add_t meter_policy_add;
> > +
> > +     /** 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;
> >  };
> >
> >  /**
> > --
> > 2.21.0
> 
> Regards,
> Cristian
Thanks!

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

* Re: [dpdk-dev] [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by the drivers
  2021-03-23 21:33   ` Dumitrescu, Cristian
@ 2021-03-25  8:21     ` Matan Azrad
  2021-03-25 23:16       ` Ajit Khaparde
  2021-03-27 13:15       ` Jerin Jacob
  0 siblings, 2 replies; 78+ messages in thread
From: Matan Azrad @ 2021-03-25  8:21 UTC (permalink / raw)
  To: Dumitrescu, Cristian, Li Zhang, Dekel Peled, Ori Kam,
	Slava Ovsiienko, Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Jerin Jacob, Hemant Agrawal, Ajit Khaparde, Richardson, Bruce,
	Doherty, Declan
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai

Hi Cristian

From: Dumitrescu, Cristian
> Hi Li and Matan,
> 
> > -----Original Message-----
> > From: Li Zhang <lizh@nvidia.com>
> > Sent: Thursday, March 18, 2021 8:58 AM
> > To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu, Cristian
> > <cristian.dumitrescu@intel.com>
> > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > Subject: [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by
> > the drivers
> >
> > Currently, all the meter objects are managed by the user IDs:
> > meter, profile and policy.
> > Hence, each PMD should manage data-structure in order to map each API
> > ID to the private PMD management structure.
> >
> > From the application side, it has all the picture how meter is going
> > to be assigned to flows and can easily use direct mapping even when
> > the meter handler is provided by the PMDs.
> >
> > Also, this is the approach of the rte_flow API handles:
> > the flow handle and the shared action handle is provided by the PMDs.
> >
> > Use drivers handlers in order to manage all the meter API objects.
> >
> 
> This seems to be take 2 of the discussion that we already had  in this thread:
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmails.dp
> dk.org%2Farchives%2Fdev%2F2021-
> March%2F200710.html&amp;data=04%7C01%7Cmatan%40nvidia.com%7Cab0
> e3cc77b9e4101344e08d8ee434bbe%7C43083d15727340c1b7db39efd9ccc17a%
> 7C0%7C0%7C637521320105450617%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiM
> C4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&
> amp;sdata=94bFRICfGEzk5s53MRUvFMQe5ZlhP2Tmnu82hwUytc4%3D&amp;re
> served=0, so apologies for mostly summarizing my previous feedback here.
> 
> I am against this proposal because:
> 1. We already discussed this topic of user-provided handles vs. driver-provided
> handles at length on this exact email list back in 2017, when we first introduced
> this API, and I don't see any real reason to revisit the decision we took then.

Why not?
There is more experiences\usages now.
New drivers added the support and also now scalability is growing and growing....


> 2. For me, it is more natural and it also helps the application to simplify its data
> structures if the user provides its own IDs rather than the user having to deal
> with the IDs provided by the driver.

Generally I don't think other flow DPDK APIs align with your feelings here, see rte_flow object and rte_flow_shared_action.

Specifically for meter:
	- here, meter is HW\driver offload where performance\rate either for meter creation\deletion or for the actual data-path is very important especially when we talk on very big numbers, so "natural" has less importance here.
	  We need to think on the global solution for application ->API->driver. in meter feature, the user has the ability to manage the IDs better than the PMDs for the most of the use-cases:
			1. meter per flow: just save the driver handle in the app flow context.
			2. meter per VM\USER flows\rte_flow group\any other context grouped multiple flows: just save the driver handle in the app context.
	If PMD need to map the IDs, it is more complex for sure, requires more memory and more lookup time.

	- I'm not sure it is natural for all the use-cases, sometimes generating unique ID may complex the app.


> 3. It is much easier and portable to pass numeric and string-based IDs around
> (e.g. between processes) as opposed to pointer-based IDs, as pointers are only
> valid in one address space and not in others. There are several DPDK APIs that
> moved away from pointer handles to string IDs.

Yes, I agree here generally.
But again, since meter is used only by rte_flow, it is better to align the same handle mechanism.

> 4. The mapping of user IDs to internal pointers within the driver is IMO not a
> big issue in terms of memory footprint or API call rate. Matan also confirmed
> this in the above thread when saying tis is not about either driver memory
> footprint or API call speed, as this mapping is easy to optimize.

Yes, it is not very big deal, but still costs more than the new suggestion, especially in big scale.

> And last but not least, this change obviously propagates in every API function,
> so it would result in big churn in API, all drivers and all apps (including testpmd,
> etc) implementing it (for IMO no real benefit). Yes, this API is experimental and
> therefore we can operate changes in it, but I'd rather see incremental and
> converging improvements rather than this.

Yes, it changes all API, but very small part in each, will be very easy to align all the current dpdk components to use this concept. 

> If you guys insist with this proposal, I would like to get more opinions from
> other vendors and contributors from within our DPDK community.


Yes, more opinions are very welcomed.

Thanks

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

* Re: [dpdk-dev] [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by the drivers
  2021-03-25  8:21     ` Matan Azrad
@ 2021-03-25 23:16       ` Ajit Khaparde
  2021-03-29 19:56         ` Matan Azrad
  2021-03-27 13:15       ` Jerin Jacob
  1 sibling, 1 reply; 78+ messages in thread
From: Ajit Khaparde @ 2021-03-25 23:16 UTC (permalink / raw)
  To: Matan Azrad
  Cc: Dumitrescu, Cristian, Li Zhang, Dekel Peled, Ori Kam,
	Slava Ovsiienko, Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Jerin Jacob, Hemant Agrawal, Richardson, Bruce, Doherty, Declan,
	dev, Raslan Darawsheh, Roni Bar Yanai

[-- Attachment #1: Type: text/plain, Size: 5863 bytes --]

On Thu, Mar 25, 2021 at 1:21 AM Matan Azrad <matan@nvidia.com> wrote:
>
> Hi Cristian
>
> From: Dumitrescu, Cristian
> > Hi Li and Matan,
> >
> > > -----Original Message-----
> > > From: Li Zhang <lizh@nvidia.com>
> > > Sent: Thursday, March 18, 2021 8:58 AM
> > > To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> > > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> > > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> > > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu, Cristian
> > > <cristian.dumitrescu@intel.com>
> > > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > > Subject: [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by
> > > the drivers
> > >
> > > Currently, all the meter objects are managed by the user IDs:
> > > meter, profile and policy.
> > > Hence, each PMD should manage data-structure in order to map each API
> > > ID to the private PMD management structure.
> > >
> > > From the application side, it has all the picture how meter is going
> > > to be assigned to flows and can easily use direct mapping even when
> > > the meter handler is provided by the PMDs.
> > >
> > > Also, this is the approach of the rte_flow API handles:
> > > the flow handle and the shared action handle is provided by the PMDs.
> > >
> > > Use drivers handlers in order to manage all the meter API objects.
> > >
> >
> > This seems to be take 2 of the discussion that we already had  in this thread:
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmails.dp
> > dk.org%2Farchives%2Fdev%2F2021-
> > March%2F200710.html&amp;data=04%7C01%7Cmatan%40nvidia.com%7Cab0
> > e3cc77b9e4101344e08d8ee434bbe%7C43083d15727340c1b7db39efd9ccc17a%
> > 7C0%7C0%7C637521320105450617%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiM
> > C4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&
> > amp;sdata=94bFRICfGEzk5s53MRUvFMQe5ZlhP2Tmnu82hwUytc4%3D&amp;re
> > served=0, so apologies for mostly summarizing my previous feedback here.
> >
> > I am against this proposal because:
> > 1. We already discussed this topic of user-provided handles vs. driver-provided
> > handles at length on this exact email list back in 2017, when we first introduced
> > this API, and I don't see any real reason to revisit the decision we took then.
>
> Why not?
> There is more experiences\usages now.
> New drivers added the support and also now scalability is growing and growing....
>
>
> > 2. For me, it is more natural and it also helps the application to simplify its data
> > structures if the user provides its own IDs rather than the user having to deal
> > with the IDs provided by the driver.
>
> Generally I don't think other flow DPDK APIs align with your feelings here, see rte_flow object and rte_flow_shared_action.
>
> Specifically for meter:
>         - here, meter is HW\driver offload where performance\rate either for meter creation\deletion or for the actual data-path is very important especially when we talk on very big numbers, so "natural" has less importance here.
>           We need to think on the global solution for application ->API->driver. in meter feature, the user has the ability to manage the IDs better than the PMDs for the most of the use-cases:
>                         1. meter per flow: just save the driver handle in the app flow context.
>                         2. meter per VM\USER flows\rte_flow group\any other context grouped multiple flows: just save the driver handle in the app context.
>         If PMD need to map the IDs, it is more complex for sure, requires more memory and more lookup time.
>
>         - I'm not sure it is natural for all the use-cases, sometimes generating unique ID may complex the app.
>
>
> > 3. It is much easier and portable to pass numeric and string-based IDs around
> > (e.g. between processes) as opposed to pointer-based IDs, as pointers are only
> > valid in one address space and not in others. There are several DPDK APIs that
> > moved away from pointer handles to string IDs.
Pardon my ignorance..
But which DPDK APIs moved to string IDs from pointer handles?

>
> Yes, I agree here generally.
> But again, since meter is used only by rte_flow, it is better to align the same handle mechanism.
I don't want to say - do this because rte_flow uses a pointer.
I don't have a strong opinion for one over the other. In the end the
logic can be adapted one way or the other.
But having implemented rte_flow support in the PMD, I think it is a
good idea to avoid the duplication of meter_id to pointer based handle
conversion and bookkeeping logic in the application and the PMD.

>
> > 4. The mapping of user IDs to internal pointers within the driver is IMO not a
> > big issue in terms of memory footprint or API call rate. Matan also confirmed
> > this in the above thread when saying tis is not about either driver memory
> > footprint or API call speed, as this mapping is easy to optimize.
>
> Yes, it is not very big deal, but still costs more than the new suggestion, especially in big scale.
>
> > And last but not least, this change obviously propagates in every API function,
> > so it would result in big churn in API, all drivers and all apps (including testpmd,
> > etc) implementing it (for IMO no real benefit). Yes, this API is experimental and
> > therefore we can operate changes in it, but I'd rather see incremental and
> > converging improvements rather than this.
>
> Yes, it changes all API, but very small part in each, will be very easy to align all the current dpdk components to use this concept.
>
> > If you guys insist with this proposal, I would like to get more opinions from
> > other vendors and contributors from within our DPDK community.
>
>
> Yes, more opinions are very welcomed.
>
> Thanks

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

* Re: [dpdk-dev] [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by the drivers
  2021-03-25  8:21     ` Matan Azrad
  2021-03-25 23:16       ` Ajit Khaparde
@ 2021-03-27 13:15       ` Jerin Jacob
  2021-03-29 20:10         ` Matan Azrad
  1 sibling, 1 reply; 78+ messages in thread
From: Jerin Jacob @ 2021-03-27 13:15 UTC (permalink / raw)
  To: Matan Azrad
  Cc: Dumitrescu, Cristian, Li Zhang, Dekel Peled, Ori Kam,
	Slava Ovsiienko, Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Hemant Agrawal, Ajit Khaparde, Richardson, Bruce, Doherty,
	Declan, dev, Raslan Darawsheh, Roni Bar Yanai

On Thu, Mar 25, 2021 at 1:51 PM Matan Azrad <matan@nvidia.com> wrote:
>
> Hi Cristian
>
> From: Dumitrescu, Cristian
> > Hi Li and Matan,
> >
> > > -----Original Message-----
> > > From: Li Zhang <lizh@nvidia.com>
> > > Sent: Thursday, March 18, 2021 8:58 AM
> > > To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> > > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> > > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> > > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu, Cristian
> > > <cristian.dumitrescu@intel.com>
> > > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > > Subject: [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by
> > > the drivers
> > >

>
> Yes, it changes all API, but very small part in each, will be very easy to align all the current dpdk components to use this concept.
>
> > If you guys insist with this proposal, I would like to get more opinions from
> > other vendors and contributors from within our DPDK community.
>
>
> Yes, more opinions are very welcomed.

This point was discussed to the core in the initial meter RFC.

IMO, IDs helps in managing meter objects more clean way with lookup
cost. especially, If a non DPDK application, managing the meter ID
via some sort of IPC.

Considering existing APIs and drivers are implemented with ID scheme,
I think, it would be better to give some performance data for
changing the scheme.

I was under impression that, Typical number of MAX meter HW objects
could be around 16k something and the number of meter objects
created and destroyed per second will be very low. (In the order to
16k ops per second).

Could you share the practical number of meter HW objects in MLX SoCs
and the number of operations are you are envisioning?

>
> Thanks

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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-03-25  6:56   ` Matan Azrad
@ 2021-03-29  9:23     ` Ori Kam
  2021-03-29 16:24       ` Dumitrescu, Cristian
  2021-03-29 16:08     ` Dumitrescu, Cristian
  1 sibling, 1 reply; 78+ messages in thread
From: Ori Kam @ 2021-03-29  9:23 UTC (permalink / raw)
  To: Matan Azrad, Dumitrescu, Cristian, Li Zhang, Dekel Peled,
	Slava Ovsiienko, Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Jerin Jacob, Hemant Agrawal, Ajit Khaparde
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai

Hi All,

> -----Original Message-----
> From: Matan Azrad <matan@nvidia.com>
> Subject: RE: [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
> 
> Hi Cristian
> 
> Thank you for your important review!
> I agree with all your comments except one, please see inline.
> 
> From: Dumitrescu, Cristian
> > Hi Li and Matan,
> >
> > Thank you for your proposal, some comments below.
> >
> > I am also adding Jerin and Hemant to this thread, as they also participated in
> > the definition of the rte_mtr API in 2017. Also Ajit expressed some interest in
> a
> > previous email.
> >
> > > -----Original Message-----
> > > From: Li Zhang <lizh@nvidia.com>
> > > Sent: Thursday, March 18, 2021 8:58 AM
> > > To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> > > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> > > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> > > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu, Cristian
> > > <cristian.dumitrescu@intel.com>
> > > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > > Subject: [PATCH 1/2] [RFC]: 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 - no action, yellow - no action, red - drop
> > >
> > > Allow coloring the packet using a new rte_flow_action_color as could
> > > be done by the old policy API,
> > >
> >
> > The proposal essentially is to define the meter policy based on rte_flow
> actions
> > rather than a reduced action set defined specifically just for meter object.
> This
> > makes sense to me.
> >
> > > The next API function were added:
> > > - rte_mtr_meter_policy_add
> > > - 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
> > >
> > > Signed-off-by: Li Zhang <lizh@nvidia.com>
> > > ---
> > >  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 |  45 ++++++--
> > >  4 files changed, 210 insertions(+), 74 deletions(-)
> > >
> > > diff --git a/lib/librte_ethdev/rte_flow.h
> > > b/lib/librte_ethdev/rte_flow.h index 669e677e91..5f38aa7fa4 100644
> > > --- a/lib/librte_ethdev/rte_flow.h
> > > +++ b/lib/librte_ethdev/rte_flow.h
> > > @@ -31,6 +31,7 @@
> > >  #include <rte_ecpri.h>
> > >  #include <rte_mbuf.h>
> > >  #include <rte_mbuf_dyn.h>
> > > +#include <rte_meter.h>
> > >
> > >  #ifdef __cplusplus
> > >  extern "C" {
> > > @@ -2236,6 +2237,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_COlOR,
> >
> > Typo here, it should be RTE_FLOW_ACTION_TYPE_COLOR.
> >

Why do we need this action?
if it is to save the color it should be done by using mark/metadata
Or by the action of meter. For example you can see RTE_FLOW_ACTION_TYPE_SECURITY
Which if exist saves the session id to a dedicated mbuf field.

> > >  };
> > >
> > >  /**

[Snip]

> > I suggest you do not redundantly specify the value of the default policy ID in
> the
> > comment. Replace by "Default policy ID."
> >
> > > + * Action per color as below:
> > > + * green - no action, yellow - no action, red - drop
> >
> > This does not make sense to me as the default policy. The default policy
> should
> > be "no change", i.e. green -> green (no change), yellow -> yellow (no change),
> > red -> red (no change).
> 
> Can you explain why it doesn't make sense to you?
> 
> Meter with "no change" for all colors has no effect on the packets so it is
> redundant action which just costs performance and resources - probably never
> be used.
> 
> The most common usage for meter is to drop all the packets come above the
> defined rate limit - so it makes sense to take this behavior as default.
> 
> 
> > I suggest we avoid the "no action" statement, as it might be confusing.
> 
> Maybe "do nothing" is better?
> 
Maybe passthrough? Or in rte_flow passthru
 

> > > + * It can be used without creating it by the rte_mtr_meter_policy_add
> > > function.
> > > + */


Best,
Ori

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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-03-18  8:58 [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API Li Zhang
  2021-03-18  8:58 ` [dpdk-dev] [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by the drivers Li Zhang
  2021-03-23 21:02 ` [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API Dumitrescu, Cristian
@ 2021-03-29 10:38 ` Jerin Jacob
  2021-03-29 20:31   ` Matan Azrad
  2021-04-13  0:14 ` [dpdk-dev] [PATCH v3 0/2] Support " Li Zhang
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 78+ messages in thread
From: Jerin Jacob @ 2021-03-29 10:38 UTC (permalink / raw)
  To: Li Zhang
  Cc: Dekel Peled, Ori Kam, Viacheslav Ovsiienko, Matan Azrad,
	Shahaf Shuler, Liron Himi, Jasvinder Singh, Thomas Monjalon,
	Ferruh Yigit, Andrew Rybchenko, Cristian Dumitrescu, dpdk-dev,
	Raslan Darawsheh, Roni Bar Yanai

On Thu, Mar 18, 2021 at 2:28 PM Li Zhang <lizh@nvidia.com> wrote:
>
> 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 - no action, yellow - no action, 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_add
> - 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
>
> Signed-off-by: Li Zhang <lizh@nvidia.com>
> ---
>  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 |  45 ++++++--
>  4 files changed, 210 insertions(+), 74 deletions(-)
>
> diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
> index 669e677e91..5f38aa7fa4 100644
> --- a/lib/librte_ethdev/rte_flow.h
> +++ b/lib/librte_ethdev/rte_flow.h
> @@ -31,6 +31,7 @@
>  #include <rte_ecpri.h>
>  #include <rte_mbuf.h>
>  #include <rte_mbuf_dyn.h>
> +#include <rte_meter.h>
>
>  #ifdef __cplusplus
>  extern "C" {
> @@ -2236,6 +2237,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_COlOR,

Based on my understanding of this API,
1) Application creates the policy
2) Attachs the policy ID to meter object in params
If so, Why we need this new action?

>  };
>
>  /**
> @@ -2828,6 +2836,16 @@ struct rte_flow_action_set_dscp {
>   */
>  struct rte_flow_shared_action;
>
> +/**
> + * 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_add(uint16_t port_id,


_create() may be better here instead of _add() as you have used _delete()

> +       uint32_t policy_id,
> +       const struct rte_flow_action *actions[RTE_COLORS],


1) Does this mean that MLX HW can support any rte_flow actions like,
if packet color is green do RTE_FLOW_ACTION_TYPE_SECURITY etc.


2) Is there any real-world use case other than using normal action
like pass or drop as it is used
in conjunction with meter object?


3) Marvell HW has the following policy actions
a) PASS
b) DROP
c) RED (Random early discard)

Both (a) and (c) are not in enumated as rte_flow_actions.

Should we take rte_flow_action or create meter-specific policy actions?

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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-03-25  6:56   ` Matan Azrad
  2021-03-29  9:23     ` Ori Kam
@ 2021-03-29 16:08     ` Dumitrescu, Cristian
  2021-03-29 20:43       ` Matan Azrad
  1 sibling, 1 reply; 78+ messages in thread
From: Dumitrescu, Cristian @ 2021-03-29 16:08 UTC (permalink / raw)
  To: Matan Azrad, Li Zhang, Dekel Peled, Ori Kam, Slava Ovsiienko,
	Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Jerin Jacob, Hemant Agrawal, Ajit Khaparde
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai

Hi Matan,

> -----Original Message-----
> From: Matan Azrad <matan@nvidia.com>
> Sent: Thursday, March 25, 2021 6:57 AM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; Li Zhang
> <lizh@nvidia.com>; Dekel Peled <dekelp@nvidia.com>; Ori Kam
> <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; Shahaf
> Shuler <shahafs@nvidia.com>; lironh@marvell.com; Singh, Jasvinder
> <jasvinder.singh@intel.com>; NBU-Contact-Thomas Monjalon
> <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> Rybchenko <andrew.rybchenko@oktetlabs.ru>; Jerin Jacob
> <jerinjacobk@gmail.com>; Hemant Agrawal <hemant.agrawal@nxp.com>;
> Ajit Khaparde <ajit.khaparde@broadcom.com>
> Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar Yanai
> <roniba@nvidia.com>
> Subject: RE: [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
> 
> Hi Cristian
> 
> Thank you for your important review!
> I agree with all your comments except one, please see inline.
> 
> From: Dumitrescu, Cristian
> > Hi Li and Matan,
> >
> > Thank you for your proposal, some comments below.
> >
> > I am also adding Jerin and Hemant to this thread, as they also participated
> in
> > the definition of the rte_mtr API in 2017. Also Ajit expressed some interest
> in a
> > previous email.
> >
> > > -----Original Message-----
> > > From: Li Zhang <lizh@nvidia.com>
> > > Sent: Thursday, March 18, 2021 8:58 AM
> > > To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> > > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> > > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>;
> Andrew
> > > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu, Cristian
> > > <cristian.dumitrescu@intel.com>
> > > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > > Subject: [PATCH 1/2] [RFC]: 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 - no action, yellow - no action, red - drop
> > >
> > > Allow coloring the packet using a new rte_flow_action_color as could
> > > be done by the old policy API,
> > >
> >
> > The proposal essentially is to define the meter policy based on rte_flow
> actions
> > rather than a reduced action set defined specifically just for meter object.
> This
> > makes sense to me.
> >
> > > The next API function were added:
> > > - rte_mtr_meter_policy_add
> > > - 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
> > >
> > > Signed-off-by: Li Zhang <lizh@nvidia.com>
> > > ---
> > >  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 |  45 ++++++--
> > >  4 files changed, 210 insertions(+), 74 deletions(-)
> > >
> > > diff --git a/lib/librte_ethdev/rte_flow.h
> > > b/lib/librte_ethdev/rte_flow.h index 669e677e91..5f38aa7fa4 100644
> > > --- a/lib/librte_ethdev/rte_flow.h
> > > +++ b/lib/librte_ethdev/rte_flow.h
> > > @@ -31,6 +31,7 @@
> > >  #include <rte_ecpri.h>
> > >  #include <rte_mbuf.h>
> > >  #include <rte_mbuf_dyn.h>
> > > +#include <rte_meter.h>
> > >
> > >  #ifdef __cplusplus
> > >  extern "C" {
> > > @@ -2236,6 +2237,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_COlOR,
> >
> > Typo here, it should be RTE_FLOW_ACTION_TYPE_COLOR.
> >
> > >  };
> > >
> > >  /**
> > > @@ -2828,6 +2836,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. */
> >
> > I would avoid expanding the list of colors in the comment, as we might
> have to
> > support more than 3 colors in the future. I would simply write: "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..fccec3760b 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 add */
> > > +int
> > > +rte_mtr_meter_policy_add(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_add)(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..07961f2777 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
> > >        */
> > > @@ -462,6 +441,94 @@ 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.
> >
> > I suggest you do not redundantly specify the value of the default policy ID
> in the
> > comment. Replace by "Default policy ID."
> >
> > > + * Action per color as below:
> > > + * green - no action, yellow - no action, red - drop
> >
> > This does not make sense to me as the default policy. The default policy
> should
> > be "no change", i.e. green -> green (no change), yellow -> yellow (no
> change),
> > red -> red (no change).
> 
> Can you explain why it doesn't make sense to you?
> 
> Meter with "no change" for all colors has no effect on the packets so it is
> redundant action which just costs performance and resources - probably
> never be used.
> 

The mbuf::sched::color needs to be set for the packet, and the only way to do this is by applying the RTE_FLOW_ACTION_TYPE_COLOR Action, right? It would make sense that the default policy is to simply apply to the packet the color that the meter just computed for the current packet with no change, right?

> The most common usage for meter is to drop all the packets come above the
> defined rate limit - so it makes sense to take this behavior as default.
> 

I don't agree with this assertion either. One typical usage of the color is to accept all input packets from the user, either green, yellow or red in the absence of any congestion, and charge the user for this traffic; in case of congestion, as typically detected later (typically on scheduling and maybe on a different network node, depending on the application), the packet color is used to prioritize between packets, i.e. drop red packets first before dropping any yellow or green packets. In this case, there is no pre-defined "drop all red packets straight away" policy.

> 
> > I suggest we avoid the "no action" statement, as it might be confusing.
> 
> Maybe "do nothing" is better?
> 

Yes, makes sense to me.

> 
> > > + * It can be used without creating it by the rte_mtr_meter_policy_add
> > > 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] policy_id
> > > + *   Policy identifier for the new meter policy.
> > > + * @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,
> > > +     uint32_t policy_id,
> > > +     const struct rte_flow_action *actions[RTE_COLORS],
> > > +     struct rte_mtr_error *error);
> > > +
> >
> > This entire proposal is about defining a meter policy, yet there is no
> structure
> > defining what exactly the meter policy is!
> >
> > Please let's use the following structure for the policy parameters for the
> policy
> > validate/add/delete API functions:
> >
> > struct rte_mtr_meter_policy_params {
> >         struct rte_flow_action *actions[RTE_COLORS]; };
> >
> > This would also give us the chance to document the policy concept in detail
> > once and not repeat the same explanation over and over. For example, we
> > need to explain clearly that actions[i] potentially represents a chain of
> rte_flow
> > actions terminated by the END action, exactly as specified by the rte_flow
> API
> > for the flow definition, and not just a single action. This is very important
> and
> > yet not entirely clear from the above description.
> >
> > This would also give us the chance to add more attributes to the meter
> policy
> > later, if/when needed, with minimal impact to the API.
> >
> > > +/**
> > > + * 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_add(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..1ad8fb4c40 100644
> > > --- a/lib/librte_ethdev/rte_mtr_driver.h
> > > +++ b/lib/librte_ethdev/rte_mtr_driver.h
> > > @@ -41,6 +41,23 @@ 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,
> > > +     uint32_t policy_id,
> > > +     const struct rte_flow_action *actions[RTE_COLORS],
> > > +     struct rte_mtr_error *error);
> > > +/**< @internal MTR meter policy validate */
> > > +
> > > +typedef int (*rte_mtr_meter_policy_add_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 +86,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 +140,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 add */
> > > +     rte_mtr_meter_policy_add_t meter_policy_add;
> > > +
> > > +     /** 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;
> > >  };
> > >
> > >  /**
> > > --
> > > 2.21.0
> >
> > Regards,
> > Cristian
> Thanks!

Regards,
Cristian

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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-03-29  9:23     ` Ori Kam
@ 2021-03-29 16:24       ` Dumitrescu, Cristian
  2021-04-01 13:13         ` Ori Kam
  0 siblings, 1 reply; 78+ messages in thread
From: Dumitrescu, Cristian @ 2021-03-29 16:24 UTC (permalink / raw)
  To: Ori Kam, Matan Azrad, Li Zhang, Dekel Peled, Slava Ovsiienko,
	Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Jerin Jacob, Hemant Agrawal, Ajit Khaparde
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai

Hi Ori,

> -----Original Message-----
> From: Ori Kam <orika@nvidia.com>
> Sent: Monday, March 29, 2021 10:23 AM
> To: Matan Azrad <matan@nvidia.com>; Dumitrescu, Cristian
> <cristian.dumitrescu@intel.com>; Li Zhang <lizh@nvidia.com>; Dekel Peled
> <dekelp@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; Shahaf
> Shuler <shahafs@nvidia.com>; lironh@marvell.com; Singh, Jasvinder
> <jasvinder.singh@intel.com>; NBU-Contact-Thomas Monjalon
> <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> Rybchenko <andrew.rybchenko@oktetlabs.ru>; Jerin Jacob
> <jerinjacobk@gmail.com>; Hemant Agrawal <hemant.agrawal@nxp.com>;
> Ajit Khaparde <ajit.khaparde@broadcom.com>
> Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar Yanai
> <roniba@nvidia.com>
> Subject: RE: [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
> 
> Hi All,
> 
> > -----Original Message-----
> > From: Matan Azrad <matan@nvidia.com>
> > Subject: RE: [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
> >
> > Hi Cristian
> >
> > Thank you for your important review!
> > I agree with all your comments except one, please see inline.
> >
> > From: Dumitrescu, Cristian
> > > Hi Li and Matan,
> > >
> > > Thank you for your proposal, some comments below.
> > >
> > > I am also adding Jerin and Hemant to this thread, as they also participated
> in
> > > the definition of the rte_mtr API in 2017. Also Ajit expressed some
> interest in
> > a
> > > previous email.
> > >
> > > > -----Original Message-----
> > > > From: Li Zhang <lizh@nvidia.com>
> > > > Sent: Thursday, March 18, 2021 8:58 AM
> > > > To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> > > > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> > > > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>;
> Andrew
> > > > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu, Cristian
> > > > <cristian.dumitrescu@intel.com>
> > > > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > > > Subject: [PATCH 1/2] [RFC]: 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 - no action, yellow - no action, red - drop
> > > >
> > > > Allow coloring the packet using a new rte_flow_action_color as could
> > > > be done by the old policy API,
> > > >
> > >
> > > The proposal essentially is to define the meter policy based on rte_flow
> > actions
> > > rather than a reduced action set defined specifically just for meter object.
> > This
> > > makes sense to me.
> > >
> > > > The next API function were added:
> > > > - rte_mtr_meter_policy_add
> > > > - 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
> > > >
> > > > Signed-off-by: Li Zhang <lizh@nvidia.com>
> > > > ---
> > > >  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 |  45 ++++++--
> > > >  4 files changed, 210 insertions(+), 74 deletions(-)
> > > >
> > > > diff --git a/lib/librte_ethdev/rte_flow.h
> > > > b/lib/librte_ethdev/rte_flow.h index 669e677e91..5f38aa7fa4 100644
> > > > --- a/lib/librte_ethdev/rte_flow.h
> > > > +++ b/lib/librte_ethdev/rte_flow.h
> > > > @@ -31,6 +31,7 @@
> > > >  #include <rte_ecpri.h>
> > > >  #include <rte_mbuf.h>
> > > >  #include <rte_mbuf_dyn.h>
> > > > +#include <rte_meter.h>
> > > >
> > > >  #ifdef __cplusplus
> > > >  extern "C" {
> > > > @@ -2236,6 +2237,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_COlOR,
> > >
> > > Typo here, it should be RTE_FLOW_ACTION_TYPE_COLOR.
> > >
> 
> Why do we need this action?

We need this new proposed RTE_FLOW_ACTION_TYPE_COLOR action to set the packet color in the packet mbuf (i.e. in the mbuf::sched:color field) in order to tell the later stages of the pipeline what the packet color is.

> if it is to save the color it should be done by using mark/metadata

As stated in its description, the  RTE_FLOW_ACTION_TYPE_MARK action Is setting the mbuf::hash.fdir.hi field, which is used for a different purpose that is unrelated to the packet color, which has its own field within the mbuf.

> Or by the action of meter.

The new proposed RTE_FLOW_ACTION_TYPE_COLOR action is indeed an action of the meter and meter only, right?

For example you can see
> RTE_FLOW_ACTION_TYPE_SECURITY
> Which if exist saves the session id to a dedicated mbuf field.
> 

The meter processing and action take place independently of the security API: it can be enabled when the security API is disabled and is not conditioned in any way by the security API. To be honest, I don't understand the connection with the security API that you are trying to make here.

> > > >  };
> > > >
> > > >  /**
> 
> [Snip]
> 
> > > I suggest you do not redundantly specify the value of the default policy ID
> in
> > the
> > > comment. Replace by "Default policy ID."
> > >
> > > > + * Action per color as below:
> > > > + * green - no action, yellow - no action, red - drop
> > >
> > > This does not make sense to me as the default policy. The default policy
> > should
> > > be "no change", i.e. green -> green (no change), yellow -> yellow (no
> change),
> > > red -> red (no change).
> >
> > Can you explain why it doesn't make sense to you?
> >
> > Meter with "no change" for all colors has no effect on the packets so it is
> > redundant action which just costs performance and resources - probably
> never
> > be used.
> >
> > The most common usage for meter is to drop all the packets come above
> the
> > defined rate limit - so it makes sense to take this behavior as default.
> >
> >
> > > I suggest we avoid the "no action" statement, as it might be confusing.
> >
> > Maybe "do nothing" is better?
> >
> Maybe passthrough? Or in rte_flow passthru
> 

No, we need to save the packet color in the packet mbuf (mbuf::sched:color), and the RTE_FLOW_ACTION_TYPE_PASSTHRU action is not doing this.

> 
> > > > + * It can be used without creating it by the rte_mtr_meter_policy_add
> > > > function.
> > > > + */
> 
> 
> Best,
> Ori

Regards,
Cristian

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

* Re: [dpdk-dev] [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by the drivers
  2021-03-25 23:16       ` Ajit Khaparde
@ 2021-03-29 19:56         ` Matan Azrad
  0 siblings, 0 replies; 78+ messages in thread
From: Matan Azrad @ 2021-03-29 19:56 UTC (permalink / raw)
  To: Ajit Khaparde
  Cc: Dumitrescu, Cristian, Li Zhang, Dekel Peled, Ori Kam,
	Slava Ovsiienko, Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Jerin Jacob, Hemant Agrawal, Richardson, Bruce, Doherty, Declan,
	dev, Raslan Darawsheh, Roni Bar Yanai

Hi Ajit

Looks like you agree with this RFC to move meter objects to be managed by PMD pointers.

Thanks for the review!

From: Ajit Khaparde
> On Thu, Mar 25, 2021 at 1:21 AM Matan Azrad <matan@nvidia.com> wrote:
> >
> > Hi Cristian
> >
> > From: Dumitrescu, Cristian
> > > Hi Li and Matan,
> > >
> > > > -----Original Message-----
> > > > From: Li Zhang <lizh@nvidia.com>
> > > > Sent: Thursday, March 18, 2021 8:58 AM
> > > > To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> > > > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> > > > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> > > > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu, Cristian
> > > > <cristian.dumitrescu@intel.com>
> > > > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > > > Subject: [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by
> > > > the drivers
> > > >
> > > > Currently, all the meter objects are managed by the user IDs:
> > > > meter, profile and policy.
> > > > Hence, each PMD should manage data-structure in order to map each API
> > > > ID to the private PMD management structure.
> > > >
> > > > From the application side, it has all the picture how meter is going
> > > > to be assigned to flows and can easily use direct mapping even when
> > > > the meter handler is provided by the PMDs.
> > > >
> > > > Also, this is the approach of the rte_flow API handles:
> > > > the flow handle and the shared action handle is provided by the PMDs.
> > > >
> > > > Use drivers handlers in order to manage all the meter API objects.
> > > >
> > >
> > > This seems to be take 2 of the discussion that we already had  in this thread:
> > >
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmails.dp
> > > dk.org%2Farchives%2Fdev%2F2021-
> > >
> March%2F200710.html&amp;data=04%7C01%7Cmatan%40nvidia.com%7Cab0
> > >
> e3cc77b9e4101344e08d8ee434bbe%7C43083d15727340c1b7db39efd9ccc17a%
> > >
> 7C0%7C0%7C637521320105450617%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiM
> > >
> C4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&
> > >
> amp;sdata=94bFRICfGEzk5s53MRUvFMQe5ZlhP2Tmnu82hwUytc4%3D&amp;re
> > > served=0, so apologies for mostly summarizing my previous feedback here.
> > >
> > > I am against this proposal because:
> > > 1. We already discussed this topic of user-provided handles vs. driver-
> provided
> > > handles at length on this exact email list back in 2017, when we first
> introduced
> > > this API, and I don't see any real reason to revisit the decision we took then.
> >
> > Why not?
> > There is more experiences\usages now.
> > New drivers added the support and also now scalability is growing and
> growing....
> >
> >
> > > 2. For me, it is more natural and it also helps the application to simplify its
> data
> > > structures if the user provides its own IDs rather than the user having to
> deal
> > > with the IDs provided by the driver.
> >
> > Generally I don't think other flow DPDK APIs align with your feelings here, see
> rte_flow object and rte_flow_shared_action.
> >
> > Specifically for meter:
> >         - here, meter is HW\driver offload where performance\rate either for
> meter creation\deletion or for the actual data-path is very important especially
> when we talk on very big numbers, so "natural" has less importance here.
> >           We need to think on the global solution for application ->API->driver. in
> meter feature, the user has the ability to manage the IDs better than the PMDs
> for the most of the use-cases:
> >                         1. meter per flow: just save the driver handle in the app flow
> context.
> >                         2. meter per VM\USER flows\rte_flow group\any other context
> grouped multiple flows: just save the driver handle in the app context.
> >         If PMD need to map the IDs, it is more complex for sure, requires more
> memory and more lookup time.
> >
> >         - I'm not sure it is natural for all the use-cases, sometimes generating
> unique ID may complex the app.
> >
> >
> > > 3. It is much easier and portable to pass numeric and string-based IDs
> around
> > > (e.g. between processes) as opposed to pointer-based IDs, as pointers are
> only
> > > valid in one address space and not in others. There are several DPDK APIs
> that
> > > moved away from pointer handles to string IDs.
> Pardon my ignorance..
> But which DPDK APIs moved to string IDs from pointer handles?
> 
> >
> > Yes, I agree here generally.
> > But again, since meter is used only by rte_flow, it is better to align the same
> handle mechanism.
> I don't want to say - do this because rte_flow uses a pointer.
> I don't have a strong opinion for one over the other. In the end the
> logic can be adapted one way or the other.
> But having implemented rte_flow support in the PMD, I think it is a
> good idea to avoid the duplication of meter_id to pointer based handle
> conversion and bookkeeping logic in the application and the PMD.
> 
> >
> > > 4. The mapping of user IDs to internal pointers within the driver is IMO not
> a
> > > big issue in terms of memory footprint or API call rate. Matan also
> confirmed
> > > this in the above thread when saying tis is not about either driver memory
> > > footprint or API call speed, as this mapping is easy to optimize.
> >
> > Yes, it is not very big deal, but still costs more than the new suggestion,
> especially in big scale.
> >
> > > And last but not least, this change obviously propagates in every API
> function,
> > > so it would result in big churn in API, all drivers and all apps (including
> testpmd,
> > > etc) implementing it (for IMO no real benefit). Yes, this API is experimental
> and
> > > therefore we can operate changes in it, but I'd rather see incremental and
> > > converging improvements rather than this.
> >
> > Yes, it changes all API, but very small part in each, will be very easy to align
> all the current dpdk components to use this concept.
> >
> > > If you guys insist with this proposal, I would like to get more opinions from
> > > other vendors and contributors from within our DPDK community.
> >
> >
> > Yes, more opinions are very welcomed.
> >
> > Thanks

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

* Re: [dpdk-dev] [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by the drivers
  2021-03-27 13:15       ` Jerin Jacob
@ 2021-03-29 20:10         ` Matan Azrad
  2021-03-31 10:22           ` Jerin Jacob
  0 siblings, 1 reply; 78+ messages in thread
From: Matan Azrad @ 2021-03-29 20:10 UTC (permalink / raw)
  To: Jerin Jacob
  Cc: Dumitrescu, Cristian, Li Zhang, Dekel Peled, Ori Kam,
	Slava Ovsiienko, Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Hemant Agrawal, Ajit Khaparde, Richardson, Bruce, Doherty,
	Declan, dev, Raslan Darawsheh, Roni Bar Yanai

Hi Jerin

Thanks for the review.
PSB

From: Jerin Jacob
> On Thu, Mar 25, 2021 at 1:51 PM Matan Azrad <matan@nvidia.com> wrote:
> >
> > Hi Cristian
> >
> > From: Dumitrescu, Cristian
> > > Hi Li and Matan,
> > >
> > > > -----Original Message-----
> > > > From: Li Zhang <lizh@nvidia.com>
> > > > Sent: Thursday, March 18, 2021 8:58 AM
> > > > To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> > > > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> > > > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>;
> > > > Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu,
> > > > Cristian <cristian.dumitrescu@intel.com>
> > > > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > > > Subject: [PATCH 2/2] [RFC]: ethdev: manage meter API object
> > > > handles by the drivers
> > > >
> 
> >
> > Yes, it changes all API, but very small part in each, will be very easy to align
> all the current dpdk components to use this concept.
> >
> > > If you guys insist with this proposal, I would like to get more
> > > opinions from other vendors and contributors from within our DPDK
> community.
> >
> >
> > Yes, more opinions are very welcomed.
> 
> This point was discussed to the core in the initial meter RFC.
> 
> IMO, IDs helps in managing meter objects more clean way with lookup cost.

Although it is not the main topic here I ask:
What is the difference between pointer to ID for the cost topic? Both are unique IDs actually....

> especially, If a non DPDK application, managing the meter ID via some sort of
> IPC.
> 
> Considering existing APIs and drivers are implemented with ID scheme, I think,
> it would be better to give some performance data for changing the scheme.
> 
> I was under impression that, Typical number of MAX meter HW objects could
> be around 16k something and the number of meter objects created and
> destroyed per second will be very low. (In the order to 16k ops per second)
> Could you share the practical number of meter HW objects in MLX SoCs and
> the number of operations are you are envisioning?

We are talking about 4M HW meters in the next version of mlx5 driver.
The rate of flows(with meter action) creation\deletion can arrive to 200K-300K per second and we are working hard to improve it more.

Can you please give also your opinion about the owner of the ID\pointer?
The main goal of this patch is to move the owner from the application to the driver....




 
> >
> > Thanks

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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-03-29 10:38 ` Jerin Jacob
@ 2021-03-29 20:31   ` Matan Azrad
  2021-03-31 10:50     ` Jerin Jacob
  0 siblings, 1 reply; 78+ messages in thread
From: Matan Azrad @ 2021-03-29 20:31 UTC (permalink / raw)
  To: Jerin Jacob, Li Zhang
  Cc: Dekel Peled, Ori Kam, Slava Ovsiienko, Shahaf Shuler, Liron Himi,
	Jasvinder Singh, NBU-Contact-Thomas Monjalon, Ferruh Yigit,
	Andrew Rybchenko, Cristian Dumitrescu, dpdk-dev,
	Raslan Darawsheh, Roni Bar Yanai

Hi Jerin

Thanks for the review.
PSB

From: Jerin Jacob
> On Thu, Mar 18, 2021 at 2:28 PM Li Zhang <lizh@nvidia.com> wrote:
> >
> > 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 - no action, yellow - no action, 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_add
> > - 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
> >
> > Signed-off-by: Li Zhang <lizh@nvidia.com>
> > ---
> >  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 |  45 ++++++--
> >  4 files changed, 210 insertions(+), 74 deletions(-)
> >
> > diff --git a/lib/librte_ethdev/rte_flow.h
> > b/lib/librte_ethdev/rte_flow.h index 669e677e91..5f38aa7fa4 100644
> > --- a/lib/librte_ethdev/rte_flow.h
> > +++ b/lib/librte_ethdev/rte_flow.h
> > @@ -31,6 +31,7 @@
> >  #include <rte_ecpri.h>
> >  #include <rte_mbuf.h>
> >  #include <rte_mbuf_dyn.h>
> > +#include <rte_meter.h>
> >
> >  #ifdef __cplusplus
> >  extern "C" {
> > @@ -2236,6 +2237,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_COlOR,
> 
> Based on my understanding of this API,
> 1) Application creates the policy
> 2) Attachs the policy ID to meter object in params If so, Why we need this new
> action?

Yes,
In the new policy API the meter actions will be defined by rte_flow actions.
The old policy API used rte_mtr actions: color green\color yellow\color red\drop.

This new rte_flow COLOR action comes to replace the old policy API "color" actions which set the color field in mbuf.


> >  };
> >
> >  /**
> > @@ -2828,6 +2836,16 @@ struct rte_flow_action_set_dscp {
> >   */
> >  struct rte_flow_shared_action;
> >
> > +/**
> > + * 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_add(uint16_t port_id,
> 
> 
> _create() may be better here instead of _add() as you have used _delete()

Yes!

> > +       uint32_t policy_id,
> > +       const struct rte_flow_action *actions[RTE_COLORS],
> 
> 
> 1) Does this mean that MLX HW can support any rte_flow actions like, if packet
> color is green do RTE_FLOW_ACTION_TYPE_SECURITY etc.

Theoretically yes, we can support most of the actions.
For the first stage we are going to support next: queue\RSS\port id\mark\tag\jump.

For example, user can select different queue\port id per color.

> 2) Is there any real-world use case other than using normal action like pass or
> drop as it is used in conjunction with meter object?

Yes, I wrote above.
 
> 3) Marvell HW has the following policy actions
> a) PASS
> b) DROP
> c) RED (Random early discard)
> 
> Both (a) and (c) are not in enumated as rte_flow_actions.

(a) is in, just don't specify any action.

Can you explain what is "Random early discard"?
How did you specify it in the old\current meter policy API?


Note, that after the policy actions the device should continue to do the rest of the actions in the flow (after meter) if no termination action in the policy color.

> 
> Should we take rte_flow_action or create meter-specific policy actions?

This patch removes the meter-specific policy actions.
You need to use rte_flow action.

By the way, can you help to adjust Marvell driver to the change?


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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-03-29 16:08     ` Dumitrescu, Cristian
@ 2021-03-29 20:43       ` Matan Azrad
  2021-03-31 15:46         ` Dumitrescu, Cristian
  0 siblings, 1 reply; 78+ messages in thread
From: Matan Azrad @ 2021-03-29 20:43 UTC (permalink / raw)
  To: Dumitrescu, Cristian, Li Zhang, Dekel Peled, Ori Kam,
	Slava Ovsiienko, Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Jerin Jacob, Hemant Agrawal, Ajit Khaparde
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai



From: Dumitrescu, Cristian
> Hi Matan,
> 
> > -----Original Message-----
> > From: Matan Azrad <matan@nvidia.com>
> > Sent: Thursday, March 25, 2021 6:57 AM
> > To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; Li Zhang
> > <lizh@nvidia.com>; Dekel Peled <dekelp@nvidia.com>; Ori Kam
> > <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; Shahaf
> > Shuler <shahafs@nvidia.com>; lironh@marvell.com; Singh, Jasvinder
> > <jasvinder.singh@intel.com>; NBU-Contact-Thomas Monjalon
> > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Jerin Jacob
> > <jerinjacobk@gmail.com>; Hemant Agrawal <hemant.agrawal@nxp.com>;
> Ajit
> > Khaparde <ajit.khaparde@broadcom.com>
> > Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar
> > Yanai <roniba@nvidia.com>
> > Subject: RE: [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy
> > API
> >
> > Hi Cristian
> >
> > Thank you for your important review!
> > I agree with all your comments except one, please see inline.
> >
> > From: Dumitrescu, Cristian
> > > Hi Li and Matan,
> > >
> > > Thank you for your proposal, some comments below.
> > >
> > > I am also adding Jerin and Hemant to this thread, as they also
> > > participated
> > in
> > > the definition of the rte_mtr API in 2017. Also Ajit expressed some
> > > interest
> > in a
> > > previous email.
> > >
> > > > -----Original Message-----
> > > > From: Li Zhang <lizh@nvidia.com>
> > > > Sent: Thursday, March 18, 2021 8:58 AM
> > > > To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> > > > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> > > > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>;
> > Andrew
> > > > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu, Cristian
> > > > <cristian.dumitrescu@intel.com>
> > > > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > > > Subject: [PATCH 1/2] [RFC]: 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 - no action, yellow - no action, red - drop
> > > >
> > > > Allow coloring the packet using a new rte_flow_action_color as
> > > > could be done by the old policy API,
> > > >
> > >
> > > The proposal essentially is to define the meter policy based on
> > > rte_flow
> > actions
> > > rather than a reduced action set defined specifically just for meter object.
> > This
> > > makes sense to me.
> > >
> > > > The next API function were added:
> > > > - rte_mtr_meter_policy_add
> > > > - 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
> > > >
> > > > Signed-off-by: Li Zhang <lizh@nvidia.com>
> > > > ---
> > > >  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 |  45 ++++++--
> > > >  4 files changed, 210 insertions(
<snip>
> > > > +/**
> > > > + * Policy id 0 is default policy.
> > >
> > > I suggest you do not redundantly specify the value of the default
> > > policy ID
> > in the
> > > comment. Replace by "Default policy ID."
> > >
> > > > + * Action per color as below:
> > > > + * green - no action, yellow - no action, red - drop
> > >
> > > This does not make sense to me as the default policy. The default
> > > policy
> > should
> > > be "no change", i.e. green -> green (no change), yellow -> yellow
> > > (no
> > change),
> > > red -> red (no change).
> >
> > Can you explain why it doesn't make sense to you?
> >
> > Meter with "no change" for all colors has no effect on the packets so
> > it is redundant action which just costs performance and resources -
> > probably never be used.
> >
> 
> The mbuf::sched::color needs to be set for the packet, and the only way to do
> this is by applying the RTE_FLOW_ACTION_TYPE_COLOR Action, right? It would
> make sense that the default policy is to simply apply to the packet the color
> that the meter just computed for the current packet with no change, right?

I don't think so.
When we are working with HW offloads (this is the main goal of rte_flow and this meter API) the motivation is to do the actions directly in the NIC HW.
Moving the color information to the SW is like doing "partial offload".


> > The most common usage for meter is to drop all the packets come above
> > the defined rate limit - so it makes sense to take this behavior as default.
> >
> 
> I don't agree with this assertion either. One typical usage of the color is to
> accept all input packets from the user, either green, yellow or red in the
> absence of any congestion, and charge the user for this traffic; in case of
> congestion, as typically detected later (typically on scheduling and maybe on a
> different network node, depending on the application), the packet color is used
> to prioritize between packets, i.e. drop red packets first before dropping any
> yellow or green packets. In this case, there is no pre-defined "drop all red
> packets straight away" policy.


I familiar with a lot of meter users(at least 5 applications) in the industry, no one use the color actions. 
All of them drop red packets and continue to the next flow actions(after meter) otherwise.


If you insist, we can define 2 default IDs...

> >
> > > I suggest we avoid the "no action" statement, as it might be confusing.
> >
> > Maybe "do nothing" is better?
> >
> 
> Yes, makes sense to me.

<snip>

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

* Re: [dpdk-dev] [PATCH 2/2] [RFC]: ethdev: manage meter API object handles by the drivers
  2021-03-29 20:10         ` Matan Azrad
@ 2021-03-31 10:22           ` Jerin Jacob
  0 siblings, 0 replies; 78+ messages in thread
From: Jerin Jacob @ 2021-03-31 10:22 UTC (permalink / raw)
  To: Matan Azrad
  Cc: Dumitrescu, Cristian, Li Zhang, Dekel Peled, Ori Kam,
	Slava Ovsiienko, Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Hemant Agrawal, Ajit Khaparde, Richardson, Bruce, Doherty,
	Declan, dev, Raslan Darawsheh, Roni Bar Yanai

On Tue, Mar 30, 2021 at 1:40 AM Matan Azrad <matan@nvidia.com> wrote:
>
> Hi Jerin


Hi Matan

>
> Thanks for the review.
> PSB
>
> From: Jerin Jacob
> > On Thu, Mar 25, 2021 at 1:51 PM Matan Azrad <matan@nvidia.com> wrote:
> > >
> > > Hi Cristian
> > >
> > > From: Dumitrescu, Cristian
> > > > Hi Li and Matan,
> > > >
> > > > > -----Original Message-----
> > > > > From: Li Zhang <lizh@nvidia.com>
> > > > > Sent: Thursday, March 18, 2021 8:58 AM
> > > > > To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> > > > > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> > > > > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > > > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>;
> > > > > Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu,
> > > > > Cristian <cristian.dumitrescu@intel.com>
> > > > > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > > > > Subject: [PATCH 2/2] [RFC]: ethdev: manage meter API object
> > > > > handles by the drivers
> > > > >
> >
> > >
> > > Yes, it changes all API, but very small part in each, will be very easy to align
> > all the current dpdk components to use this concept.
> > >
> > > > If you guys insist with this proposal, I would like to get more
> > > > opinions from other vendors and contributors from within our DPDK
> > community.
> > >
> > >
> > > Yes, more opinions are very welcomed.
> >
> > This point was discussed to the core in the initial meter RFC.
> >
> > IMO, IDs helps in managing meter objects more clean way with lookup cost.
>
> Although it is not the main topic here I ask:
> What is the difference between pointer to ID for the cost topic? Both are unique IDs actually....

Once is defined by app and another one by implemention.


>
> > especially, If a non DPDK application, managing the meter ID via some sort of
> > IPC.
> >
> > Considering existing APIs and drivers are implemented with ID scheme, I think,
> > it would be better to give some performance data for changing the scheme.
> >
> > I was under impression that, Typical number of MAX meter HW objects could
> > be around 16k something and the number of meter objects created and
> > destroyed per second will be very low. (In the order to 16k ops per second)
> > Could you share the practical number of meter HW objects in MLX SoCs and
> > the number of operations are you are envisioning?
>
> We are talking about 4M HW meters in the next version of mlx5 driver.
> The rate of flows(with meter action) creation\deletion can arrive to 200K-300K per second and we are working hard to improve it more.
>
> Can you please give also your opinion about the owner of the ID\pointer?

Just to clarify, When you have 4M HW meters, At least, you have will
4M registers or 4M context memory kind
of an interface between HW<->SW set/get meter-specific objects. Or Is
it some kind of emulation over SW?

If it 4M HW meters then ID scheme makes sense.


> The main goal of this patch is to move the owner from the application to the driver....
>
>
>
>
>
> > >
> > > Thanks

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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-03-29 20:31   ` Matan Azrad
@ 2021-03-31 10:50     ` Jerin Jacob
  0 siblings, 0 replies; 78+ messages in thread
From: Jerin Jacob @ 2021-03-31 10:50 UTC (permalink / raw)
  To: Matan Azrad
  Cc: Li Zhang, Dekel Peled, Ori Kam, Slava Ovsiienko, Shahaf Shuler,
	Liron Himi, Jasvinder Singh, NBU-Contact-Thomas Monjalon,
	Ferruh Yigit, Andrew Rybchenko, Cristian Dumitrescu, dpdk-dev,
	Raslan Darawsheh, Roni Bar Yanai

On Tue, Mar 30, 2021 at 2:01 AM Matan Azrad <matan@nvidia.com> wrote:
>
> Hi Jerin
>
> Thanks for the review.
> PSB
>
> From: Jerin Jacob
> > On Thu, Mar 18, 2021 at 2:28 PM Li Zhang <lizh@nvidia.com> wrote:
> > >
> > > 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 - no action, yellow - no action, 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_add
> > > - 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
> > >
> > > Signed-off-by: Li Zhang <lizh@nvidia.com>
> > > ---
> > >  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 |  45 ++++++--
> > >  4 files changed, 210 insertions(+), 74 deletions(-)
> > >
> > > diff --git a/lib/librte_ethdev/rte_flow.h
> > > b/lib/librte_ethdev/rte_flow.h index 669e677e91..5f38aa7fa4 100644
> > > --- a/lib/librte_ethdev/rte_flow.h
> > > +++ b/lib/librte_ethdev/rte_flow.h
> > > @@ -31,6 +31,7 @@
> > >  #include <rte_ecpri.h>
> > >  #include <rte_mbuf.h>
> > >  #include <rte_mbuf_dyn.h>
> > > +#include <rte_meter.h>
> > >
> > >  #ifdef __cplusplus
> > >  extern "C" {
> > > @@ -2236,6 +2237,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_COlOR,
> >
> > Based on my understanding of this API,
> > 1) Application creates the policy
> > 2) Attachs the policy ID to meter object in params If so, Why we need this new
> > action?
>
> Yes,
> In the new policy API the meter actions will be defined by rte_flow actions.
> The old policy API used rte_mtr actions: color green\color yellow\color red\drop.
>
> This new rte_flow COLOR action comes to replace the old policy API "color" actions which set the color field in mbuf.

OK. Looks good to me. I think, it is better to change to
RTE_FLOW_ACTION_TYPE_METER_COLOR to
denote it as meter-specific action.

>
>
> > >  };
> > >
> > >  /**
> > > @@ -2828,6 +2836,16 @@ struct rte_flow_action_set_dscp {
> > >   */
> > >  struct rte_flow_shared_action;
> > >
> > > +/**
> > > + * 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_add(uint16_t port_id,
> >
> >
> > _create() may be better here instead of _add() as you have used _delete()
>
> Yes!

OK

>
> > > +       uint32_t policy_id,
> > > +       const struct rte_flow_action *actions[RTE_COLORS],
> >
> >
> > 1) Does this mean that MLX HW can support any rte_flow actions like, if packet
> > color is green do RTE_FLOW_ACTION_TYPE_SECURITY etc.
>
> Theoretically yes, we can support most of the actions.
> For the first stage we are going to support next: queue\RSS\port id\mark\tag\jump.
>
> For example, user can select different queue\port id per color.


OK.

>
> > 2) Is there any real-world use case other than using normal action like pass or
> > drop as it is used in conjunction with meter object?
>
> Yes, I wrote above.
>
> > 3) Marvell HW has the following policy actions
> > a) PASS
> > b) DROP
> > c) RED (Random early discard)
> >
> > Both (a) and (c) are not in enumated as rte_flow_actions.
>
> (a) is in, just don't specify any action.
>
> Can you explain what is "Random early discard"?

https://en.wikipedia.org/wiki/Random_early_detection

> How did you specify it in the old\current meter policy API?

It can not. We are planning to add support for the meter in the new cnxk driver.
Planning change the meter API based on the driver patch.

>
>
> Note, that after the policy actions the device should continue to do the rest of the actions in the flow (after meter) if no termination action in the policy color.
>
> >
> > Should we take rte_flow_action or create meter-specific policy actions?
>
> This patch removes the meter-specific policy actions.
> You need to use rte_flow action.
>
> By the way, can you help to adjust Marvell driver to the change?

The current driver(octeontx2) is not using meter.



>

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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-03-29 20:43       ` Matan Azrad
@ 2021-03-31 15:46         ` Dumitrescu, Cristian
  2021-04-04 13:48           ` Matan Azrad
  0 siblings, 1 reply; 78+ messages in thread
From: Dumitrescu, Cristian @ 2021-03-31 15:46 UTC (permalink / raw)
  To: Matan Azrad, Li Zhang, Dekel Peled, Ori Kam, Slava Ovsiienko,
	Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Jerin Jacob, Hemant Agrawal, Ajit Khaparde
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai

Hi Matan,

> -----Original Message-----
> From: Matan Azrad <matan@nvidia.com>
> Sent: Monday, March 29, 2021 9:44 PM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; Li Zhang
> <lizh@nvidia.com>; Dekel Peled <dekelp@nvidia.com>; Ori Kam
> <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; Shahaf
> Shuler <shahafs@nvidia.com>; lironh@marvell.com; Singh, Jasvinder
> <jasvinder.singh@intel.com>; NBU-Contact-Thomas Monjalon
> <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> Rybchenko <andrew.rybchenko@oktetlabs.ru>; Jerin Jacob
> <jerinjacobk@gmail.com>; Hemant Agrawal <hemant.agrawal@nxp.com>;
> Ajit Khaparde <ajit.khaparde@broadcom.com>
> Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar Yanai
> <roniba@nvidia.com>
> Subject: RE: [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
> 
> 
> 
> From: Dumitrescu, Cristian
> > Hi Matan,
> >
> > > -----Original Message-----
> > > From: Matan Azrad <matan@nvidia.com>
> > > Sent: Thursday, March 25, 2021 6:57 AM
> > > To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; Li Zhang
> > > <lizh@nvidia.com>; Dekel Peled <dekelp@nvidia.com>; Ori Kam
> > > <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; Shahaf
> > > Shuler <shahafs@nvidia.com>; lironh@marvell.com; Singh, Jasvinder
> > > <jasvinder.singh@intel.com>; NBU-Contact-Thomas Monjalon
> > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>;
> Andrew
> > > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Jerin Jacob
> > > <jerinjacobk@gmail.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>;
> > Ajit
> > > Khaparde <ajit.khaparde@broadcom.com>
> > > Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar
> > > Yanai <roniba@nvidia.com>
> > > Subject: RE: [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy
> > > API
> > >
> > > Hi Cristian
> > >
> > > Thank you for your important review!
> > > I agree with all your comments except one, please see inline.
> > >
> > > From: Dumitrescu, Cristian
> > > > Hi Li and Matan,
> > > >
> > > > Thank you for your proposal, some comments below.
> > > >
> > > > I am also adding Jerin and Hemant to this thread, as they also
> > > > participated
> > > in
> > > > the definition of the rte_mtr API in 2017. Also Ajit expressed some
> > > > interest
> > > in a
> > > > previous email.
> > > >
> > > > > -----Original Message-----
> > > > > From: Li Zhang <lizh@nvidia.com>
> > > > > Sent: Thursday, March 18, 2021 8:58 AM
> > > > > To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> > > > > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> > > > > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > > > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>;
> > > Andrew
> > > > > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu, Cristian
> > > > > <cristian.dumitrescu@intel.com>
> > > > > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > > > > Subject: [PATCH 1/2] [RFC]: 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 - no action, yellow - no action, red - drop
> > > > >
> > > > > Allow coloring the packet using a new rte_flow_action_color as
> > > > > could be done by the old policy API,
> > > > >
> > > >
> > > > The proposal essentially is to define the meter policy based on
> > > > rte_flow
> > > actions
> > > > rather than a reduced action set defined specifically just for meter
> object.
> > > This
> > > > makes sense to me.
> > > >
> > > > > The next API function were added:
> > > > > - rte_mtr_meter_policy_add
> > > > > - 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
> > > > >
> > > > > Signed-off-by: Li Zhang <lizh@nvidia.com>
> > > > > ---
> > > > >  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 |  45 ++++++--
> > > > >  4 files changed, 210 insertions(
> <snip>
> > > > > +/**
> > > > > + * Policy id 0 is default policy.
> > > >
> > > > I suggest you do not redundantly specify the value of the default
> > > > policy ID
> > > in the
> > > > comment. Replace by "Default policy ID."
> > > >
> > > > > + * Action per color as below:
> > > > > + * green - no action, yellow - no action, red - drop
> > > >
> > > > This does not make sense to me as the default policy. The default
> > > > policy
> > > should
> > > > be "no change", i.e. green -> green (no change), yellow -> yellow
> > > > (no
> > > change),
> > > > red -> red (no change).
> > >
> > > Can you explain why it doesn't make sense to you?
> > >
> > > Meter with "no change" for all colors has no effect on the packets so
> > > it is redundant action which just costs performance and resources -
> > > probably never be used.
> > >
> >
> > The mbuf::sched::color needs to be set for the packet, and the only way to
> do
> > this is by applying the RTE_FLOW_ACTION_TYPE_COLOR Action, right? It
> would
> > make sense that the default policy is to simply apply to the packet the color
> > that the meter just computed for the current packet with no change, right?
> 
> I don't think so.
> When we are working with HW offloads (this is the main goal of rte_flow and
> this meter API) the motivation is to do the actions directly in the NIC HW.
> Moving the color information to the SW is like doing "partial offload".
> 

Sorry, Matan, but as the bulk of the packets are passed by the NIC to the CPU as opposed to being returned to the network without the CPU ever seeing them, the rte_flow API is a partial offload API, not a full offload API, not sure why we disagree here.

Just to make sure we are on the same page and not getting round in circles: I think you agree that we should have this action RTE_FLOW_ACTION_TYPE_COLOR to setup the color for the CPU to see in mbuf::sched:color, but you don't agree this action should be part of the default policy, did I get your position correctly?

> 
> > > The most common usage for meter is to drop all the packets come above
> > > the defined rate limit - so it makes sense to take this behavior as default.
> > >
> >
> > I don't agree with this assertion either. One typical usage of the color is to
> > accept all input packets from the user, either green, yellow or red in the
> > absence of any congestion, and charge the user for this traffic; in case of
> > congestion, as typically detected later (typically on scheduling and maybe
> on a
> > different network node, depending on the application), the packet color is
> used
> > to prioritize between packets, i.e. drop red packets first before dropping
> any
> > yellow or green packets. In this case, there is no pre-defined "drop all red
> > packets straight away" policy.
> 
> 
> I familiar with a lot of meter users(at least 5 applications) in the industry, no
> one use the color actions.
> All of them drop red packets and continue to the next flow actions(after
> meter) otherwise.
> 

I politely but firmly disagree. None of the apps that I have seen is dropping the red packets straight away, they simply use the color as an indication of the packet drop priority at a later stage in the pipeline when congestion is detected. 

> 
> If you insist, we can define 2 default IDs...
> 

Maybe we should not have any pre-registered policies at all?

For the user's convenience, we could provide the configuration parameters for some of the common policies, like the ones mentioned here, in the API and let the users decide which one(s), if any, they want to register?

> > >
> > > > I suggest we avoid the "no action" statement, as it might be confusing.
> > >
> > > Maybe "do nothing" is better?
> > >
> >
> > Yes, makes sense to me.
> 
> <snip>

Regards,
Cristian

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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-03-29 16:24       ` Dumitrescu, Cristian
@ 2021-04-01 13:13         ` Ori Kam
  2021-04-01 13:35           ` Dumitrescu, Cristian
  0 siblings, 1 reply; 78+ messages in thread
From: Ori Kam @ 2021-04-01 13:13 UTC (permalink / raw)
  To: Dumitrescu, Cristian, Matan Azrad, Li Zhang, Dekel Peled,
	Slava Ovsiienko, Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Jerin Jacob, Hemant Agrawal, Ajit Khaparde
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai

Hi Cristian,

> -----Original Message-----
> From: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Hi Ori,
> 
> > -----Original Message-----
> > From: Ori Kam <orika@nvidia.com>
> > Hi All,
> >
> > > -----Original Message-----
> > > From: Matan Azrad <matan@nvidia.com>
> > > Subject: RE: [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
> > >
> > > Hi Cristian
> > >
> > > Thank you for your important review!
> > > I agree with all your comments except one, please see inline.
> > >
> > > From: Dumitrescu, Cristian
> > > > Hi Li and Matan,
> > > >
> > > > Thank you for your proposal, some comments below.
> > > >
> > > > I am also adding Jerin and Hemant to this thread, as they also
> participated
> > in
> > > > the definition of the rte_mtr API in 2017. Also Ajit expressed some
> > interest in
> > > a
> > > > previous email.
> > > >
> > > > > -----Original Message-----
> > > > > From: Li Zhang <lizh@nvidia.com>
> > > > > Sent: Thursday, March 18, 2021 8:58 AM
> > > > > To: dekelp@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> > > > > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com; Singh,
> > > > > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > > > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>;
> > Andrew
> > > > > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu, Cristian
> > > > > <cristian.dumitrescu@intel.com>
> > > > > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > > > > Subject: [PATCH 1/2] [RFC]: 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 - no action, yellow - no action, red - drop
> > > > >
> > > > > Allow coloring the packet using a new rte_flow_action_color as could
> > > > > be done by the old policy API,
> > > > >
> > > >
> > > > The proposal essentially is to define the meter policy based on rte_flow
> > > actions
> > > > rather than a reduced action set defined specifically just for meter object.
> > > This
> > > > makes sense to me.
> > > >
> > > > > The next API function were added:
> > > > > - rte_mtr_meter_policy_add
> > > > > - 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
> > > > >
> > > > > Signed-off-by: Li Zhang <lizh@nvidia.com>
> > > > > ---
> > > > >  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 |  45 ++++++--
> > > > >  4 files changed, 210 insertions(+), 74 deletions(-)
> > > > >
> > > > > diff --git a/lib/librte_ethdev/rte_flow.h
> > > > > b/lib/librte_ethdev/rte_flow.h index 669e677e91..5f38aa7fa4 100644
> > > > > --- a/lib/librte_ethdev/rte_flow.h
> > > > > +++ b/lib/librte_ethdev/rte_flow.h
> > > > > @@ -31,6 +31,7 @@
> > > > >  #include <rte_ecpri.h>
> > > > >  #include <rte_mbuf.h>
> > > > >  #include <rte_mbuf_dyn.h>
> > > > > +#include <rte_meter.h>
> > > > >
> > > > >  #ifdef __cplusplus
> > > > >  extern "C" {
> > > > > @@ -2236,6 +2237,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_COlOR,
> > > >
> > > > Typo here, it should be RTE_FLOW_ACTION_TYPE_COLOR.
> > > >
> >
> > Why do we need this action?
> 
> We need this new proposed RTE_FLOW_ACTION_TYPE_COLOR action to set the
> packet color in the packet mbuf (i.e. in the mbuf::sched:color field) in order to
> tell the later stages of the pipeline what the packet color is.
> 
> > if it is to save the color it should be done by using mark/metadata
> 
> As stated in its description, the  RTE_FLOW_ACTION_TYPE_MARK action Is
> setting the mbuf::hash.fdir.hi field, which is used for a different purpose that is
> unrelated to the packet color, which has its own field within the mbuf.
> 

Agree,

> > Or by the action of meter.
> 
> The new proposed RTE_FLOW_ACTION_TYPE_COLOR action is indeed an action
> of the meter and meter only, right?
> 
> For example you can see
> > RTE_FLOW_ACTION_TYPE_SECURITY
> > Which if exist saves the session id to a dedicated mbuf field.
> >
> 
> The meter processing and action take place independently of the security API: it
> can be enabled when the security API is disabled and is not conditioned in any
> way by the security API. To be honest, I don't understand the connection with
> the security API that you are trying to make here.
> 

Sorry for not being clear,
I didn’t mean use the security action, what I meant is just like the security action
which when given, it will saves the session and pass it to the SW in dedicated member in the 
mbuf, the same with meter if the meter action is present then
the PMD should know to save the color value and extract it to the correct mbuf member.

Does that make sense?


> > > > >  };
> > > > >
> > > > >  /**
> >
> > [Snip]
> >
> > > > I suggest you do not redundantly specify the value of the default policy ID
> > in
> > > the
> > > > comment. Replace by "Default policy ID."
> > > >
> > > > > + * Action per color as below:
> > > > > + * green - no action, yellow - no action, red - drop
> > > >
> > > > This does not make sense to me as the default policy. The default policy
> > > should
> > > > be "no change", i.e. green -> green (no change), yellow -> yellow (no
> > change),
> > > > red -> red (no change).
> > >
> > > Can you explain why it doesn't make sense to you?
> > >
> > > Meter with "no change" for all colors has no effect on the packets so it is
> > > redundant action which just costs performance and resources - probably
> > never
> > > be used.
> > >
> > > The most common usage for meter is to drop all the packets come above
> > the
> > > defined rate limit - so it makes sense to take this behavior as default.
> > >
> > >
> > > > I suggest we avoid the "no action" statement, as it might be confusing.
> > >
> > > Maybe "do nothing" is better?
> > >
> > Maybe passthrough? Or in rte_flow passthru
> >
> 
> No, we need to save the packet color in the packet mbuf (mbuf::sched:color),
> and the RTE_FLOW_ACTION_TYPE_PASSTHRU action is not doing this.
> 

Please see my comment above.
The saving of color will be done automatically.

> >
> > > > > + * It can be used without creating it by the rte_mtr_meter_policy_add
> > > > > function.
> > > > > + */
> >
> >
> > Best,
> > Ori
> 
> Regards,
> Cristian

Best,
Ori

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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-04-01 13:13         ` Ori Kam
@ 2021-04-01 13:35           ` Dumitrescu, Cristian
  2021-04-01 14:22             ` Ori Kam
  0 siblings, 1 reply; 78+ messages in thread
From: Dumitrescu, Cristian @ 2021-04-01 13:35 UTC (permalink / raw)
  To: Ori Kam, Matan Azrad, Li Zhang, Dekel Peled, Slava Ovsiienko,
	Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Jerin Jacob, Hemant Agrawal, Ajit Khaparde
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai

Hi Ori,

> -----Original Message-----
> From: Ori Kam <orika@nvidia.com>
> Sent: Thursday, April 1, 2021 2:14 PM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; Matan Azrad
> <matan@nvidia.com>; Li Zhang <lizh@nvidia.com>; Dekel Peled
> <dekelp@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; Shahaf
> Shuler <shahafs@nvidia.com>; lironh@marvell.com; Singh, Jasvinder
> <jasvinder.singh@intel.com>; NBU-Contact-Thomas Monjalon
> <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> Rybchenko <andrew.rybchenko@oktetlabs.ru>; Jerin Jacob
> <jerinjacobk@gmail.com>; Hemant Agrawal <hemant.agrawal@nxp.com>;
> Ajit Khaparde <ajit.khaparde@broadcom.com>
> Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar Yanai
> <roniba@nvidia.com>
> Subject: RE: [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
> 
> Hi Cristian,
> 
> > -----Original Message-----
> > From: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> > Hi Ori,
> >
> > > -----Original Message-----
> > > From: Ori Kam <orika@nvidia.com>
> > > Hi All,
> > >
> > > > -----Original Message-----
> > > > From: Matan Azrad <matan@nvidia.com>
> > > > Subject: RE: [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy
> API
> > > >
> > > > Hi Cristian
> > > >
> > > > Thank you for your important review!
> > > > I agree with all your comments except one, please see inline.
> > > >
> > > > From: Dumitrescu, Cristian
> > > > > Hi Li and Matan,
> > > > >
> > > > > Thank you for your proposal, some comments below.
> > > > >
> > > > > I am also adding Jerin and Hemant to this thread, as they also
> > participated
> > > in
> > > > > the definition of the rte_mtr API in 2017. Also Ajit expressed some
> > > interest in
> > > > a
> > > > > previous email.
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Li Zhang <lizh@nvidia.com>
> > > > > > Sent: Thursday, March 18, 2021 8:58 AM
> > > > > > To: dekelp@nvidia.com; orika@nvidia.com;
> viacheslavo@nvidia.com;
> > > > > > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com;
> Singh,
> > > > > > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > > > > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>;
> > > Andrew
> > > > > > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu,
> Cristian
> > > > > > <cristian.dumitrescu@intel.com>
> > > > > > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > > > > > Subject: [PATCH 1/2] [RFC]: 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 - no action, yellow - no action, red - drop
> > > > > >
> > > > > > Allow coloring the packet using a new rte_flow_action_color as
> could
> > > > > > be done by the old policy API,
> > > > > >
> > > > >
> > > > > The proposal essentially is to define the meter policy based on
> rte_flow
> > > > actions
> > > > > rather than a reduced action set defined specifically just for meter
> object.
> > > > This
> > > > > makes sense to me.
> > > > >
> > > > > > The next API function were added:
> > > > > > - rte_mtr_meter_policy_add
> > > > > > - 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
> > > > > >
> > > > > > Signed-off-by: Li Zhang <lizh@nvidia.com>
> > > > > > ---
> > > > > >  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 |  45 ++++++--
> > > > > >  4 files changed, 210 insertions(+), 74 deletions(-)
> > > > > >
> > > > > > diff --git a/lib/librte_ethdev/rte_flow.h
> > > > > > b/lib/librte_ethdev/rte_flow.h index 669e677e91..5f38aa7fa4
> 100644
> > > > > > --- a/lib/librte_ethdev/rte_flow.h
> > > > > > +++ b/lib/librte_ethdev/rte_flow.h
> > > > > > @@ -31,6 +31,7 @@
> > > > > >  #include <rte_ecpri.h>
> > > > > >  #include <rte_mbuf.h>
> > > > > >  #include <rte_mbuf_dyn.h>
> > > > > > +#include <rte_meter.h>
> > > > > >
> > > > > >  #ifdef __cplusplus
> > > > > >  extern "C" {
> > > > > > @@ -2236,6 +2237,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_COlOR,
> > > > >
> > > > > Typo here, it should be RTE_FLOW_ACTION_TYPE_COLOR.
> > > > >
> > >
> > > Why do we need this action?
> >
> > We need this new proposed RTE_FLOW_ACTION_TYPE_COLOR action to
> set the
> > packet color in the packet mbuf (i.e. in the mbuf::sched:color field) in order
> to
> > tell the later stages of the pipeline what the packet color is.
> >
> > > if it is to save the color it should be done by using mark/metadata
> >
> > As stated in its description, the  RTE_FLOW_ACTION_TYPE_MARK action Is
> > setting the mbuf::hash.fdir.hi field, which is used for a different purpose
> that is
> > unrelated to the packet color, which has its own field within the mbuf.
> >
> 
> Agree,
> 
> > > Or by the action of meter.
> >
> > The new proposed RTE_FLOW_ACTION_TYPE_COLOR action is indeed an
> action
> > of the meter and meter only, right?
> >
> > For example you can see
> > > RTE_FLOW_ACTION_TYPE_SECURITY
> > > Which if exist saves the session id to a dedicated mbuf field.
> > >
> >
> > The meter processing and action take place independently of the security
> API: it
> > can be enabled when the security API is disabled and is not conditioned in
> any
> > way by the security API. To be honest, I don't understand the connection
> with
> > the security API that you are trying to make here.
> >
> 
> Sorry for not being clear,
> I didn’t mean use the security action, what I meant is just like the security
> action
> which when given, it will saves the session and pass it to the SW in dedicated
> member in the
> mbuf, the same with meter if the meter action is present then
> the PMD should know to save the color value and extract it to the correct
> mbuf member.
> 
> Does that make sense?
> 

Yes, I does, I guess we are using the same principle for the proposed RTE_FLOW_ACTION_TYPE_COLOR action, right?

> 
> > > > > >  };
> > > > > >
> > > > > >  /**
> > >
> > > [Snip]
> > >
> > > > > I suggest you do not redundantly specify the value of the default
> policy ID
> > > in
> > > > the
> > > > > comment. Replace by "Default policy ID."
> > > > >
> > > > > > + * Action per color as below:
> > > > > > + * green - no action, yellow - no action, red - drop
> > > > >
> > > > > This does not make sense to me as the default policy. The default
> policy
> > > > should
> > > > > be "no change", i.e. green -> green (no change), yellow -> yellow (no
> > > change),
> > > > > red -> red (no change).
> > > >
> > > > Can you explain why it doesn't make sense to you?
> > > >
> > > > Meter with "no change" for all colors has no effect on the packets so it
> is
> > > > redundant action which just costs performance and resources -
> probably
> > > never
> > > > be used.
> > > >
> > > > The most common usage for meter is to drop all the packets come
> above
> > > the
> > > > defined rate limit - so it makes sense to take this behavior as default.
> > > >
> > > >
> > > > > I suggest we avoid the "no action" statement, as it might be
> confusing.
> > > >
> > > > Maybe "do nothing" is better?
> > > >
> > > Maybe passthrough? Or in rte_flow passthru
> > >
> >
> > No, we need to save the packet color in the packet mbuf
> (mbuf::sched:color),
> > and the RTE_FLOW_ACTION_TYPE_PASSTHRU action is not doing this.
> >
> 
> Please see my comment above.
> The saving of color will be done automatically.

The "automatically" part might be the problem for some apps, like the one Matan is describing.

If for example all that user wants is to drop all the RED packets immediately with no need to consider the packet color later in the CPU app, then the user policy is simply: [GREEN => pass-through; YELLOW => pass-through; RED => drop] with no need to use the RTE_FLOW_ACTION_TYPE_COLOR action to set the color in the mbuf::sched::color field, as the app does not need to know the color. This is the use-case described by Matan.

If for example the user utilizes the packet color on the CPU app as the packet drop priority in case of congestion, then the user policy is simply: [GREEN => color; YELLOW => color; RED => color], so the RTE_FLOW_ACTION_TYPE_COLOR action is used to set the color in the mbuf::sched:color field. This is the use-case I described in earlier emails.

So it is probably the best option to have the user to explicitly set / not set the RTE_FLOW_ACTION_TYPE_COLOR action as opposed to have this action always executed automatically/implicitly.

Makes sense?

> 
> > >
> > > > > > + * It can be used without creating it by the
> rte_mtr_meter_policy_add
> > > > > > function.
> > > > > > + */
> > >
> > >
> > > Best,
> > > Ori
> >
> > Regards,
> > Cristian
> 
> Best,
> Ori

Regards,
Cristian

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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-04-01 13:35           ` Dumitrescu, Cristian
@ 2021-04-01 14:22             ` Ori Kam
  0 siblings, 0 replies; 78+ messages in thread
From: Ori Kam @ 2021-04-01 14:22 UTC (permalink / raw)
  To: Dumitrescu, Cristian, Matan Azrad, Li Zhang, Slava Ovsiienko,
	Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Jerin Jacob, Hemant Agrawal, Ajit Khaparde
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai

Hi Cristian,


> -----Original Message-----
> From: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> 
> Hi Ori,
> 
> > -----Original Message-----
> > From: Ori Kam <orika@nvidia.com>
> > Hi Cristian,
> >
> > > -----Original Message-----
> > > From: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> > > Hi Ori,
> > >
> > > > -----Original Message-----
> > > > From: Ori Kam <orika@nvidia.com>
> > > > Hi All,
> > > >
> > > > > -----Original Message-----
> > > > > From: Matan Azrad <matan@nvidia.com>
> > > > > Subject: RE: [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy
> > API
> > > > >
> > > > > Hi Cristian
> > > > >
> > > > > Thank you for your important review!
> > > > > I agree with all your comments except one, please see inline.
> > > > >
> > > > > From: Dumitrescu, Cristian
> > > > > > Hi Li and Matan,
> > > > > >
> > > > > > Thank you for your proposal, some comments below.
> > > > > >
> > > > > > I am also adding Jerin and Hemant to this thread, as they also
> > > participated
> > > > in
> > > > > > the definition of the rte_mtr API in 2017. Also Ajit expressed some
> > > > interest in
> > > > > a
> > > > > > previous email.
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Li Zhang <lizh@nvidia.com>
> > > > > > > Sent: Thursday, March 18, 2021 8:58 AM
> > > > > > > To: dekelp@nvidia.com; orika@nvidia.com;
> > viacheslavo@nvidia.com;
> > > > > > > matan@nvidia.com; shahafs@nvidia.com; lironh@marvell.com;
> > Singh,
> > > > > > > Jasvinder <jasvinder.singh@intel.com>; Thomas Monjalon
> > > > > > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>;
> > > > Andrew
> > > > > > > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu,
> > Cristian
> > > > > > > <cristian.dumitrescu@intel.com>
> > > > > > > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > > > > > > Subject: [PATCH 1/2] [RFC]: 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 - no action, yellow - no action, red - drop
> > > > > > >
> > > > > > > Allow coloring the packet using a new rte_flow_action_color as
> > could
> > > > > > > be done by the old policy API,
> > > > > > >
> > > > > >
> > > > > > The proposal essentially is to define the meter policy based on
> > rte_flow
> > > > > actions
> > > > > > rather than a reduced action set defined specifically just for meter
> > object.
> > > > > This
> > > > > > makes sense to me.
> > > > > >
> > > > > > > The next API function were added:
> > > > > > > - rte_mtr_meter_policy_add
> > > > > > > - 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
> > > > > > >
> > > > > > > Signed-off-by: Li Zhang <lizh@nvidia.com>
> > > > > > > ---
> > > > > > >  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 |  45 ++++++--
> > > > > > >  4 files changed, 210 insertions(+), 74 deletions(-)
> > > > > > >
> > > > > > > diff --git a/lib/librte_ethdev/rte_flow.h
> > > > > > > b/lib/librte_ethdev/rte_flow.h index 669e677e91..5f38aa7fa4
> > 100644
> > > > > > > --- a/lib/librte_ethdev/rte_flow.h
> > > > > > > +++ b/lib/librte_ethdev/rte_flow.h
> > > > > > > @@ -31,6 +31,7 @@
> > > > > > >  #include <rte_ecpri.h>
> > > > > > >  #include <rte_mbuf.h>
> > > > > > >  #include <rte_mbuf_dyn.h>
> > > > > > > +#include <rte_meter.h>
> > > > > > >
> > > > > > >  #ifdef __cplusplus
> > > > > > >  extern "C" {
> > > > > > > @@ -2236,6 +2237,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_COlOR,
> > > > > >
> > > > > > Typo here, it should be RTE_FLOW_ACTION_TYPE_COLOR.
> > > > > >
> > > >
> > > > Why do we need this action?
> > >
> > > We need this new proposed RTE_FLOW_ACTION_TYPE_COLOR action to
> > set the
> > > packet color in the packet mbuf (i.e. in the mbuf::sched:color field) in order
> > to
> > > tell the later stages of the pipeline what the packet color is.
> > >
> > > > if it is to save the color it should be done by using mark/metadata
> > >
> > > As stated in its description, the  RTE_FLOW_ACTION_TYPE_MARK action Is
> > > setting the mbuf::hash.fdir.hi field, which is used for a different purpose
> > that is
> > > unrelated to the packet color, which has its own field within the mbuf.
> > >
> >
> > Agree,
> >
> > > > Or by the action of meter.
> > >
> > > The new proposed RTE_FLOW_ACTION_TYPE_COLOR action is indeed an
> > action
> > > of the meter and meter only, right?
> > >
> > > For example you can see
> > > > RTE_FLOW_ACTION_TYPE_SECURITY
> > > > Which if exist saves the session id to a dedicated mbuf field.
> > > >
> > >
> > > The meter processing and action take place independently of the security
> > API: it
> > > can be enabled when the security API is disabled and is not conditioned in
> > any
> > > way by the security API. To be honest, I don't understand the connection
> > with
> > > the security API that you are trying to make here.
> > >
> >
> > Sorry for not being clear,
> > I didn’t mean use the security action, what I meant is just like the security
> > action
> > which when given, it will saves the session and pass it to the SW in dedicated
> > member in the
> > mbuf, the same with meter if the meter action is present then
> > the PMD should know to save the color value and extract it to the correct
> > mbuf member.
> >
> > Does that make sense?
> >
> 
> Yes, I does, I guess we are using the same principle for the proposed
> RTE_FLOW_ACTION_TYPE_COLOR action, right?
> 

Just to make sure we are talking about the same thing.
I don't think we should add any new action for this.
My idea is that when the PMD will see the action RTE_FLOW_ACTION_TYPE_METER,
it will send the traffic to the meter, and will also in the of case the packet being
routed to the application will update the color member in the mbuf with color value.

> >
> > > > > > >  };
> > > > > > >
> > > > > > >  /**
> > > >
> > > > [Snip]
> > > >
> > > > > > I suggest you do not redundantly specify the value of the default
> > policy ID
> > > > in
> > > > > the
> > > > > > comment. Replace by "Default policy ID."
> > > > > >
> > > > > > > + * Action per color as below:
> > > > > > > + * green - no action, yellow - no action, red - drop
> > > > > >
> > > > > > This does not make sense to me as the default policy. The default
> > policy
> > > > > should
> > > > > > be "no change", i.e. green -> green (no change), yellow -> yellow (no
> > > > change),
> > > > > > red -> red (no change).
> > > > >
> > > > > Can you explain why it doesn't make sense to you?
> > > > >
> > > > > Meter with "no change" for all colors has no effect on the packets so it
> > is
> > > > > redundant action which just costs performance and resources -
> > probably
> > > > never
> > > > > be used.
> > > > >
> > > > > The most common usage for meter is to drop all the packets come
> > above
> > > > the
> > > > > defined rate limit - so it makes sense to take this behavior as default.
> > > > >
> > > > >
> > > > > > I suggest we avoid the "no action" statement, as it might be
> > confusing.
> > > > >
> > > > > Maybe "do nothing" is better?
> > > > >
> > > > Maybe passthrough? Or in rte_flow passthru
> > > >
> > >
> > > No, we need to save the packet color in the packet mbuf
> > (mbuf::sched:color),
> > > and the RTE_FLOW_ACTION_TYPE_PASSTHRU action is not doing this.
> > >
> >
> > Please see my comment above.
> > The saving of color will be done automatically.
> 
> The "automatically" part might be the problem for some apps, like the one
> Matan is describing.
> 
> If for example all that user wants is to drop all the RED packets immediately
> with no need to consider the packet color later in the CPU app, then the user
> policy is simply: [GREEN => pass-through; YELLOW => pass-through; RED =>
> drop] with no need to use the RTE_FLOW_ACTION_TYPE_COLOR action to set
> the color in the mbuf::sched::color field, as the app does not need to know the
> color. This is the use-case described by Matan.
> 
> If for example the user utilizes the packet color on the CPU app as the packet
> drop priority in case of congestion, then the user policy is simply: [GREEN =>
> color; YELLOW => color; RED => color], so the
> RTE_FLOW_ACTION_TYPE_COLOR action is used to set the color in the
> mbuf::sched:color field. This is the use-case I described in earlier emails.
> 
> So it is probably the best option to have the user to explicitly set / not set the
> RTE_FLOW_ACTION_TYPE_COLOR action as opposed to have this action always
> executed automatically/implicitly.
> 
> Makes sense?
> 

I think I understand what you are saying but I don't agree,
First I assume that the meter color is dynamic field, if not the
answer will need some small change.
lets look at the use cases:
1. The first case of direct drop:
The PMD  sees that the dynamic color was not registered so it knows
not to same or update the field.
2. Second case the app register the color field and the pmd
knows that it needs to save it when meter action was set.

In any case the worst that will happen is that the PMD will store a value that
will not be checked.

Also adding a color action makes sense only if I can match on it later on, and for that
we have registers tags,mark and metadata.

Another approach is to totally remove the policy and just create mtr_color_item,
Then when application issues the meter action the color will be set to the color_item
Which the application will be able to match on. 
basically the application will create the policy using rte flow group with rules that matches
the color.

This is the way I really think it should be done, but we can move to this way later on.

 

> >
> > > >
> > > > > > > + * It can be used without creating it by the
> > rte_mtr_meter_policy_add
> > > > > > > function.
> > > > > > > + */
> > > >
> > > >
> > > > Best,
> > > > Ori
> > >
> > > Regards,
> > > Cristian
> >
> > Best,
> > Ori
> 
> Regards,
> Cristian

Best,
Ori

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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-03-31 15:46         ` Dumitrescu, Cristian
@ 2021-04-04 13:48           ` Matan Azrad
  0 siblings, 0 replies; 78+ messages in thread
From: Matan Azrad @ 2021-04-04 13:48 UTC (permalink / raw)
  To: Dumitrescu, Cristian, Li Zhang, Dekel Peled, Ori Kam,
	Slava Ovsiienko, Shahaf Shuler, lironh, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Yigit, Ferruh, Andrew Rybchenko,
	Jerin Jacob, Hemant Agrawal, Ajit Khaparde
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai


Hi Cristian

From: Dumitrescu, Cristian
> Hi Matan,
> 
> > -----Original Message-----
> > From: Matan Azrad <matan@nvidia.com>
> > Sent: Monday, March 29, 2021 9:44 PM
> > To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; Li Zhang
> > <lizh@nvidia.com>; Dekel Peled <dekelp@nvidia.com>; Ori Kam
> > <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; Shahaf
> > Shuler <shahafs@nvidia.com>; lironh@marvell.com; Singh, Jasvinder
> > <jasvinder.singh@intel.com>; NBU-Contact-Thomas Monjalon
> > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Jerin Jacob
> > <jerinjacobk@gmail.com>; Hemant Agrawal <hemant.agrawal@nxp.com>;
> Ajit
> > Khaparde <ajit.khaparde@broadcom.com>
> > Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar
> > Yanai <roniba@nvidia.com>
> > Subject: RE: [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy
> > API
> >
> >
> >
> > From: Dumitrescu, Cristian
> > > Hi Matan,
> > >
> > > > -----Original Message-----
> > > > From: Matan Azrad <matan@nvidia.com>
> > > > Sent: Thursday, March 25, 2021 6:57 AM
> > > > To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; Li Zhang
> > > > <lizh@nvidia.com>; Dekel Peled <dekelp@nvidia.com>; Ori Kam
> > > > <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>;
> > > > Shahaf Shuler <shahafs@nvidia.com>; lironh@marvell.com; Singh,
> > > > Jasvinder <jasvinder.singh@intel.com>; NBU-Contact-Thomas Monjalon
> > > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>;
> > Andrew
> > > > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Jerin Jacob
> > > > <jerinjacobk@gmail.com>; Hemant Agrawal
> > <hemant.agrawal@nxp.com>;
> > > Ajit
> > > > Khaparde <ajit.khaparde@broadcom.com>
> > > > Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar
> > > > Yanai <roniba@nvidia.com>
> > > > Subject: RE: [PATCH 1/2] [RFC]: ethdev: add pre-defined meter
> > > > policy API
> > > >
> > > > Hi Cristian
> > > >
> > > > Thank you for your important review!
> > > > I agree with all your comments except one, please see inline.
> > > >
> > > > From: Dumitrescu, Cristian
> > > > > Hi Li and Matan,
> > > > >
> > > > > Thank you for your proposal, some comments below.
> > > > >
> > > > > I am also adding Jerin and Hemant to this thread, as they also
> > > > > participated
> > > > in
> > > > > the definition of the rte_mtr API in 2017. Also Ajit expressed
> > > > > some interest
> > > > in a
> > > > > previous email.
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Li Zhang <lizh@nvidia.com>
> > > > > > Sent: Thursday, March 18, 2021 8:58 AM
> > > > > > To: dekelp@nvidia.com; orika@nvidia.com;
> > > > > > viacheslavo@nvidia.com; matan@nvidia.com; shahafs@nvidia.com;
> > > > > > lironh@marvell.com; Singh, Jasvinder
> > > > > > <jasvinder.singh@intel.com>; Thomas Monjalon
> > > > > > <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>;
> > > > Andrew
> > > > > > Rybchenko <andrew.rybchenko@oktetlabs.ru>; Dumitrescu,
> > > > > > Cristian <cristian.dumitrescu@intel.com>
> > > > > > Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com
> > > > > > Subject: [PATCH 1/2] [RFC]: 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 - no action, yellow - no action, red - drop
> > > > > >
> > > > > > Allow coloring the packet using a new rte_flow_action_color as
> > > > > > could be done by the old policy API,
> > > > > >
> > > > >
> > > > > The proposal essentially is to define the meter policy based on
> > > > > rte_flow
> > > > actions
> > > > > rather than a reduced action set defined specifically just for
> > > > > meter
> > object.
> > > > This
> > > > > makes sense to me.
> > > > >
> > > > > > The next API function were added:
> > > > > > - rte_mtr_meter_policy_add
> > > > > > - 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
> > > > > >
> > > > > > Signed-off-by: Li Zhang <lizh@nvidia.com>
> > > > > > ---
> > > > > >  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 |  45 ++++++--
> > > > > >  4 files changed, 210 insertions(
> > <snip>
> > > > > > +/**
> > > > > > + * Policy id 0 is default policy.
> > > > >
> > > > > I suggest you do not redundantly specify the value of the
> > > > > default policy ID
> > > > in the
> > > > > comment. Replace by "Default policy ID."
> > > > >
> > > > > > + * Action per color as below:
> > > > > > + * green - no action, yellow - no action, red - drop
> > > > >
> > > > > This does not make sense to me as the default policy. The
> > > > > default policy
> > > > should
> > > > > be "no change", i.e. green -> green (no change), yellow ->
> > > > > yellow (no
> > > > change),
> > > > > red -> red (no change).
> > > >
> > > > Can you explain why it doesn't make sense to you?
> > > >
> > > > Meter with "no change" for all colors has no effect on the packets
> > > > so it is redundant action which just costs performance and
> > > > resources - probably never be used.
> > > >
> > >
> > > The mbuf::sched::color needs to be set for the packet, and the only
> > > way to
> > do
> > > this is by applying the RTE_FLOW_ACTION_TYPE_COLOR Action, right? It
> > would
> > > make sense that the default policy is to simply apply to the packet
> > > the color that the meter just computed for the current packet with no
> change, right?
> >
> > I don't think so.
> > When we are working with HW offloads (this is the main goal of
> > rte_flow and this meter API) the motivation is to do the actions directly in the
> NIC HW.
> > Moving the color information to the SW is like doing "partial offload".
> >
> 
> Sorry, Matan, but as the bulk of the packets are passed by the NIC to the CPU as
> opposed to being returned to the network without the CPU ever seeing them,
> the rte_flow API is a partial offload API, not a full offload API, not sure why we
> disagree here.
> 

I said that the direction is to do "full offload", for sure "partial offload" is exists too, using MARK, METADATA, etc.. actions.
Example for "full offload" is all the hairpin features, added lastly.


> Just to make sure we are on the same page and not getting round in circles: I
> think you agree that we should have this action
> RTE_FLOW_ACTION_TYPE_COLOR to setup the color for the CPU to see in
> mbuf::sched:color, but you don't agree this action should be part of the default
> policy, did I get your position correctly?

Yes.

> >
> > > > The most common usage for meter is to drop all the packets come
> > > > above the defined rate limit - so it makes sense to take this behavior as
> default.
> > > >
> > >
> > > I don't agree with this assertion either. One typical usage of the
> > > color is to accept all input packets from the user, either green,
> > > yellow or red in the absence of any congestion, and charge the user
> > > for this traffic; in case of congestion, as typically detected later
> > > (typically on scheduling and maybe
> > on a
> > > different network node, depending on the application), the packet
> > > color is
> > used
> > > to prioritize between packets, i.e. drop red packets first before
> > > dropping
> > any
> > > yellow or green packets. In this case, there is no pre-defined "drop
> > > all red packets straight away" policy.
> >
> >
> > I familiar with a lot of meter users(at least 5 applications) in the
> > industry, no one use the color actions.
> > All of them drop red packets and continue to the next flow
> > actions(after
> > meter) otherwise.
> >
> 
> I politely but firmly disagree. None of the apps that I have seen is dropping the
> red packets straight away, they simply use the color as an indication of the
> packet drop priority at a later stage in the pipeline when congestion is
> detected.
> 
> >
> > If you insist, we can define 2 default IDs...
> >
> 
> Maybe we should not have any pre-registered policies at all?
> 

OK, for that.

> For the user's convenience, we could provide the configuration parameters for
> some of the common policies, like the ones mentioned here, in the API and let
> the users decide which one(s), if any, they want to register?

Good direction
I think it is better to give these 2 examples in the policy create\validate description or in example application,
Then the user just can copy it to create a policy....

> > > >
> > > > > I suggest we avoid the "no action" statement, as it might be confusing.
> > > >
> > > > Maybe "do nothing" is better?
> > > >
> > >
> > > Yes, makes sense to me.
> >
> > <snip>
> 
> Regards,
> Cristian

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

* [dpdk-dev] [PATCH v3 0/2] Support meter policy API
  2021-03-18  8:58 [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API Li Zhang
                   ` (2 preceding siblings ...)
  2021-03-29 10:38 ` Jerin Jacob
@ 2021-04-13  0:14 ` Li Zhang
  2021-04-13  0:14   ` [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined " Li Zhang
  2021-04-13  0:14   ` [dpdk-dev] [PATCH v3 2/2] app/testpmd: support policy actions per color Li Zhang
  2021-04-14  3:12 ` [dpdk-dev] [PATCH v4 0/2] Support meter policy API Li Zhang
                   ` (5 subsequent siblings)
  9 siblings, 2 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-13  0:14 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/

Depends-on: series=16300  ("Add ASO meter support in MLX5 PMD ")
https://patchwork.dpdk.org/project/dpdk/list/?series=16300

V2: Delete default policy and change relation doc files.
V3: Fix coding style issues.

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                        |  14 +-
 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                         |  32 ++
 app/test-pmd/testpmd.h                        |   2 +
 doc/guides/prog_guide/rte_flow.rst            |  21 +
 .../traffic_metering_and_policing.rst         |  16 +-
 doc/guides/rel_notes/release_21_05.rst        |  22 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  48 +-
 drivers/net/mlx5/mlx5.h                       |  24 +-
 drivers/net/mlx5/mlx5_flow.c                  |  46 --
 drivers/net/mlx5/mlx5_flow.h                  |  18 +-
 drivers/net/mlx5/mlx5_flow_aso.c              |   8 +-
 drivers/net/mlx5/mlx5_flow_dv.c               | 461 +-----------------
 drivers/net/mlx5/mlx5_flow_meter.c            | 369 +-------------
 drivers/net/softnic/rte_eth_softnic_flow.c    |  19 +-
 .../net/softnic/rte_eth_softnic_internals.h   |  18 +-
 drivers/net/softnic/rte_eth_softnic_meter.c   | 264 +++++++---
 lib/librte_ethdev/rte_flow.h                  |  22 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 215 ++++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   5 +-
 25 files changed, 837 insertions(+), 1272 deletions(-)

-- 
2.27.0


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

* [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy API
  2021-04-13  0:14 ` [dpdk-dev] [PATCH v3 0/2] Support " Li Zhang
@ 2021-04-13  0:14   ` Li Zhang
  2021-04-13 14:19     ` Dumitrescu, Cristian
                       ` (2 more replies)
  2021-04-13  0:14   ` [dpdk-dev] [PATCH v3 2/2] app/testpmd: support policy actions per color Li Zhang
  1 sibling, 3 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-13  0:14 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, Jiawei Wang

Currently, the flow meter policy does not support multiple actions
per color; also the allowed action types per color are very limited.
In addition, the policy cannot be pre-defined.

Due to the growing in flow actions offload abilities there is a potential
for the user to use variety of actions per color differently.
This new meter policy API comes to allow this potential in the most ethdev
common way using rte_flow action definition.
A list of rte_flow actions will be provided by the user per color
in order to create a meter policy.
In addition, the API forces to pre-define the policy before
the meters creation in order to allow sharing of single policy
with multiple meters efficiently.

meter_policy_id is added into struct rte_mtr_params.
So that it can get the policy during the meters creation.

Allow coloring the packet using a new rte_flow_action_color
as could be done by the old policy API.

The next API function were added:
- rte_mtr_meter_policy_create
- rte_mtr_meter_policy_delete
- rte_mtr_meter_policy_update
- rte_mtr_meter_policy_validate
The next struct was changed:
- rte_mtr_params
- rte_mtr_capabilities
The next API was deleted:
- rte_mtr_policer_actions_update

To support this API the following app were changed:
app/test-flow-perf: clean meter policer
app/testpmd: clean meter policer

To support this API the following drivers were changed:
net/softnic: support meter policy API
1. cleans meter rte_mtr_policer_action.
2. Support policy API to get color action as policer action did.
   The color action will be mapped into rte_table_action_policer.

net/mlx5: clean meter creation management
Cleans and breaks part of the current meter management
in order to allow better design with policy API.

Signed-off-by: Li Zhang <lizh@nvidia.com>
Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
---
 app/test-flow-perf/main.c                     |   7 -
 app/test-pmd/cmdline.c                        |   1 -
 app/test-pmd/cmdline_mtr.c                    | 172 -------
 app/test-pmd/cmdline_mtr.h                    |   1 -
 doc/guides/prog_guide/rte_flow.rst            |  21 +
 .../traffic_metering_and_policing.rst         |  16 +-
 doc/guides/rel_notes/release_21_05.rst        |  22 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  18 -
 drivers/net/mlx5/mlx5.h                       |  24 +-
 drivers/net/mlx5/mlx5_flow.c                  |  46 --
 drivers/net/mlx5/mlx5_flow.h                  |  18 +-
 drivers/net/mlx5/mlx5_flow_aso.c              |   8 +-
 drivers/net/mlx5/mlx5_flow_dv.c               | 461 +-----------------
 drivers/net/mlx5/mlx5_flow_meter.c            | 369 +-------------
 drivers/net/softnic/rte_eth_softnic_flow.c    |  19 +-
 .../net/softnic/rte_eth_softnic_internals.h   |  18 +-
 drivers/net/softnic/rte_eth_softnic_meter.c   | 264 +++++++---
 lib/librte_ethdev/rte_flow.h                  |  22 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 215 ++++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   5 +-
 22 files changed, 568 insertions(+), 1258 deletions(-)

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


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

* [dpdk-dev] [PATCH v3 2/2] app/testpmd: support policy actions per color
  2021-04-13  0:14 ` [dpdk-dev] [PATCH v3 0/2] Support " Li Zhang
  2021-04-13  0:14   ` [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined " Li Zhang
@ 2021-04-13  0:14   ` Li Zhang
  1 sibling, 0 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-13  0:14 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 create/del policy CLIs to support actions per color.
The CLIs are:
Create:  add port meter policy (port_id) (policy_id) g_actions (actions)
y_actions (actions) r_actions (actions)
Delete:  del port meter policy (port_id) (policy_id)

Examples:
testpmd> add port meter policy 0 1 g_actions rss / end y_actions end
r_actions drop / end
testpmd> del port meter policy 0 1

Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
---
 app/test-pmd/cmdline.c                      |  13 ++-
 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                       |  32 ++++++
 app/test-pmd/testpmd.h                      |   2 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  30 ++++-
 7 files changed, 269 insertions(+), 14 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index fae79d4c85..8940936f84 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -705,9 +705,8 @@ 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"
-			"(g_action) (y_action) (r_action) (stats_mask) (shared)\n"
-			"(use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
+			"create port meter (port_id) (mtr_id) (profile_id) (policy_id) (meter_enable)\n"
+			"(stats_mask) (shared) (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
 			"(dscp_tbl_entry63)]\n"
 			"    meter create\n\n"
 
@@ -720,6 +719,13 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"del port meter (port_id) (mtr_id)\n"
 			"    meter delete\n\n"
 
+			"add port meter policy (port_id) (policy_id) g_actions (actions)\n"
+			"y_actions (actions) r_actions (actions)\n"
+			"    meter policy add\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"
 
@@ -17069,6 +17075,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 fb7a3a8bd3..f50e7312ee 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. */
@@ -808,6 +818,9 @@ struct buffer {
 		struct {
 			int destroy;
 		} aged; /**< Aged arguments. */
+		struct {
+			uint32_t policy_id;
+		} policy;/**< Policy arguments. */
 	} args; /**< Command arguments. */
 };
 
@@ -1785,6 +1798,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);
@@ -1823,7 +1839,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 = "",
@@ -1945,6 +1961,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",
@@ -4528,6 +4551,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. */
@@ -4712,6 +4783,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,
@@ -7685,6 +7797,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..f1d1abc6fb 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,36 @@ 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 *act = actions;
+	const struct rte_flow_action *start;
+	struct rte_mtr_meter_policy_params policy;
+	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)
+			policy.actions[i] = start;
+		else
+			policy.actions[i] = NULL;
+		act++;
+	}
+	ret = rte_mtr_meter_policy_create(port_id,
+			policy_id,
+			&policy, &error);
+	if (ret)
+		print_mtr_err_msg(&error);
+	return ret;
+}
+
 /** 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);
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 3f7a1c0e33..b596ee9a14 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2764,13 +2764,37 @@ Delete meter profile from the ethernet device::
 
    testpmd> del port meter profile (port_id) (profile_id)
 
+create port policy
+~~~~~~~~~~~~~~~~~~
+
+Create new policy object for the ethernet device::
+
+   testpmd> add port meter policy (port_id) (policy_id) g_actions \
+   {action} y_actions {action} r_actions {action}
+
+where:
+
+* ``policy_id``: policy ID.
+* ``action``: action lists for green/yellow/red colors.
+
+delete port policy
+~~~~~~~~~~~~~~~~~~
+
+Delete policy object for the ethernet device::
+
+   testpmd> del port meter policy (port_id) (policy_id)
+
+where:
+
+* ``policy_id``: policy ID.
+
 create port meter
 ~~~~~~~~~~~~~~~~~
 
 Create new meter object for the ethernet device::
 
    testpmd> create port meter (port_id) (mtr_id) (profile_id) \
-   (meter_enable) (g_action) (y_action) (r_action) (stats_mask) (shared) \
+   (policy_id) (meter_enable) (stats_mask) (shared) \
    (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\
    (dscp_tbl_entry63)]
 
@@ -2778,11 +2802,9 @@ where:
 
 * ``mtr_id``: meter object ID.
 * ``profile_id``: ID for the meter profile.
+* ``policy_id``: ID for the policy.
 * ``meter_enable``: When this parameter has a non-zero value, the meter object
   gets enabled at the time of creation, otherwise remains disabled.
-* ``g_action``: Policer action for the packet with green color.
-* ``y_action``: Policer action for the packet with yellow color.
-* ``r_action``: Policer action for the packet with red color.
 * ``stats_mask``: Mask of statistics counter types to be enabled for the
   meter object.
 * ``shared``:  When this parameter has a non-zero value, the meter object is
-- 
2.27.0


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

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy API
  2021-04-13  0:14   ` [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined " Li Zhang
@ 2021-04-13 14:19     ` Dumitrescu, Cristian
  2021-04-14  3:23       ` Li Zhang
  2021-04-13 14:59     ` Dumitrescu, Cristian
  2021-04-13 16:25     ` Kinsella, Ray
  2 siblings, 1 reply; 78+ messages in thread
From: Dumitrescu, Cristian @ 2021-04-13 14:19 UTC (permalink / raw)
  To: Li Zhang, dekelp, orika, viacheslavo, matan, shahafs, lironh,
	Wisam Jaddo, Li, Xiaoyun, Singh, Jasvinder, Thomas Monjalon,
	Yigit, Ferruh, Andrew Rybchenko, Ray Kinsella, Neil Horman,
	Jerin Jacob
  Cc: dev, rasland, roniba, Haifei Luo, Jiawei Wang

Hi Li,

This patch does not apply on top of the latest DPDK. Can you please rebase on top of DPDK version and resend. If this depends on some other patch sets to be applied first, then please send clear steps on how to apply.

Thanks,
Cristian

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

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy API
  2021-04-13  0:14   ` [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined " Li Zhang
  2021-04-13 14:19     ` Dumitrescu, Cristian
@ 2021-04-13 14:59     ` Dumitrescu, Cristian
  2021-04-14  4:55       ` Li Zhang
  2021-04-13 16:25     ` Kinsella, Ray
  2 siblings, 1 reply; 78+ messages in thread
From: Dumitrescu, Cristian @ 2021-04-13 14:59 UTC (permalink / raw)
  To: Li Zhang, dekelp, orika, viacheslavo, matan, shahafs, lironh,
	Wisam Jaddo, Li, Xiaoyun, Singh, Jasvinder, Thomas Monjalon,
	Yigit, Ferruh, Andrew Rybchenko, Ray Kinsella, Neil Horman,
	Jerin Jacob, Hemant Agrawal
  Cc: dev, rasland, roniba, Haifei Luo, Jiawei Wang

Hi Li,

Here are some initial comments while waiting for a new version that applies cleanly.

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

Maybe tweak the explanation a bit: The same policy can be used to create multiple MTR objects.

> + * Two common examples to define meter policy action list:
> + * Example #1: GREEN - GREEN, YELLOW - YELLOW, RED - RED
> + *	struct rte_mtr_meter_policy_params policy_0 =
> + *					(struct
> rte_mtr_meter_policy_params) {
> + *		.actions[RTE_COLOR_GREEN] = (struct rte_flow_action[]) {
> + *			{
> + *				.type =
> RTE_FLOW_ACTION_TYPE_METER_COLOR,
> + *				.conf = &(struct
> rte_flow_action_meter_color) {
> + *					.color = RTE_COLOR_GREEN,
> + *				},
> + *			},
> + *			{
> + *				.type = RTE_FLOW_ACTION_TYPE_END,
> + *			},
> + *		},
> + *		.actions[RTE_COLOR_YELLOW] = (struct rte_flow_action[]) {
> + *			{
> + *				.type =
> RTE_FLOW_ACTION_TYPE_METER_COLOR,
> + *				.conf = &(struct
> rte_flow_action_meter_color) {
> + *					.color = RTE_COLOR_YELLOW,
> + *				},
> + *			},
> + *			{
> + *			.type = RTE_FLOW_ACTION_TYPE_END,
> + *			},
> + *		},
> + *		.actions[RTE_COLOR_RED] = (struct rte_flow_action[]) {
> + *			{
> + *				.type =
> RTE_FLOW_ACTION_TYPE_METER_COLOR,
> + *				.conf = &(struct
> rte_flow_action_meter_color) {
> + *					.color = RTE_COLOR_RED,
> + *				},
> + *			},
> + *			{
> + *				.type = RTE_FLOW_ACTION_TYPE_END,
> + *			},
> + *		},
> + *	};
> + *
> + * Example #2: GREEN - Do nothing, YELLOW - Do nothing, RED - DROP
> + *	struct rte_mtr_meter_policy_params policy_1 =
> + *					(struct
> rte_mtr_meter_policy_params) {
> + *		.actions[RTE_COLOR_GREEN] = NULL,
> + *		.actions[RTE_COLOR_YELLOW] = NULL,
> + *		.actions[RTE_COLOR_RED] = (struct rte_flow_action[]) {
> + *			{
> + *				.type = RTE_FLOW_ACTION_TYPE_DROP,
> + *			},
> + *			{
> + *				.type = RTE_FLOW_ACTION_TYPE_END,
> + *			},
> + *		},
> + *	};
> + *

These two example policies should be available to be used straight away, please make them real data structures, not comments.

I suggest their names as: pass_color_policy_params and drop_red_policy_params.

> + * @param[in] port_id
> + *   The port identifier of the Ethernet device.
> + * @param[in] policy_id
> + *   Policy identifier for the new meter policy.
> + * @param[in] policy
> + *   Associated actions per color.
> + *   list NULL is legal and means no special action.
> + *   Non-NULL list must be terminated.
> + *   (list terminated by the END action).
> + * @param[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +__rte_experimental
> +int
> +rte_mtr_meter_policy_create(uint16_t port_id,

The name of this function at the top of its description is mentioned as "meter policy add", while this function name here is policy create, please align the two.

Since we already have other API functions in this file for profiles/policies with the naming convention of add/delete as opposed to create/destroy (rte_mtr_meter_profile_add  and rte_mtr_meter_profile_delete), please let's use the existing convention and call these ones rte_mtr_meter_policy_add and rte_mtr_meter_policy_delete.

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

Regards,
Cristian

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

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy API
  2021-04-13  0:14   ` [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined " Li Zhang
  2021-04-13 14:19     ` Dumitrescu, Cristian
  2021-04-13 14:59     ` Dumitrescu, Cristian
@ 2021-04-13 16:25     ` Kinsella, Ray
  2 siblings, 0 replies; 78+ messages in thread
From: Kinsella, Ray @ 2021-04-13 16:25 UTC (permalink / raw)
  To: Li Zhang, dekelp, orika, viacheslavo, matan, shahafs,
	cristian.dumitrescu, lironh, Wisam Jaddo, Xiaoyun Li,
	Jasvinder Singh, Thomas Monjalon, Ferruh Yigit, Andrew Rybchenko,
	Neil Horman
  Cc: dev, rasland, roniba, Haifei Luo, Jiawei Wang



On 13/04/2021 01:14, Li Zhang wrote:
> Currently, the flow meter policy does not support multiple actions
> per color; also the allowed action types per color are very limited.
> In addition, the policy cannot be pre-defined.
> 
> Due to the growing in flow actions offload abilities there is a potential
> for the user to use variety of actions per color differently.
> This new meter policy API comes to allow this potential in the most ethdev
> common way using rte_flow action definition.
> A list of rte_flow actions will be provided by the user per color
> in order to create a meter policy.
> In addition, the API forces to pre-define the policy before
> the meters creation in order to allow sharing of single policy
> with multiple meters efficiently.
> 
> meter_policy_id is added into struct rte_mtr_params.
> So that it can get the policy during the meters creation.
> 
> Allow coloring the packet using a new rte_flow_action_color
> as could be done by the old policy API.
> 
> The next API function were added:
> - rte_mtr_meter_policy_create
> - rte_mtr_meter_policy_delete
> - rte_mtr_meter_policy_update
> - rte_mtr_meter_policy_validate
> The next struct was changed:
> - rte_mtr_params
> - rte_mtr_capabilities
> The next API was deleted:
> - rte_mtr_policer_actions_update
> 
> To support this API the following app were changed:
> app/test-flow-perf: clean meter policer
> app/testpmd: clean meter policer
> 
> To support this API the following drivers were changed:
> net/softnic: support meter policy API
> 1. cleans meter rte_mtr_policer_action.
> 2. Support policy API to get color action as policer action did.
>    The color action will be mapped into rte_table_action_policer.
> 
> net/mlx5: clean meter creation management
> Cleans and breaks part of the current meter management
> in order to allow better design with policy API.
> 
> Signed-off-by: Li Zhang <lizh@nvidia.com>
> Signed-off-by: Haifei Luo <haifeil@nvidia.com>
> Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
> Acked-by: Matan Azrad <matan@nvidia.com>
> ---
>  app/test-flow-perf/main.c                     |   7 -
>  app/test-pmd/cmdline.c                        |   1 -
>  app/test-pmd/cmdline_mtr.c                    | 172 -------
>  app/test-pmd/cmdline_mtr.h                    |   1 -
>  doc/guides/prog_guide/rte_flow.rst            |  21 +
>  .../traffic_metering_and_policing.rst         |  16 +-
>  doc/guides/rel_notes/release_21_05.rst        |  22 +-
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  18 -
>  drivers/net/mlx5/mlx5.h                       |  24 +-
>  drivers/net/mlx5/mlx5_flow.c                  |  46 --
>  drivers/net/mlx5/mlx5_flow.h                  |  18 +-
>  drivers/net/mlx5/mlx5_flow_aso.c              |   8 +-
>  drivers/net/mlx5/mlx5_flow_dv.c               | 461 +-----------------
>  drivers/net/mlx5/mlx5_flow_meter.c            | 369 +-------------
>  drivers/net/softnic/rte_eth_softnic_flow.c    |  19 +-
>  .../net/softnic/rte_eth_softnic_internals.h   |  18 +-
>  drivers/net/softnic/rte_eth_softnic_meter.c   | 264 +++++++---
>  lib/librte_ethdev/rte_flow.h                  |  22 +
>  lib/librte_ethdev/rte_mtr.c                   |  55 ++-
>  lib/librte_ethdev/rte_mtr.h                   | 215 ++++++--
>  lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
>  lib/librte_ethdev/version.map                 |   5 +-
>  22 files changed, 568 insertions(+), 1258 deletions(-)
> 


Acked-by: Ray Kinsella <mdr@ashroe.eu>

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

* [dpdk-dev] [PATCH v4 0/2] Support meter policy API
  2021-03-18  8:58 [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API Li Zhang
                   ` (3 preceding siblings ...)
  2021-04-13  0:14 ` [dpdk-dev] [PATCH v3 0/2] Support " Li Zhang
@ 2021-04-14  3:12 ` Li Zhang
  2021-04-14  3:12   ` [dpdk-dev] [PATCH v4 1/2] ethdev: add pre-defined " Li Zhang
  2021-04-14  3:12   ` [dpdk-dev] [PATCH v4 2/2] app/testpmd: support policy actions per color Li Zhang
  2021-04-14  6:32 ` [dpdk-dev] [PATCH v5 0/2] Support meter policy API Li Zhang
                   ` (4 subsequent siblings)
  9 siblings, 2 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-14  3:12 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/

Depends-on: series=16351  ("Add ASO meter support in MLX5 PMD ")
https://patchwork.dpdk.org/project/dpdk/list/?series=16351

V2: Delete default policy and change relation doc files.
V3: Fix coding style issues.
V4: Fix comments.

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                        |  14 +-
 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                         |  32 ++
 app/test-pmd/testpmd.h                        |   2 +
 doc/guides/prog_guide/rte_flow.rst            |  21 +
 .../traffic_metering_and_policing.rst         |  16 +-
 doc/guides/rel_notes/release_21_05.rst        |  22 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  48 +-
 drivers/net/mlx5/mlx5.h                       |  24 +-
 drivers/net/mlx5/mlx5_flow.c                  |  46 --
 drivers/net/mlx5/mlx5_flow.h                  |  18 +-
 drivers/net/mlx5/mlx5_flow_aso.c              |   8 +-
 drivers/net/mlx5/mlx5_flow_dv.c               | 461 +-----------------
 drivers/net/mlx5/mlx5_flow_meter.c            | 369 +-------------
 drivers/net/softnic/rte_eth_softnic_flow.c    |  19 +-
 .../net/softnic/rte_eth_softnic_internals.h   |  18 +-
 drivers/net/softnic/rte_eth_softnic_meter.c   | 264 +++++++---
 lib/librte_ethdev/rte_flow.h                  |  22 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 215 ++++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   5 +-
 25 files changed, 837 insertions(+), 1272 deletions(-)

-- 
2.27.0


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

* [dpdk-dev] [PATCH v4 1/2] ethdev: add pre-defined meter policy API
  2021-04-14  3:12 ` [dpdk-dev] [PATCH v4 0/2] Support meter policy API Li Zhang
@ 2021-04-14  3:12   ` Li Zhang
  2021-04-14  3:12   ` [dpdk-dev] [PATCH v4 2/2] app/testpmd: support policy actions per color Li Zhang
  1 sibling, 0 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-14  3:12 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, Jiawei Wang

Currently, the flow meter policy does not support multiple actions
per color; also the allowed action types per color are very limited.
In addition, the policy cannot be pre-defined.

Due to the growing in flow actions offload abilities there is a potential
for the user to use variety of actions per color differently.
This new meter policy API comes to allow this potential in the most ethdev
common way using rte_flow action definition.
A list of rte_flow actions will be provided by the user per color
in order to create a meter policy.
In addition, the API forces to pre-define the policy before
the meters creation in order to allow sharing of single policy
with multiple meters efficiently.

meter_policy_id is added into struct rte_mtr_params.
So that it can get the policy during the meters creation.

Allow coloring the packet using a new rte_flow_action_color
as could be done by the old policy API.

The next API function were added:
- rte_mtr_meter_policy_create
- rte_mtr_meter_policy_delete
- rte_mtr_meter_policy_update
- rte_mtr_meter_policy_validate
The next struct was changed:
- rte_mtr_params
- rte_mtr_capabilities
The next API was deleted:
- rte_mtr_policer_actions_update

To support this API the following app were changed:
app/test-flow-perf: clean meter policer
app/testpmd: clean meter policer

To support this API the following drivers were changed:
net/softnic: support meter policy API
1. cleans meter rte_mtr_policer_action.
2. Support policy API to get color action as policer action did.
   The color action will be mapped into rte_table_action_policer.

net/mlx5: clean meter creation management
Cleans and breaks part of the current meter management
in order to allow better design with policy API.

Signed-off-by: Li Zhang <lizh@nvidia.com>
Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
---
 app/test-flow-perf/main.c                     |   7 -
 app/test-pmd/cmdline.c                        |   1 -
 app/test-pmd/cmdline_mtr.c                    | 172 -------
 app/test-pmd/cmdline_mtr.h                    |   1 -
 doc/guides/prog_guide/rte_flow.rst            |  21 +
 .../traffic_metering_and_policing.rst         |  16 +-
 doc/guides/rel_notes/release_21_05.rst        |  22 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  18 -
 drivers/net/mlx5/mlx5.h                       |  24 +-
 drivers/net/mlx5/mlx5_flow.c                  |  46 --
 drivers/net/mlx5/mlx5_flow.h                  |  18 +-
 drivers/net/mlx5/mlx5_flow_aso.c              |   8 +-
 drivers/net/mlx5/mlx5_flow_dv.c               | 461 +-----------------
 drivers/net/mlx5/mlx5_flow_meter.c            | 369 +-------------
 drivers/net/softnic/rte_eth_softnic_flow.c    |  19 +-
 .../net/softnic/rte_eth_softnic_internals.h   |  18 +-
 drivers/net/softnic/rte_eth_softnic_meter.c   | 264 +++++++---
 lib/librte_ethdev/rte_flow.h                  |  22 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 215 ++++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   5 +-
 22 files changed, 568 insertions(+), 1258 deletions(-)

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


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

* [dpdk-dev] [PATCH v4 2/2] app/testpmd: support policy actions per color
  2021-04-14  3:12 ` [dpdk-dev] [PATCH v4 0/2] Support meter policy API Li Zhang
  2021-04-14  3:12   ` [dpdk-dev] [PATCH v4 1/2] ethdev: add pre-defined " Li Zhang
@ 2021-04-14  3:12   ` Li Zhang
  1 sibling, 0 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-14  3:12 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 create/del policy CLIs to support actions per color.
The CLIs are:
Create:  add port meter policy (port_id) (policy_id) g_actions (actions)
y_actions (actions) r_actions (actions)
Delete:  del port meter policy (port_id) (policy_id)

Examples:
testpmd> add port meter policy 0 1 g_actions rss / end y_actions end
r_actions drop / end
testpmd> del port meter policy 0 1

Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
---
 app/test-pmd/cmdline.c                      |  13 ++-
 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                       |  32 ++++++
 app/test-pmd/testpmd.h                      |   2 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  30 ++++-
 7 files changed, 269 insertions(+), 14 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0bb6394314..6c6184a170 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -705,9 +705,8 @@ 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"
-			"(g_action) (y_action) (r_action) (stats_mask) (shared)\n"
-			"(use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
+			"create port meter (port_id) (mtr_id) (profile_id) (policy_id) (meter_enable)\n"
+			"(stats_mask) (shared) (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
 			"(dscp_tbl_entry63)]\n"
 			"    meter create\n\n"
 
@@ -720,6 +719,13 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"del port meter (port_id) (mtr_id)\n"
 			"    meter delete\n\n"
 
+			"add port meter policy (port_id) (policy_id) g_actions (actions)\n"
+			"y_actions (actions) r_actions (actions)\n"
+			"    meter policy add\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"
 
@@ -17069,6 +17075,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 fb7a3a8bd3..f50e7312ee 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. */
@@ -808,6 +818,9 @@ struct buffer {
 		struct {
 			int destroy;
 		} aged; /**< Aged arguments. */
+		struct {
+			uint32_t policy_id;
+		} policy;/**< Policy arguments. */
 	} args; /**< Command arguments. */
 };
 
@@ -1785,6 +1798,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);
@@ -1823,7 +1839,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 = "",
@@ -1945,6 +1961,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",
@@ -4528,6 +4551,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. */
@@ -4712,6 +4783,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,
@@ -7685,6 +7797,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 a5e82b7a97..c50d104b61 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
 
@@ -1465,6 +1467,36 @@ 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 *act = actions;
+	const struct rte_flow_action *start;
+	struct rte_mtr_meter_policy_params policy;
+	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)
+			policy.actions[i] = start;
+		else
+			policy.actions[i] = NULL;
+		act++;
+	}
+	ret = rte_mtr_meter_policy_create(port_id,
+			policy_id,
+			&policy, &error);
+	if (ret)
+		print_mtr_err_msg(&error);
+	return ret;
+}
+
 /** 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);
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 3f7a1c0e33..b596ee9a14 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2764,13 +2764,37 @@ Delete meter profile from the ethernet device::
 
    testpmd> del port meter profile (port_id) (profile_id)
 
+create port policy
+~~~~~~~~~~~~~~~~~~
+
+Create new policy object for the ethernet device::
+
+   testpmd> add port meter policy (port_id) (policy_id) g_actions \
+   {action} y_actions {action} r_actions {action}
+
+where:
+
+* ``policy_id``: policy ID.
+* ``action``: action lists for green/yellow/red colors.
+
+delete port policy
+~~~~~~~~~~~~~~~~~~
+
+Delete policy object for the ethernet device::
+
+   testpmd> del port meter policy (port_id) (policy_id)
+
+where:
+
+* ``policy_id``: policy ID.
+
 create port meter
 ~~~~~~~~~~~~~~~~~
 
 Create new meter object for the ethernet device::
 
    testpmd> create port meter (port_id) (mtr_id) (profile_id) \
-   (meter_enable) (g_action) (y_action) (r_action) (stats_mask) (shared) \
+   (policy_id) (meter_enable) (stats_mask) (shared) \
    (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\
    (dscp_tbl_entry63)]
 
@@ -2778,11 +2802,9 @@ where:
 
 * ``mtr_id``: meter object ID.
 * ``profile_id``: ID for the meter profile.
+* ``policy_id``: ID for the policy.
 * ``meter_enable``: When this parameter has a non-zero value, the meter object
   gets enabled at the time of creation, otherwise remains disabled.
-* ``g_action``: Policer action for the packet with green color.
-* ``y_action``: Policer action for the packet with yellow color.
-* ``r_action``: Policer action for the packet with red color.
 * ``stats_mask``: Mask of statistics counter types to be enabled for the
   meter object.
 * ``shared``:  When this parameter has a non-zero value, the meter object is
-- 
2.27.0


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

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy API
  2021-04-13 14:19     ` Dumitrescu, Cristian
@ 2021-04-14  3:23       ` Li Zhang
  0 siblings, 0 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-14  3:23 UTC (permalink / raw)
  To: Dumitrescu, Cristian, dekelp, Ori Kam, Slava Ovsiienko,
	Matan Azrad, Shahaf Shuler, lironh, Wisam Monther, Li, Xiaoyun,
	Singh, Jasvinder, NBU-Contact-Thomas Monjalon, Yigit, Ferruh,
	Andrew Rybchenko, Ray Kinsella, Neil Horman, Jerin Jacob
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai, Haifei Luo, Jiawei(Jonny) Wang

Hi Cristian,

This patch is depend on series=16351.
Depends-on: series=16351  ("Add ASO meter support in MLX5 PMD ")
https://patchwork.dpdk.org/project/dpdk/list/?series=16351

Because RTE API change and it need change PMD part to fix building issue.

Regards,
Li Zhang

> -----Original Message-----
> From: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Sent: Tuesday, April 13, 2021 10:19 PM
> To: Li Zhang <lizh@nvidia.com>; dekelp@nvidia.com; Ori Kam
> <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; Matan
> Azrad <matan@nvidia.com>; Shahaf Shuler <shahafs@nvidia.com>;
> lironh@marvell.com; Wisam Monther <wisamm@nvidia.com>; Li, Xiaoyun
> <xiaoyun.li@intel.com>; Singh, Jasvinder <jasvinder.singh@intel.com>; NBU-
> Contact-Thomas Monjalon <thomas@monjalon.net>; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Andrew Rybchenko
> <andrew.rybchenko@oktetlabs.ru>; Ray Kinsella <mdr@ashroe.eu>; Neil
> Horman <nhorman@tuxdriver.com>; Jerin Jacob <jerinjacobk@gmail.com>
> Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar Yanai
> <roniba@nvidia.com>; Haifei Luo <haifeil@nvidia.com>; Jiawei(Jonny) Wang
> <jiaweiw@nvidia.com>
> Subject: RE: [PATCH v3 1/2] ethdev: add pre-defined meter policy API
> 
> External email: Use caution opening links or attachments
> 
> 
> Hi Li,
> 
> This patch does not apply on top of the latest DPDK. Can you please rebase on
> top of DPDK version and resend. If this depends on some other patch sets to be
> applied first, then please send clear steps on how to apply.
> 
> Thanks,
> Cristian

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

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy API
  2021-04-13 14:59     ` Dumitrescu, Cristian
@ 2021-04-14  4:55       ` Li Zhang
  2021-04-14  8:02         ` Thomas Monjalon
  0 siblings, 1 reply; 78+ messages in thread
From: Li Zhang @ 2021-04-14  4:55 UTC (permalink / raw)
  To: Dumitrescu, Cristian, dekelp, Ori Kam, Slava Ovsiienko,
	Matan Azrad, Shahaf Shuler, lironh, Wisam Monther, Li, Xiaoyun,
	Singh, Jasvinder, NBU-Contact-Thomas Monjalon, Yigit, Ferruh,
	Andrew Rybchenko, Ray Kinsella, Neil Horman, Jerin Jacob,
	Hemant Agrawal
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai, Haifei Luo, Jiawei(Jonny) Wang

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

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

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

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

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

* [dpdk-dev] [PATCH v5 0/2] Support meter policy API
  2021-03-18  8:58 [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API Li Zhang
                   ` (4 preceding siblings ...)
  2021-04-14  3:12 ` [dpdk-dev] [PATCH v4 0/2] Support meter policy API Li Zhang
@ 2021-04-14  6:32 ` Li Zhang
  2021-04-14  6:32   ` [dpdk-dev] [PATCH v5 1/2] ethdev: add pre-defined " Li Zhang
  2021-04-14  6:32   ` [dpdk-dev] [PATCH v5 2/2] app/testpmd: support policy actions per color Li Zhang
  2021-04-14  8:57 ` [dpdk-dev] [PATCH v6 0/2] Support meter policy API Li Zhang
                   ` (3 subsequent siblings)
  9 siblings, 2 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-14  6:32 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/

Depends-on: series=16351  ("Add ASO meter support in MLX5 PMD ")
https://patchwork.dpdk.org/project/dpdk/list/?series=16351

V2: Delete default policy and change relation doc files.
V3: Fix coding style issues.
V4: Fix comments about Depends-on
V5: Fix comments about rte_mtr_meter_policy_add.

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                        |  14 +-
 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                         |  32 ++
 app/test-pmd/testpmd.h                        |   2 +
 doc/guides/prog_guide/rte_flow.rst            |  21 +
 .../traffic_metering_and_policing.rst         |  16 +-
 doc/guides/rel_notes/release_21_05.rst        |  22 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  48 +-
 drivers/net/mlx5/mlx5.h                       |  24 +-
 drivers/net/mlx5/mlx5_flow.c                  |  46 --
 drivers/net/mlx5/mlx5_flow.h                  |  18 +-
 drivers/net/mlx5/mlx5_flow_aso.c              |   8 +-
 drivers/net/mlx5/mlx5_flow_dv.c               | 461 +-----------------
 drivers/net/mlx5/mlx5_flow_meter.c            | 369 +-------------
 drivers/net/softnic/rte_eth_softnic_flow.c    |  19 +-
 .../net/softnic/rte_eth_softnic_internals.h   |  18 +-
 drivers/net/softnic/rte_eth_softnic_meter.c   | 264 +++++++---
 lib/librte_ethdev/rte_flow.h                  |  22 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 216 ++++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   5 +-
 25 files changed, 838 insertions(+), 1272 deletions(-)

-- 
2.27.0


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

* [dpdk-dev] [PATCH v5 1/2] ethdev: add pre-defined meter policy API
  2021-04-14  6:32 ` [dpdk-dev] [PATCH v5 0/2] Support meter policy API Li Zhang
@ 2021-04-14  6:32   ` Li Zhang
  2021-04-14  6:32   ` [dpdk-dev] [PATCH v5 2/2] app/testpmd: support policy actions per color Li Zhang
  1 sibling, 0 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-14  6:32 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, Jiawei Wang

Currently, the flow meter policy does not support multiple actions
per color; also the allowed action types per color are very limited.
In addition, the policy cannot be pre-defined.

Due to the growing in flow actions offload abilities there is a potential
for the user to use variety of actions per color differently.
This new meter policy API comes to allow this potential in the most ethdev
common way using rte_flow action definition.
A list of rte_flow actions will be provided by the user per color
in order to create a meter policy.
In addition, the API forces to pre-define the policy before
the meters creation in order to allow sharing of single policy
with multiple meters efficiently.

meter_policy_id is added into struct rte_mtr_params.
So that it can get the policy during the meters creation.

Allow coloring the packet using a new rte_flow_action_color
as could be done by the old policy API.

The next API function were added:
- rte_mtr_meter_policy_create
- rte_mtr_meter_policy_delete
- rte_mtr_meter_policy_update
- rte_mtr_meter_policy_validate
The next struct was changed:
- rte_mtr_params
- rte_mtr_capabilities
The next API was deleted:
- rte_mtr_policer_actions_update

To support this API the following app were changed:
app/test-flow-perf: clean meter policer
app/testpmd: clean meter policer

To support this API the following drivers were changed:
net/softnic: support meter policy API
1. cleans meter rte_mtr_policer_action.
2. Support policy API to get color action as policer action did.
   The color action will be mapped into rte_table_action_policer.

net/mlx5: clean meter creation management
Cleans and breaks part of the current meter management
in order to allow better design with policy API.

Signed-off-by: Li Zhang <lizh@nvidia.com>
Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
Acked-by: Ray Kinsella <mdr@ashroe.eu>
---
 app/test-flow-perf/main.c                     |   7 -
 app/test-pmd/cmdline.c                        |   1 -
 app/test-pmd/cmdline_mtr.c                    | 172 -------
 app/test-pmd/cmdline_mtr.h                    |   1 -
 doc/guides/prog_guide/rte_flow.rst            |  21 +
 .../traffic_metering_and_policing.rst         |  16 +-
 doc/guides/rel_notes/release_21_05.rst        |  22 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  18 -
 drivers/net/mlx5/mlx5.h                       |  24 +-
 drivers/net/mlx5/mlx5_flow.c                  |  46 --
 drivers/net/mlx5/mlx5_flow.h                  |  18 +-
 drivers/net/mlx5/mlx5_flow_aso.c              |   8 +-
 drivers/net/mlx5/mlx5_flow_dv.c               | 461 +-----------------
 drivers/net/mlx5/mlx5_flow_meter.c            | 369 +-------------
 drivers/net/softnic/rte_eth_softnic_flow.c    |  19 +-
 .../net/softnic/rte_eth_softnic_internals.h   |  18 +-
 drivers/net/softnic/rte_eth_softnic_meter.c   | 264 +++++++---
 lib/librte_ethdev/rte_flow.h                  |  22 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 216 ++++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   5 +-
 22 files changed, 569 insertions(+), 1258 deletions(-)

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


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

* [dpdk-dev] [PATCH v5 2/2] app/testpmd: support policy actions per color
  2021-04-14  6:32 ` [dpdk-dev] [PATCH v5 0/2] Support meter policy API Li Zhang
  2021-04-14  6:32   ` [dpdk-dev] [PATCH v5 1/2] ethdev: add pre-defined " Li Zhang
@ 2021-04-14  6:32   ` Li Zhang
  1 sibling, 0 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-14  6:32 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 create/del policy CLIs to support actions per color.
The CLIs are:
Create:  add port meter policy (port_id) (policy_id) g_actions (actions)
y_actions (actions) r_actions (actions)
Delete:  del port meter policy (port_id) (policy_id)

Examples:
testpmd> add port meter policy 0 1 g_actions rss / end y_actions end
r_actions drop / end
testpmd> del port meter policy 0 1

Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
---
 app/test-pmd/cmdline.c                      |  13 ++-
 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                       |  32 ++++++
 app/test-pmd/testpmd.h                      |   2 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  30 ++++-
 7 files changed, 269 insertions(+), 14 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0bb6394314..6c6184a170 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -705,9 +705,8 @@ 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"
-			"(g_action) (y_action) (r_action) (stats_mask) (shared)\n"
-			"(use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
+			"create port meter (port_id) (mtr_id) (profile_id) (policy_id) (meter_enable)\n"
+			"(stats_mask) (shared) (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
 			"(dscp_tbl_entry63)]\n"
 			"    meter create\n\n"
 
@@ -720,6 +719,13 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"del port meter (port_id) (mtr_id)\n"
 			"    meter delete\n\n"
 
+			"add port meter policy (port_id) (policy_id) g_actions (actions)\n"
+			"y_actions (actions) r_actions (actions)\n"
+			"    meter policy add\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"
 
@@ -17069,6 +17075,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 fb7a3a8bd3..f50e7312ee 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. */
@@ -808,6 +818,9 @@ struct buffer {
 		struct {
 			int destroy;
 		} aged; /**< Aged arguments. */
+		struct {
+			uint32_t policy_id;
+		} policy;/**< Policy arguments. */
 	} args; /**< Command arguments. */
 };
 
@@ -1785,6 +1798,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);
@@ -1823,7 +1839,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 = "",
@@ -1945,6 +1961,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",
@@ -4528,6 +4551,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. */
@@ -4712,6 +4783,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,
@@ -7685,6 +7797,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 a5e82b7a97..f8b3f671cd 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
 
@@ -1465,6 +1467,36 @@ 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 *act = actions;
+	const struct rte_flow_action *start;
+	struct rte_mtr_meter_policy_params policy;
+	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)
+			policy.actions[i] = start;
+		else
+			policy.actions[i] = NULL;
+		act++;
+	}
+	ret = rte_mtr_meter_policy_add(port_id,
+			policy_id,
+			&policy, &error);
+	if (ret)
+		print_mtr_err_msg(&error);
+	return ret;
+}
+
 /** 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);
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 3f7a1c0e33..b596ee9a14 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2764,13 +2764,37 @@ Delete meter profile from the ethernet device::
 
    testpmd> del port meter profile (port_id) (profile_id)
 
+create port policy
+~~~~~~~~~~~~~~~~~~
+
+Create new policy object for the ethernet device::
+
+   testpmd> add port meter policy (port_id) (policy_id) g_actions \
+   {action} y_actions {action} r_actions {action}
+
+where:
+
+* ``policy_id``: policy ID.
+* ``action``: action lists for green/yellow/red colors.
+
+delete port policy
+~~~~~~~~~~~~~~~~~~
+
+Delete policy object for the ethernet device::
+
+   testpmd> del port meter policy (port_id) (policy_id)
+
+where:
+
+* ``policy_id``: policy ID.
+
 create port meter
 ~~~~~~~~~~~~~~~~~
 
 Create new meter object for the ethernet device::
 
    testpmd> create port meter (port_id) (mtr_id) (profile_id) \
-   (meter_enable) (g_action) (y_action) (r_action) (stats_mask) (shared) \
+   (policy_id) (meter_enable) (stats_mask) (shared) \
    (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\
    (dscp_tbl_entry63)]
 
@@ -2778,11 +2802,9 @@ where:
 
 * ``mtr_id``: meter object ID.
 * ``profile_id``: ID for the meter profile.
+* ``policy_id``: ID for the policy.
 * ``meter_enable``: When this parameter has a non-zero value, the meter object
   gets enabled at the time of creation, otherwise remains disabled.
-* ``g_action``: Policer action for the packet with green color.
-* ``y_action``: Policer action for the packet with yellow color.
-* ``r_action``: Policer action for the packet with red color.
 * ``stats_mask``: Mask of statistics counter types to be enabled for the
   meter object.
 * ``shared``:  When this parameter has a non-zero value, the meter object is
-- 
2.27.0


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

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy API
  2021-04-14  4:55       ` Li Zhang
@ 2021-04-14  8:02         ` Thomas Monjalon
  2021-04-14  8:31           ` Matan Azrad
  2021-04-14  8:47           ` Asaf Penso
  0 siblings, 2 replies; 78+ messages in thread
From: Thomas Monjalon @ 2021-04-14  8:02 UTC (permalink / raw)
  To: Dumitrescu, Cristian, Li Zhang
  Cc: Ori Kam, Slava Ovsiienko, Matan Azrad, lironh, Wisam Monther, Li,
	Xiaoyun, Singh, Jasvinder, Yigit, Ferruh, Andrew Rybchenko,
	Ray Kinsella, Jerin Jacob, Hemant Agrawal, dev, Raslan Darawsheh,
	Roni Bar Yanai, Haifei Luo, Jiawei(Jonny) Wang

Cristian, Li, please remove useless context when replying.

14/04/2021 06:55, Li Zhang:
> > > + * Example #2: GREEN - Do nothing, YELLOW - Do nothing, RED - DROP
> > > + *   struct rte_mtr_meter_policy_params policy_1 =
> > > + *                                   (struct
> > > rte_mtr_meter_policy_params) {
> > > + *           .actions[RTE_COLOR_GREEN] = NULL,
> > > + *           .actions[RTE_COLOR_YELLOW] = NULL,
> > > + *           .actions[RTE_COLOR_RED] = (struct rte_flow_action[]) {
> > > + *                   {
> > > + *                           .type = RTE_FLOW_ACTION_TYPE_DROP,
> > > + *                   },
> > > + *                   {
> > > + *                           .type = RTE_FLOW_ACTION_TYPE_END,
> > > + *                   },
> > > + *           },
> > > + *   };
> > > + *
> >
> > These two example policies should be available to be used straight away,
> > please make them real data structures, not comments.

Wait, you are giving code examples as part of doxygen?
It's really too long, we don't do that.

> > I suggest their names as: pass_color_policy_params and
> > drop_red_policy_params.
> >
> Thanks. Will change the names. But it can not be real data structures, since it just one example define and no use code.
> It will bring build as below:
> error: 'drop_red_policy_params' defined but not used.
>  User can copy these example to his .c file when it using rte_mtr_meter_policy_add().

If you need to provide an example, we use the directory examples.
I see rte_mtr is not implemented in any example,
so it could be a later addition.




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

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy API
  2021-04-14  8:02         ` Thomas Monjalon
@ 2021-04-14  8:31           ` Matan Azrad
  2021-04-14  8:47           ` Asaf Penso
  1 sibling, 0 replies; 78+ messages in thread
From: Matan Azrad @ 2021-04-14  8:31 UTC (permalink / raw)
  To: NBU-Contact-Thomas Monjalon, Dumitrescu, Cristian, Li Zhang
  Cc: Ori Kam, Slava Ovsiienko, lironh, Wisam Monther, Li, Xiaoyun,
	Singh, Jasvinder, Yigit, Ferruh, Andrew Rybchenko, Ray Kinsella,
	Jerin Jacob, Hemant Agrawal, dev, Raslan Darawsheh,
	Roni Bar Yanai, Haifei Luo, Jiawei(Jonny) Wang



From: Thomas Monjalon
> Cristian, Li, please remove useless context when replying.
> 
> 14/04/2021 06:55, Li Zhang:
> > > > + * Example #2: GREEN - Do nothing, YELLOW - Do nothing, RED - DROP
> > > > + *   struct rte_mtr_meter_policy_params policy_1 =
> > > > + *                                   (struct
> > > > rte_mtr_meter_policy_params) {
> > > > + *           .actions[RTE_COLOR_GREEN] = NULL,
> > > > + *           .actions[RTE_COLOR_YELLOW] = NULL,
> > > > + *           .actions[RTE_COLOR_RED] = (struct rte_flow_action[]) {
> > > > + *                   {
> > > > + *                           .type = RTE_FLOW_ACTION_TYPE_DROP,
> > > > + *                   },
> > > > + *                   {
> > > > + *                           .type = RTE_FLOW_ACTION_TYPE_END,
> > > > + *                   },
> > > > + *           },
> > > > + *   };
> > > > + *
> > >
> > > These two example policies should be available to be used straight
> > > away, please make them real data structures, not comments.
> 
> Wait, you are giving code examples as part of doxygen?
> It's really too long, we don't do that.
> 
> > > I suggest their names as: pass_color_policy_params and
> > > drop_red_policy_params.
> > >
> > Thanks. Will change the names. But it can not be real data structures, since it
> just one example define and no use code.
> > It will bring build as below:
> > error: 'drop_red_policy_params' defined but not used.
> >  User can copy these example to his .c file when it using
> rte_mtr_meter_policy_add().
> 
> If you need to provide an example, we use the directory examples.
> I see rte_mtr is not implemented in any example, so it could be a later
> addition.

+1
 


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

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy API
  2021-04-14  8:02         ` Thomas Monjalon
  2021-04-14  8:31           ` Matan Azrad
@ 2021-04-14  8:47           ` Asaf Penso
  2021-04-14  8:59             ` Li Zhang
                               ` (2 more replies)
  1 sibling, 3 replies; 78+ messages in thread
From: Asaf Penso @ 2021-04-14  8:47 UTC (permalink / raw)
  To: NBU-Contact-Thomas Monjalon, Dumitrescu, Cristian, Li Zhang
  Cc: Ori Kam, Slava Ovsiienko, Matan Azrad, lironh, Wisam Monther, Li,
	Xiaoyun, Singh, Jasvinder, Yigit, Ferruh, Andrew Rybchenko,
	Ray Kinsella, Jerin Jacob, Hemant Agrawal, dev, Raslan Darawsheh,
	Roni Bar Yanai, Haifei Luo, Jiawei(Jonny) Wang

>-----Original Message-----
>From: dev <dev-bounces@dpdk.org> On Behalf Of Thomas Monjalon
>Sent: Wednesday, April 14, 2021 11:02 AM
>To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; Li Zhang
><lizh@nvidia.com>
>Cc: Ori Kam <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>;
>Matan Azrad <matan@nvidia.com>; lironh@marvell.com; Wisam Monther
><wisamm@nvidia.com>; Li, Xiaoyun <xiaoyun.li@intel.com>; Singh, Jasvinder
><jasvinder.singh@intel.com>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
>Rybchenko <andrew.rybchenko@oktetlabs.ru>; Ray Kinsella
><mdr@ashroe.eu>; Jerin Jacob <jerinjacobk@gmail.com>; Hemant Agrawal
><hemant.agrawal@nxp.com>; dev@dpdk.org; Raslan Darawsheh
><rasland@nvidia.com>; Roni Bar Yanai <roniba@nvidia.com>; Haifei Luo
><haifeil@nvidia.com>; Jiawei(Jonny) Wang <jiaweiw@nvidia.com>
>Subject: Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy
>API
>
>Cristian, Li, please remove useless context when replying.
>
>14/04/2021 06:55, Li Zhang:
>> > > + * Example #2: GREEN - Do nothing, YELLOW - Do nothing, RED - DROP
>> > > + *   struct rte_mtr_meter_policy_params policy_1 =
>> > > + *                                   (struct
>> > > rte_mtr_meter_policy_params) {
>> > > + *           .actions[RTE_COLOR_GREEN] = NULL,
>> > > + *           .actions[RTE_COLOR_YELLOW] = NULL,
>> > > + *           .actions[RTE_COLOR_RED] = (struct rte_flow_action[]) {
>> > > + *                   {
>> > > + *                           .type = RTE_FLOW_ACTION_TYPE_DROP,
>> > > + *                   },
>> > > + *                   {
>> > > + *                           .type = RTE_FLOW_ACTION_TYPE_END,
>> > > + *                   },
>> > > + *           },
>> > > + *   };
>> > > + *
>> >
>> > These two example policies should be available to be used straight
>> > away, please make them real data structures, not comments.
>
>Wait, you are giving code examples as part of doxygen?
>It's really too long, we don't do that.
>
>> > I suggest their names as: pass_color_policy_params and
>> > drop_red_policy_params.
>> >
>> Thanks. Will change the names. But it can not be real data structures, since it
>just one example define and no use code.
>> It will bring build as below:
>> error: 'drop_red_policy_params' defined but not used.
>>  User can copy these example to his .c file when it using
>rte_mtr_meter_policy_add().
>
>If you need to provide an example, we use the directory examples.
>I see rte_mtr is not implemented in any example, so it could be a later
>addition.
>
>
We want, as a rule of thumb, to provide more code snippets and not necessarily full-blown example applications. 
Where do you suggest having that?
In any case, I agree, this can be removed now to allow integration of rc1. Doc can be done afterward.

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

* [dpdk-dev] [PATCH v6 0/2] Support meter policy API
  2021-03-18  8:58 [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API Li Zhang
                   ` (5 preceding siblings ...)
  2021-04-14  6:32 ` [dpdk-dev] [PATCH v5 0/2] Support meter policy API Li Zhang
@ 2021-04-14  8:57 ` Li Zhang
  2021-04-14  8:57   ` [dpdk-dev] [PATCH v6 1/2] ethdev: add pre-defined " Li Zhang
  2021-04-14  8:58   ` [dpdk-dev] [PATCH v6 2/2] app/testpmd: support policy actions per color Li Zhang
  2021-04-15  4:54 ` [dpdk-dev] [PATCH v7 0/2] Support meter policy API Li Zhang
                   ` (2 subsequent siblings)
  9 siblings, 2 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-14  8:57 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, cristian.dumitrescu,
	lironh, jerinj, ferruh.yigit, ajit.khaparde
  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/

Depends-on: series=16351  ("Add ASO meter support in MLX5 PMD ")
https://patchwork.dpdk.org/project/dpdk/list/?series=16351

V2: Delete default policy and change relation doc files.
V3: Fix coding style issues.
V4: Fix comments about Depends-on
V5: Fix comments about rte_mtr_meter_policy_add.
V6: Delete policy example.

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                        |  14 +-
 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                         |  32 ++
 app/test-pmd/testpmd.h                        |   2 +
 doc/guides/prog_guide/rte_flow.rst            |  21 +
 .../traffic_metering_and_policing.rst         |  16 +-
 doc/guides/rel_notes/release_21_05.rst        |  22 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  48 +-
 drivers/net/mlx5/mlx5.h                       |  24 +-
 drivers/net/mlx5/mlx5_flow.c                  |  46 --
 drivers/net/mlx5/mlx5_flow.h                  |  18 +-
 drivers/net/mlx5/mlx5_flow_aso.c              |   8 +-
 drivers/net/mlx5/mlx5_flow_dv.c               | 461 +-----------------
 drivers/net/mlx5/mlx5_flow_meter.c            | 369 +-------------
 drivers/net/softnic/rte_eth_softnic_flow.c    |  19 +-
 .../net/softnic/rte_eth_softnic_internals.h   |  18 +-
 drivers/net/softnic/rte_eth_softnic_meter.c   | 264 +++++++---
 lib/librte_ethdev/rte_flow.h                  |  22 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 162 ++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   5 +-
 25 files changed, 784 insertions(+), 1272 deletions(-)

-- 
2.27.0


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

* [dpdk-dev] [PATCH v6 1/2] ethdev: add pre-defined meter policy API
  2021-04-14  8:57 ` [dpdk-dev] [PATCH v6 0/2] Support meter policy API Li Zhang
@ 2021-04-14  8:57   ` Li Zhang
  2021-04-14 16:16     ` Dumitrescu, Cristian
  2021-04-14 22:21     ` Singh, Jasvinder
  2021-04-14  8:58   ` [dpdk-dev] [PATCH v6 2/2] app/testpmd: support policy actions per color Li Zhang
  1 sibling, 2 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-14  8:57 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, cristian.dumitrescu,
	lironh, jerinj, ferruh.yigit, ajit.khaparde, Wisam Jaddo,
	Xiaoyun Li, Jasvinder Singh, Thomas Monjalon, Andrew Rybchenko,
	Ray Kinsella, Neil Horman
  Cc: dev, rasland, roniba, Haifei Luo, Jiawei Wang

Currently, the flow meter policy does not support multiple actions
per color; also the allowed action types per color are very limited.
In addition, the policy cannot be pre-defined.

Due to the growing in flow actions offload abilities there is a potential
for the user to use variety of actions per color differently.
This new meter policy API comes to allow this potential in the most ethdev
common way using rte_flow action definition.
A list of rte_flow actions will be provided by the user per color
in order to create a meter policy.
In addition, the API forces to pre-define the policy before
the meters creation in order to allow sharing of single policy
with multiple meters efficiently.

meter_policy_id is added into struct rte_mtr_params.
So that it can get the policy during the meters creation.

Allow coloring the packet using a new rte_flow_action_color
as could be done by the old policy API.

The next API function were added:
- rte_mtr_meter_policy_create
- rte_mtr_meter_policy_delete
- rte_mtr_meter_policy_update
- rte_mtr_meter_policy_validate
The next struct was changed:
- rte_mtr_params
- rte_mtr_capabilities
The next API was deleted:
- rte_mtr_policer_actions_update

To support this API the following app were changed:
app/test-flow-perf: clean meter policer
app/testpmd: clean meter policer

To support this API the following drivers were changed:
net/softnic: support meter policy API
1. cleans meter rte_mtr_policer_action.
2. Support policy API to get color action as policer action did.
   The color action will be mapped into rte_table_action_policer.

net/mlx5: clean meter creation management
Cleans and breaks part of the current meter management
in order to allow better design with policy API.

Signed-off-by: Li Zhang <lizh@nvidia.com>
Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
Acked-by: Ray Kinsella <mdr@ashroe.eu>
---
 app/test-flow-perf/main.c                     |   7 -
 app/test-pmd/cmdline.c                        |   1 -
 app/test-pmd/cmdline_mtr.c                    | 172 -------
 app/test-pmd/cmdline_mtr.h                    |   1 -
 doc/guides/prog_guide/rte_flow.rst            |  21 +
 .../traffic_metering_and_policing.rst         |  16 +-
 doc/guides/rel_notes/release_21_05.rst        |  22 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  18 -
 drivers/net/mlx5/mlx5.h                       |  24 +-
 drivers/net/mlx5/mlx5_flow.c                  |  46 --
 drivers/net/mlx5/mlx5_flow.h                  |  18 +-
 drivers/net/mlx5/mlx5_flow_aso.c              |   8 +-
 drivers/net/mlx5/mlx5_flow_dv.c               | 461 +-----------------
 drivers/net/mlx5/mlx5_flow_meter.c            | 369 +-------------
 drivers/net/softnic/rte_eth_softnic_flow.c    |  19 +-
 .../net/softnic/rte_eth_softnic_internals.h   |  18 +-
 drivers/net/softnic/rte_eth_softnic_meter.c   | 264 +++++++---
 lib/librte_ethdev/rte_flow.h                  |  22 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 162 ++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   5 +-
 22 files changed, 515 insertions(+), 1258 deletions(-)

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


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

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

From: Haifei Luo <haifeil@nvidia.com>

Add the create/del policy CLIs to support actions per color.
The CLIs are:
Create:  add port meter policy (port_id) (policy_id) g_actions (actions)
y_actions (actions) r_actions (actions)
Delete:  del port meter policy (port_id) (policy_id)

Examples:
testpmd> add port meter policy 0 1 g_actions rss / end y_actions end
r_actions drop / end
testpmd> del port meter policy 0 1

Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
---
 app/test-pmd/cmdline.c                      |  13 ++-
 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                       |  32 ++++++
 app/test-pmd/testpmd.h                      |   2 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  30 ++++-
 7 files changed, 269 insertions(+), 14 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0bb6394314..6c6184a170 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -705,9 +705,8 @@ 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"
-			"(g_action) (y_action) (r_action) (stats_mask) (shared)\n"
-			"(use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
+			"create port meter (port_id) (mtr_id) (profile_id) (policy_id) (meter_enable)\n"
+			"(stats_mask) (shared) (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
 			"(dscp_tbl_entry63)]\n"
 			"    meter create\n\n"
 
@@ -720,6 +719,13 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"del port meter (port_id) (mtr_id)\n"
 			"    meter delete\n\n"
 
+			"add port meter policy (port_id) (policy_id) g_actions (actions)\n"
+			"y_actions (actions) r_actions (actions)\n"
+			"    meter policy add\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"
 
@@ -17069,6 +17075,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 fb7a3a8bd3..f50e7312ee 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. */
@@ -808,6 +818,9 @@ struct buffer {
 		struct {
 			int destroy;
 		} aged; /**< Aged arguments. */
+		struct {
+			uint32_t policy_id;
+		} policy;/**< Policy arguments. */
 	} args; /**< Command arguments. */
 };
 
@@ -1785,6 +1798,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);
@@ -1823,7 +1839,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 = "",
@@ -1945,6 +1961,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",
@@ -4528,6 +4551,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. */
@@ -4712,6 +4783,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,
@@ -7685,6 +7797,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 a5e82b7a97..f8b3f671cd 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
 
@@ -1465,6 +1467,36 @@ 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 *act = actions;
+	const struct rte_flow_action *start;
+	struct rte_mtr_meter_policy_params policy;
+	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)
+			policy.actions[i] = start;
+		else
+			policy.actions[i] = NULL;
+		act++;
+	}
+	ret = rte_mtr_meter_policy_add(port_id,
+			policy_id,
+			&policy, &error);
+	if (ret)
+		print_mtr_err_msg(&error);
+	return ret;
+}
+
 /** 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);
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 3f7a1c0e33..b596ee9a14 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2764,13 +2764,37 @@ Delete meter profile from the ethernet device::
 
    testpmd> del port meter profile (port_id) (profile_id)
 
+create port policy
+~~~~~~~~~~~~~~~~~~
+
+Create new policy object for the ethernet device::
+
+   testpmd> add port meter policy (port_id) (policy_id) g_actions \
+   {action} y_actions {action} r_actions {action}
+
+where:
+
+* ``policy_id``: policy ID.
+* ``action``: action lists for green/yellow/red colors.
+
+delete port policy
+~~~~~~~~~~~~~~~~~~
+
+Delete policy object for the ethernet device::
+
+   testpmd> del port meter policy (port_id) (policy_id)
+
+where:
+
+* ``policy_id``: policy ID.
+
 create port meter
 ~~~~~~~~~~~~~~~~~
 
 Create new meter object for the ethernet device::
 
    testpmd> create port meter (port_id) (mtr_id) (profile_id) \
-   (meter_enable) (g_action) (y_action) (r_action) (stats_mask) (shared) \
+   (policy_id) (meter_enable) (stats_mask) (shared) \
    (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\
    (dscp_tbl_entry63)]
 
@@ -2778,11 +2802,9 @@ where:
 
 * ``mtr_id``: meter object ID.
 * ``profile_id``: ID for the meter profile.
+* ``policy_id``: ID for the policy.
 * ``meter_enable``: When this parameter has a non-zero value, the meter object
   gets enabled at the time of creation, otherwise remains disabled.
-* ``g_action``: Policer action for the packet with green color.
-* ``y_action``: Policer action for the packet with yellow color.
-* ``r_action``: Policer action for the packet with red color.
 * ``stats_mask``: Mask of statistics counter types to be enabled for the
   meter object.
 * ``shared``:  When this parameter has a non-zero value, the meter object is
-- 
2.27.0


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

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy API
  2021-04-14  8:47           ` Asaf Penso
@ 2021-04-14  8:59             ` Li Zhang
  2021-04-14  9:04             ` Thomas Monjalon
  2021-04-14 14:00             ` Dumitrescu, Cristian
  2 siblings, 0 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-14  8:59 UTC (permalink / raw)
  To: Asaf Penso, NBU-Contact-Thomas Monjalon, Dumitrescu, Cristian
  Cc: Ori Kam, Slava Ovsiienko, Matan Azrad, lironh, Wisam Monther, Li,
	Xiaoyun, Singh, Jasvinder, Yigit, Ferruh, Andrew Rybchenko,
	Ray Kinsella, Jerin Jacob, Hemant Agrawal, dev, Raslan Darawsheh,
	Roni Bar Yanai, Haifei Luo, Jiawei(Jonny) Wang

Hi All,

Thanks for your suggestions.
I delete the example in V6 patch.

Regards,
Li Zhang
> -----Original Message-----
> From: Asaf Penso <asafp@nvidia.com>
> Sent: Wednesday, April 14, 2021 4:47 PM
> To: NBU-Contact-Thomas Monjalon <thomas@monjalon.net>; Dumitrescu,
> Cristian <cristian.dumitrescu@intel.com>; Li Zhang <lizh@nvidia.com>
> Cc: Ori Kam <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>;
> Matan Azrad <matan@nvidia.com>; lironh@marvell.com; Wisam Monther
> <wisamm@nvidia.com>; Li, Xiaoyun <xiaoyun.li@intel.com>; Singh,
> Jasvinder <jasvinder.singh@intel.com>; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Andrew Rybchenko
> <andrew.rybchenko@oktetlabs.ru>; Ray Kinsella <mdr@ashroe.eu>; Jerin
> Jacob <jerinjacobk@gmail.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>; dev@dpdk.org; Raslan Darawsheh
> <rasland@nvidia.com>; Roni Bar Yanai <roniba@nvidia.com>; Haifei Luo
> <haifeil@nvidia.com>; Jiawei(Jonny) Wang <jiaweiw@nvidia.com>
> Subject: RE: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy
> API
> 
> >-----Original Message-----
> >From: dev <dev-bounces@dpdk.org> On Behalf Of Thomas Monjalon
> >Sent: Wednesday, April 14, 2021 11:02 AM
> >To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; Li Zhang
> ><lizh@nvidia.com>
> >Cc: Ori Kam <orika@nvidia.com>; Slava Ovsiienko
> ><viacheslavo@nvidia.com>; Matan Azrad <matan@nvidia.com>;
> >lironh@marvell.com; Wisam Monther <wisamm@nvidia.com>; Li, Xiaoyun
> ><xiaoyun.li@intel.com>; Singh, Jasvinder <jasvinder.singh@intel.com>;
> >Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew Rybchenko
> ><andrew.rybchenko@oktetlabs.ru>; Ray Kinsella <mdr@ashroe.eu>; Jerin
> >Jacob <jerinjacobk@gmail.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>;
> >dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar Yanai
> ><roniba@nvidia.com>; Haifei Luo <haifeil@nvidia.com>; Jiawei(Jonny)
> >Wang <jiaweiw@nvidia.com>
> >Subject: Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter
> >policy API
> >
> >Cristian, Li, please remove useless context when replying.
> >
> >14/04/2021 06:55, Li Zhang:
> >> > > + * Example #2: GREEN - Do nothing, YELLOW - Do nothing, RED -
> DROP
> >> > > + *   struct rte_mtr_meter_policy_params policy_1 =
> >> > > + *                                   (struct
> >> > > rte_mtr_meter_policy_params) {
> >> > > + *           .actions[RTE_COLOR_GREEN] = NULL,
> >> > > + *           .actions[RTE_COLOR_YELLOW] = NULL,
> >> > > + *           .actions[RTE_COLOR_RED] = (struct rte_flow_action[]) {
> >> > > + *                   {
> >> > > + *                           .type = RTE_FLOW_ACTION_TYPE_DROP,
> >> > > + *                   },
> >> > > + *                   {
> >> > > + *                           .type = RTE_FLOW_ACTION_TYPE_END,
> >> > > + *                   },
> >> > > + *           },
> >> > > + *   };
> >> > > + *
> >> >
> >> > These two example policies should be available to be used straight
> >> > away, please make them real data structures, not comments.
> >
> >Wait, you are giving code examples as part of doxygen?
> >It's really too long, we don't do that.
> >
> >> > I suggest their names as: pass_color_policy_params and
> >> > drop_red_policy_params.
> >> >
> >> Thanks. Will change the names. But it can not be real data
> >> structures, since it
> >just one example define and no use code.
> >> It will bring build as below:
> >> error: 'drop_red_policy_params' defined but not used.
> >>  User can copy these example to his .c file when it using
> >rte_mtr_meter_policy_add().
> >
> >If you need to provide an example, we use the directory examples.
> >I see rte_mtr is not implemented in any example, so it could be a later
> >addition.
> >
> >
> We want, as a rule of thumb, to provide more code snippets and not
> necessarily full-blown example applications.
> Where do you suggest having that?
> In any case, I agree, this can be removed now to allow integration of rc1.
> Doc can be done afterward.

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

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy API
  2021-04-14  8:47           ` Asaf Penso
  2021-04-14  8:59             ` Li Zhang
@ 2021-04-14  9:04             ` Thomas Monjalon
  2021-04-14 14:00             ` Dumitrescu, Cristian
  2 siblings, 0 replies; 78+ messages in thread
From: Thomas Monjalon @ 2021-04-14  9:04 UTC (permalink / raw)
  To: Dumitrescu, Cristian, Li Zhang, Asaf Penso
  Cc: Ori Kam, Slava Ovsiienko, Matan Azrad, lironh, Wisam Monther, Li,
	Xiaoyun, Singh, Jasvinder, Yigit, Ferruh, Andrew Rybchenko,
	Ray Kinsella, Jerin Jacob, Hemant Agrawal, dev, Raslan Darawsheh,
	Roni Bar Yanai, Haifei Luo, Jiawei(Jonny) Wang

14/04/2021 10:47, Asaf Penso:
> From: Thomas Monjalon
> >Cristian, Li, please remove useless context when replying.
> >
> >14/04/2021 06:55, Li Zhang:
> >> > > + * Example #2: GREEN - Do nothing, YELLOW - Do nothing, RED - DROP
> >> > > + *   struct rte_mtr_meter_policy_params policy_1 =
> >> > > + *                                   (struct
> >> > > rte_mtr_meter_policy_params) {
> >> > > + *           .actions[RTE_COLOR_GREEN] = NULL,
> >> > > + *           .actions[RTE_COLOR_YELLOW] = NULL,
> >> > > + *           .actions[RTE_COLOR_RED] = (struct rte_flow_action[]) {
> >> > > + *                   {
> >> > > + *                           .type = RTE_FLOW_ACTION_TYPE_DROP,
> >> > > + *                   },
> >> > > + *                   {
> >> > > + *                           .type = RTE_FLOW_ACTION_TYPE_END,
> >> > > + *                   },
> >> > > + *           },
> >> > > + *   };
> >> > > + *
> >> >
> >> > These two example policies should be available to be used straight
> >> > away, please make them real data structures, not comments.
> >
> >Wait, you are giving code examples as part of doxygen?
> >It's really too long, we don't do that.
> >
> >> > I suggest their names as: pass_color_policy_params and
> >> > drop_red_policy_params.
> >> >
> >> Thanks. Will change the names. But it can not be real data structures, since it
> >just one example define and no use code.
> >> It will bring build as below:
> >> error: 'drop_red_policy_params' defined but not used.
> >>  User can copy these example to his .c file when it using
> >rte_mtr_meter_policy_add().
> >
> >If you need to provide an example, we use the directory examples.
> >I see rte_mtr is not implemented in any example, so it could be a later
> >addition.
> >
> >
> We want, as a rule of thumb, to provide more code snippets and not necessarily full-blown example applications. 
> Where do you suggest having that?

In the examples directory, adding small functions.




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

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy API
  2021-04-14  8:47           ` Asaf Penso
  2021-04-14  8:59             ` Li Zhang
  2021-04-14  9:04             ` Thomas Monjalon
@ 2021-04-14 14:00             ` Dumitrescu, Cristian
  2021-04-14 16:21               ` Li Zhang
  2 siblings, 1 reply; 78+ messages in thread
From: Dumitrescu, Cristian @ 2021-04-14 14:00 UTC (permalink / raw)
  To: Asaf Penso, NBU-Contact-Thomas Monjalon, Li Zhang
  Cc: Ori Kam, Slava Ovsiienko, Matan Azrad, lironh, Wisam Monther, Li,
	Xiaoyun, Singh, Jasvinder, Yigit, Ferruh, Andrew Rybchenko,
	Ray Kinsella, Jerin Jacob, Hemant Agrawal, dev, Raslan Darawsheh,
	Roni Bar Yanai, Haifei Luo, Jiawei(Jonny) Wang

> >14/04/2021 06:55, Li Zhang:
> >> > > + * Example #2: GREEN - Do nothing, YELLOW - Do nothing, RED -
> DROP
> >> > > + *   struct rte_mtr_meter_policy_params policy_1 =
> >> > > + *                                   (struct
> >> > > rte_mtr_meter_policy_params) {
> >> > > + *           .actions[RTE_COLOR_GREEN] = NULL,
> >> > > + *           .actions[RTE_COLOR_YELLOW] = NULL,
> >> > > + *           .actions[RTE_COLOR_RED] = (struct rte_flow_action[]) {
> >> > > + *                   {
> >> > > + *                           .type = RTE_FLOW_ACTION_TYPE_DROP,
> >> > > + *                   },
> >> > > + *                   {
> >> > > + *                           .type = RTE_FLOW_ACTION_TYPE_END,
> >> > > + *                   },
> >> > > + *           },
> >> > > + *   };
> >> > > + *
> >> >
> >> > These two example policies should be available to be used straight
> >> > away, please make them real data structures, not comments.
> >
> >Wait, you are giving code examples as part of doxygen?
> >It's really too long, we don't do that.
> >
> >> > I suggest their names as: pass_color_policy_params and
> >> > drop_red_policy_params.
> >> >
> >> Thanks. Will change the names. But it can not be real data structures,
> since it
> >just one example define and no use code.
> >> It will bring build as below:
> >> error: 'drop_red_policy_params' defined but not used.
> >>  User can copy these example to his .c file when it using
> >rte_mtr_meter_policy_add().
> >

Although these could be looked at as examples, they are really more than examples: they are expected to be frequent policies that users would require, so it would be good to have them with the API itself.

Li, I agree we cannot instantiate structs in the header file, how about we place them as macros in the header file:

#define rte_mtr_policy_pass_color struct { \
...

#define rte_mtr_policy_drop_red struct { \
...

Regards,
Cristian

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

* Re: [dpdk-dev] [PATCH v6 1/2] ethdev: add pre-defined meter policy API
  2021-04-14  8:57   ` [dpdk-dev] [PATCH v6 1/2] ethdev: add pre-defined " Li Zhang
@ 2021-04-14 16:16     ` Dumitrescu, Cristian
  2021-04-15  1:59       ` Li Zhang
  2021-04-14 22:21     ` Singh, Jasvinder
  1 sibling, 1 reply; 78+ messages in thread
From: Dumitrescu, Cristian @ 2021-04-14 16:16 UTC (permalink / raw)
  To: Li Zhang, dekelp, orika, viacheslavo, matan, shahafs, lironh,
	jerinj, Yigit, Ferruh, ajit.khaparde, Wisam Jaddo, Li, Xiaoyun,
	Singh, Jasvinder, Thomas Monjalon, Andrew Rybchenko,
	Ray Kinsella, Neil Horman, Jerin Jacob, Hemant Agrawal
  Cc: dev, rasland, roniba, Haifei Luo, Jiawei Wang

Hi Li,

Following the API changes, there are lots of changes in the drivers, as expected, so we'll have to take the necessary time to review them.

Here are just a few comments below, please expect more during the next few days.

<snip>

> +
> +/* MTR meter policy add */
> +static int
> +pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
> +	uint32_t meter_policy_id,
> +	struct rte_mtr_meter_policy_params *policy,
> +	struct rte_mtr_error *error)
> +{
> +	struct pmd_internals *p = dev->data->dev_private;
> +	struct softnic_mtr_meter_policy_list *mpl = &p-
> >mtr.meter_policies;
> +	struct softnic_mtr_meter_policy *mp;
> +	const struct rte_flow_action *act;
> +	const struct rte_flow_action_meter_color *recolor;
> +	uint32_t i;
> +
> +	/* Meter policy ID must be valid. */
> +	if (meter_policy_id == UINT32_MAX)
> +		return -rte_mtr_error_set(error,
> +			EINVAL,
> +			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
> +			NULL,
> +			"Meter policy id not valid");

This is obviously not correct, we need to check whether the meter_policy_id provided by the user is already in use (by a policy previously added) or not. You can do this with the policy find function that you have already implemented.

> +
> +	for (i = 0; i < RTE_COLORS; i++) {
> +		act = policy->actions[i];
> +		if (act && act->type !=
> RTE_FLOW_ACTION_TYPE_METER_COLOR &&
> +			act->type != RTE_FLOW_ACTION_TYPE_DROP)
> +			return -rte_mtr_error_set(error,
> +				EINVAL,
> +				RTE_MTR_ERROR_TYPE_METER_POLICY,
> +				NULL,
> +				"Action invalid");
> +	}

This check does not look right either: obviously we cannot accept a null action list for any color, plus the action list should contain only those action types we support (RTE_FLOW_ACTION_TYPE_METER_COLOR or RTE_FLOW_ACTION_TYPE_DROP).

I agree, fist you need to check that the linked list of policy actions for each color is non-NULL, then you need to traverse it until you meet the END action, skip any PAD actions, then check that exactly one (and one only) of METER_COLOR or DROP exist, but not both at the same time, and also we don't have the same action showing up multiple times. Makes sense?

Regards,
Cristian

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

* Re: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy API
  2021-04-14 14:00             ` Dumitrescu, Cristian
@ 2021-04-14 16:21               ` Li Zhang
  0 siblings, 0 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-14 16:21 UTC (permalink / raw)
  To: Dumitrescu, Cristian, Asaf Penso, NBU-Contact-Thomas Monjalon
  Cc: Ori Kam, Slava Ovsiienko, Matan Azrad, lironh, Wisam Monther, Li,
	Xiaoyun, Singh, Jasvinder, Yigit, Ferruh, Andrew Rybchenko,
	Ray Kinsella, Jerin Jacob, Hemant Agrawal, dev, Raslan Darawsheh,
	Roni Bar Yanai, Haifei Luo, Jiawei(Jonny) Wang

Hi Cristian,

Thank you for giving suggestion.
Will add in V7 patch.

Regards,
Li Zhang
> -----Original Message-----
> From: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Sent: Wednesday, April 14, 2021 10:01 PM
> To: Asaf Penso <asafp@nvidia.com>; NBU-Contact-Thomas Monjalon
> <thomas@monjalon.net>; Li Zhang <lizh@nvidia.com>
> Cc: Ori Kam <orika@nvidia.com>; Slava Ovsiienko
> <viacheslavo@nvidia.com>; Matan Azrad <matan@nvidia.com>;
> lironh@marvell.com; Wisam Monther <wisamm@nvidia.com>; Li, Xiaoyun
> <xiaoyun.li@intel.com>; Singh, Jasvinder <jasvinder.singh@intel.com>; Yigit,
> Ferruh <ferruh.yigit@intel.com>; Andrew Rybchenko
> <andrew.rybchenko@oktetlabs.ru>; Ray Kinsella <mdr@ashroe.eu>; Jerin
> Jacob <jerinjacobk@gmail.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>; dev@dpdk.org; Raslan Darawsheh
> <rasland@nvidia.com>; Roni Bar Yanai <roniba@nvidia.com>; Haifei Luo
> <haifeil@nvidia.com>; Jiawei(Jonny) Wang <jiaweiw@nvidia.com>
> Subject: RE: [dpdk-dev] [PATCH v3 1/2] ethdev: add pre-defined meter policy
> API
> 
> External email: Use caution opening links or attachments
> 
> 
> > >14/04/2021 06:55, Li Zhang:
> > >> > > + * Example #2: GREEN - Do nothing, YELLOW - Do nothing, RED -
> > DROP
> > >> > > + *   struct rte_mtr_meter_policy_params policy_1 =
> > >> > > + *                                   (struct
> > >> > > rte_mtr_meter_policy_params) {
> > >> > > + *           .actions[RTE_COLOR_GREEN] = NULL,
> > >> > > + *           .actions[RTE_COLOR_YELLOW] = NULL,
> > >> > > + *           .actions[RTE_COLOR_RED] = (struct rte_flow_action[]) {
> > >> > > + *                   {
> > >> > > + *                           .type = RTE_FLOW_ACTION_TYPE_DROP,
> > >> > > + *                   },
> > >> > > + *                   {
> > >> > > + *                           .type = RTE_FLOW_ACTION_TYPE_END,
> > >> > > + *                   },
> > >> > > + *           },
> > >> > > + *   };
> > >> > > + *
> > >> >
> > >> > These two example policies should be available to be used
> > >> > straight away, please make them real data structures, not comments.
> > >
> > >Wait, you are giving code examples as part of doxygen?
> > >It's really too long, we don't do that.
> > >
> > >> > I suggest their names as: pass_color_policy_params and
> > >> > drop_red_policy_params.
> > >> >
> > >> Thanks. Will change the names. But it can not be real data
> > >> structures,
> > since it
> > >just one example define and no use code.
> > >> It will bring build as below:
> > >> error: 'drop_red_policy_params' defined but not used.
> > >>  User can copy these example to his .c file when it using
> > >rte_mtr_meter_policy_add().
> > >
> 
> Although these could be looked at as examples, they are really more than
> examples: they are expected to be frequent policies that users would require,
> so it would be good to have them with the API itself.
> 
> Li, I agree we cannot instantiate structs in the header file, how about we
> place them as macros in the header file:
> 
> #define rte_mtr_policy_pass_color struct { \ ...
> 
> #define rte_mtr_policy_drop_red struct { \ ...
> 
> Regards,
> Cristian

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

* Re: [dpdk-dev] [PATCH v6 1/2] ethdev: add pre-defined meter policy API
  2021-04-14  8:57   ` [dpdk-dev] [PATCH v6 1/2] ethdev: add pre-defined " Li Zhang
  2021-04-14 16:16     ` Dumitrescu, Cristian
@ 2021-04-14 22:21     ` Singh, Jasvinder
  2021-04-15  2:00       ` Li Zhang
  1 sibling, 1 reply; 78+ messages in thread
From: Singh, Jasvinder @ 2021-04-14 22:21 UTC (permalink / raw)
  To: Li Zhang, dekelp, orika, viacheslavo, matan, shahafs, Dumitrescu,
	Cristian, lironh, jerinj, Yigit, Ferruh, ajit.khaparde,
	Wisam Jaddo, Li, Xiaoyun, Thomas Monjalon, Andrew Rybchenko,
	Ray Kinsella, Neil Horman
  Cc: dev, rasland, roniba, Haifei Luo, Jiawei Wang


<snip>

> +/* MTR meter policy add */
> +static int
> +pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
> +	uint32_t meter_policy_id,
> +	struct rte_mtr_meter_policy_params *policy,
> +	struct rte_mtr_error *error)
> +{
> +	struct pmd_internals *p = dev->data->dev_private;
> +	struct softnic_mtr_meter_policy_list *mpl = &p-
> >mtr.meter_policies;
> +	struct softnic_mtr_meter_policy *mp;
> +	const struct rte_flow_action *act;
> +	const struct rte_flow_action_meter_color *recolor;
> +	uint32_t i;
> +
> +	/* Meter policy ID must be valid. */
> +	if (meter_policy_id == UINT32_MAX)
> +		return -rte_mtr_error_set(error,
> +			EINVAL,
> +			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
> +			NULL,
> +			"Meter policy id not valid");

Add check for "policy",  could be null, before dereferencing this.    


<snip>
> 
> -/* 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");

Please add check whether MTR object is already set to meter policy  id,  return success if true, no need to continue.
if (m->params.meter_policy_id == meter_policy_id)
		return 0;

>  	/* MTR object owner valid? */
>  	if (m->flow) {



Regards,
Jasvinder

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

* Re: [dpdk-dev] [PATCH v6 1/2] ethdev: add pre-defined meter policy API
  2021-04-14 16:16     ` Dumitrescu, Cristian
@ 2021-04-15  1:59       ` Li Zhang
  0 siblings, 0 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-15  1:59 UTC (permalink / raw)
  To: Dumitrescu, Cristian, dekelp, Ori Kam, Slava Ovsiienko,
	Matan Azrad, Shahaf Shuler, lironh, jerinj, Yigit, Ferruh,
	ajit.khaparde, Wisam Monther, Li, Xiaoyun, Singh, Jasvinder,
	NBU-Contact-Thomas Monjalon, Andrew Rybchenko, Ray Kinsella,
	Neil Horman, Jerin Jacob, Hemant Agrawal
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai, Haifei Luo, Jiawei(Jonny) Wang

Thanks Cristian.
Will change it in V7 patch.

Regards,
Li Zhang

> -----Original Message-----
> From: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Sent: Thursday, April 15, 2021 12:16 AM
> To: Li Zhang <lizh@nvidia.com>; dekelp@nvidia.com; Ori Kam
> <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; Matan
> Azrad <matan@nvidia.com>; Shahaf Shuler <shahafs@nvidia.com>;
> lironh@marvell.com; jerinj@marvell.com; Yigit, Ferruh
> <ferruh.yigit@intel.com>; ajit.khaparde@broadcom.com; Wisam Monther
> <wisamm@nvidia.com>; Li, Xiaoyun <xiaoyun.li@intel.com>; Singh,
> Jasvinder <jasvinder.singh@intel.com>; NBU-Contact-Thomas Monjalon
> <thomas@monjalon.net>; Andrew Rybchenko
> <andrew.rybchenko@oktetlabs.ru>; Ray Kinsella <mdr@ashroe.eu>; Neil
> Horman <nhorman@tuxdriver.com>; Jerin Jacob <jerinjacobk@gmail.com>;
> Hemant Agrawal <hemant.agrawal@nxp.com>
> Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar Yanai
> <roniba@nvidia.com>; Haifei Luo <haifeil@nvidia.com>; Jiawei(Jonny) Wang
> <jiaweiw@nvidia.com>
> Subject: RE: [PATCH v6 1/2] ethdev: add pre-defined meter policy API
> 
> External email: Use caution opening links or attachments
> 
> 
> Hi Li,
> 
> Following the API changes, there are lots of changes in the drivers, as
> expected, so we'll have to take the necessary time to review them.
> 
> Here are just a few comments below, please expect more during the next
> few days.
> 
> <snip>
> 
> > +
> > +/* MTR meter policy add */
> > +static int
> > +pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
> > +     uint32_t meter_policy_id,
> > +     struct rte_mtr_meter_policy_params *policy,
> > +     struct rte_mtr_error *error)
> > +{
> > +     struct pmd_internals *p = dev->data->dev_private;
> > +     struct softnic_mtr_meter_policy_list *mpl = &p-
> > >mtr.meter_policies;
> > +     struct softnic_mtr_meter_policy *mp;
> > +     const struct rte_flow_action *act;
> > +     const struct rte_flow_action_meter_color *recolor;
> > +     uint32_t i;
> > +
> > +     /* Meter policy ID must be valid. */
> > +     if (meter_policy_id == UINT32_MAX)
> > +             return -rte_mtr_error_set(error,
> > +                     EINVAL,
> > +                     RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
> > +                     NULL,
> > +                     "Meter policy id not valid");
> 
> This is obviously not correct, we need to check whether the meter_policy_id
> provided by the user is already in use (by a policy previously added) or not.
> You can do this with the policy find function that you have already
> implemented.
> 
> > +
> > +     for (i = 0; i < RTE_COLORS; i++) {
> > +             act = policy->actions[i];
> > +             if (act && act->type !=
> > RTE_FLOW_ACTION_TYPE_METER_COLOR &&
> > +                     act->type != RTE_FLOW_ACTION_TYPE_DROP)
> > +                     return -rte_mtr_error_set(error,
> > +                             EINVAL,
> > +                             RTE_MTR_ERROR_TYPE_METER_POLICY,
> > +                             NULL,
> > +                             "Action invalid");
> > +     }
> 
> This check does not look right either: obviously we cannot accept a null
> action list for any color, plus the action list should contain only those action
> types we support (RTE_FLOW_ACTION_TYPE_METER_COLOR or
> RTE_FLOW_ACTION_TYPE_DROP).
> 
> I agree, fist you need to check that the linked list of policy actions for each
> color is non-NULL, then you need to traverse it until you meet the END
> action, skip any PAD actions, then check that exactly one (and one only) of
> METER_COLOR or DROP exist, but not both at the same time, and also we
> don't have the same action showing up multiple times. Makes sense?
> 
> Regards,
> Cristian

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

* Re: [dpdk-dev] [PATCH v6 1/2] ethdev: add pre-defined meter policy API
  2021-04-14 22:21     ` Singh, Jasvinder
@ 2021-04-15  2:00       ` Li Zhang
  0 siblings, 0 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-15  2:00 UTC (permalink / raw)
  To: Singh, Jasvinder, dekelp, Ori Kam, Slava Ovsiienko, Matan Azrad,
	Shahaf Shuler, Dumitrescu, Cristian, lironh, jerinj, Yigit,
	Ferruh, ajit.khaparde, Wisam Monther, Li, Xiaoyun,
	NBU-Contact-Thomas Monjalon, Andrew Rybchenko, Ray Kinsella,
	Neil Horman
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai, Haifei Luo, Jiawei(Jonny) Wang

Thanks Jasvinder.
Will change it in V7 patch.

Regards,
Li Zhang

> -----Original Message-----
> From: Singh, Jasvinder <jasvinder.singh@intel.com>
> Sent: Thursday, April 15, 2021 6:22 AM
> To: Li Zhang <lizh@nvidia.com>; dekelp@nvidia.com; Ori Kam
> <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; Matan
> Azrad <matan@nvidia.com>; Shahaf Shuler <shahafs@nvidia.com>;
> Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; lironh@marvell.com;
> jerinj@marvell.com; Yigit, Ferruh <ferruh.yigit@intel.com>;
> ajit.khaparde@broadcom.com; Wisam Monther <wisamm@nvidia.com>; Li,
> Xiaoyun <xiaoyun.li@intel.com>; NBU-Contact-Thomas Monjalon
> <thomas@monjalon.net>; 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>; Jiawei(Jonny) Wang
> <jiaweiw@nvidia.com>
> Subject: RE: [PATCH v6 1/2] ethdev: add pre-defined meter policy API
> 
> External email: Use caution opening links or attachments
> 
> 
> <snip>
> 
> > +/* MTR meter policy add */
> > +static int
> > +pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
> > +     uint32_t meter_policy_id,
> > +     struct rte_mtr_meter_policy_params *policy,
> > +     struct rte_mtr_error *error)
> > +{
> > +     struct pmd_internals *p = dev->data->dev_private;
> > +     struct softnic_mtr_meter_policy_list *mpl = &p-
> > >mtr.meter_policies;
> > +     struct softnic_mtr_meter_policy *mp;
> > +     const struct rte_flow_action *act;
> > +     const struct rte_flow_action_meter_color *recolor;
> > +     uint32_t i;
> > +
> > +     /* Meter policy ID must be valid. */
> > +     if (meter_policy_id == UINT32_MAX)
> > +             return -rte_mtr_error_set(error,
> > +                     EINVAL,
> > +                     RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
> > +                     NULL,
> > +                     "Meter policy id not valid");
> 
> Add check for "policy",  could be null, before dereferencing this.
> 
> 
> <snip>
> >
> > -/* 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");
> 
> Please add check whether MTR object is already set to meter policy  id,
> return success if true, no need to continue.
> if (m->params.meter_policy_id == meter_policy_id)
>                 return 0;
> 
> >       /* MTR object owner valid? */
> >       if (m->flow) {
> 
> 
> 
> Regards,
> Jasvinder

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

* [dpdk-dev] [PATCH v7 0/2] Support meter policy API
  2021-03-18  8:58 [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API Li Zhang
                   ` (6 preceding siblings ...)
  2021-04-14  8:57 ` [dpdk-dev] [PATCH v6 0/2] Support meter policy API Li Zhang
@ 2021-04-15  4:54 ` Li Zhang
  2021-04-15  4:54   ` [dpdk-dev] [PATCH v7 1/2] ethdev: add pre-defined " Li Zhang
  2021-04-15  4:54   ` [dpdk-dev] [PATCH v7 2/2] app/testpmd: support policy actions per color Li Zhang
  2021-04-15  9:20 ` [dpdk-dev] [PATCH v8 0/2] Support meter policy API Li Zhang
  2021-04-20 17:56 ` [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined " Stephen Hemminger
  9 siblings, 2 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-15  4:54 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, cristian.dumitrescu,
	lironh, jerinj, ferruh.yigit, ajit.khaparde
  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.

Add two common policy template as macros in the header file,

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

Depends-on: series=16351  ("Add ASO meter support in MLX5 PMD ")
https://patchwork.dpdk.org/project/dpdk/list/?series=16351

V2: Delete default policy and change relation doc files.
V3: Fix coding style issues.
V4: Fix comments about Depends-on
V5: Fix comments about rte_mtr_meter_policy_add.
V6: Delete policy example.
V7: Fix comments and place two common policy template as macros.

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                        |  14 +-
 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                         |  32 ++
 app/test-pmd/testpmd.h                        |   2 +
 doc/guides/prog_guide/rte_flow.rst            |  21 +
 .../traffic_metering_and_policing.rst         |  16 +-
 doc/guides/rel_notes/release_21_05.rst        |  22 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  48 +-
 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   | 290 ++++++++---
 lib/librte_ethdev/rte_flow.h                  |  22 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 224 +++++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   5 +-
 25 files changed, 873 insertions(+), 1271 deletions(-)

-- 
2.27.0


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

* [dpdk-dev] [PATCH v7 1/2] ethdev: add pre-defined meter policy API
  2021-04-15  4:54 ` [dpdk-dev] [PATCH v7 0/2] Support meter policy API Li Zhang
@ 2021-04-15  4:54   ` Li Zhang
  2021-04-15  4:54   ` [dpdk-dev] [PATCH v7 2/2] app/testpmd: support policy actions per color Li Zhang
  1 sibling, 0 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-15  4:54 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, cristian.dumitrescu,
	lironh, jerinj, ferruh.yigit, ajit.khaparde, Wisam Jaddo,
	Xiaoyun Li, Jasvinder Singh, Thomas Monjalon, Andrew Rybchenko,
	Ray Kinsella, Neil Horman
  Cc: dev, rasland, roniba, Haifei Luo, Jiawei Wang

Currently, the flow meter policy does not support multiple actions
per color; also the allowed action types per color are very limited.
In addition, the policy cannot be pre-defined.

Due to the growing in flow actions offload abilities there is a potential
for the user to use variety of actions per color differently.
This new meter policy API comes to allow this potential in the most ethdev
common way using rte_flow action definition.
A list of rte_flow actions will be provided by the user per color
in order to create a meter policy.
In addition, the API forces to pre-define the policy before
the meters creation in order to allow sharing of single policy
with multiple meters efficiently.

meter_policy_id is added into struct rte_mtr_params.
So that it can get the policy during the meters creation.

Allow coloring the packet using a new rte_flow_action_color
as could be done by the old policy API.

Add two common policy template as macros in the head file.

The next API function were added:
- rte_mtr_meter_policy_add
- rte_mtr_meter_policy_delete
- rte_mtr_meter_policy_update
- rte_mtr_meter_policy_validate
The next struct was changed:
- rte_mtr_params
- rte_mtr_capabilities
The next API was deleted:
- rte_mtr_policer_actions_update

To support this API the following app were changed:
app/test-flow-perf: clean meter policer
app/testpmd: clean meter policer

To support this API the following drivers were changed:
net/softnic: support meter policy API
1. cleans meter rte_mtr_policer_action.
2. Support policy API to get color action as policer action did.
   The color action will be mapped into rte_table_action_policer.

net/mlx5: clean meter creation management
Cleans and breaks part of the current meter management
in order to allow better design with policy API.

Signed-off-by: Li Zhang <lizh@nvidia.com>
Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
Acked-by: Ray Kinsella <mdr@ashroe.eu>
---
 app/test-flow-perf/main.c                     |   7 -
 app/test-pmd/cmdline.c                        |   1 -
 app/test-pmd/cmdline_mtr.c                    | 172 -------
 app/test-pmd/cmdline_mtr.h                    |   1 -
 doc/guides/prog_guide/rte_flow.rst            |  21 +
 .../traffic_metering_and_policing.rst         |  16 +-
 doc/guides/rel_notes/release_21_05.rst        |  22 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  18 -
 drivers/net/mlx5/mlx5.h                       |  24 +-
 drivers/net/mlx5/mlx5_flow.c                  |  46 --
 drivers/net/mlx5/mlx5_flow.h                  |  18 +-
 drivers/net/mlx5/mlx5_flow_aso.c              |   8 +-
 drivers/net/mlx5/mlx5_flow_dv.c               | 461 +-----------------
 drivers/net/mlx5/mlx5_flow_meter.c            | 369 +-------------
 drivers/net/softnic/rte_eth_softnic_flow.c    |  19 +-
 .../net/softnic/rte_eth_softnic_internals.h   |  18 +-
 drivers/net/softnic/rte_eth_softnic_meter.c   | 290 ++++++++---
 lib/librte_ethdev/rte_flow.h                  |  22 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 224 +++++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   5 +-
 22 files changed, 604 insertions(+), 1257 deletions(-)

diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c
index 8e229679df..9be8edc31d 100644
--- a/app/test-flow-perf/main.c
+++ b/app/test-flow-perf/main.c
@@ -928,13 +928,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 56cf0bf405..0bb6394314 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -17071,7 +17071,6 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_del_port_meter,
 	(cmdline_parse_inst_t *)&cmd_set_port_meter_profile,
 	(cmdline_parse_inst_t *)&cmd_set_port_meter_dscp_table,
-	(cmdline_parse_inst_t *)&cmd_set_port_meter_policer_action,
 	(cmdline_parse_inst_t *)&cmd_set_port_meter_stats_mask,
 	(cmdline_parse_inst_t *)&cmd_show_port_meter_stats,
 	(cmdline_parse_inst_t *)&cmd_mcast_addr,
diff --git a/app/test-pmd/cmdline_mtr.c b/app/test-pmd/cmdline_mtr.c
index 3982787d20..44394e3ea1 100644
--- a/app/test-pmd/cmdline_mtr.c
+++ b/app/test-pmd/cmdline_mtr.c
@@ -146,53 +146,6 @@ parse_meter_color_str(char *c_str, uint32_t *use_prev_meter_color,
 	return 0;
 }
 
-static int
-string_to_policer_action(char *s)
-{
-	if ((strcmp(s, "G") == 0) || (strcmp(s, "g") == 0))
-		return MTR_POLICER_ACTION_COLOR_GREEN;
-
-	if ((strcmp(s, "Y") == 0) || (strcmp(s, "y") == 0))
-		return MTR_POLICER_ACTION_COLOR_YELLOW;
-
-	if ((strcmp(s, "R") == 0) || (strcmp(s, "r") == 0))
-		return MTR_POLICER_ACTION_COLOR_RED;
-
-	if ((strcmp(s, "D") == 0) || (strcmp(s, "d") == 0))
-		return MTR_POLICER_ACTION_DROP;
-
-	return -1;
-}
-
-static int
-parse_policer_action_string(char *p_str, uint32_t action_mask,
-	enum rte_mtr_policer_action actions[])
-{
-	char *token;
-	int count = __builtin_popcount(action_mask);
-	int g_color = 0, y_color = 0, action, i;
-
-	for (i = 0; i < count; i++) {
-		token = strtok_r(p_str, PARSE_DELIMITER, &p_str);
-		if (token ==  NULL)
-			return -1;
-
-		action = string_to_policer_action(token);
-		if (action == -1)
-			return -1;
-
-		if (g_color == 0 && (action_mask & 0x1)) {
-			actions[RTE_COLOR_GREEN] = action;
-			g_color = 1;
-		} else if (y_color == 0 && (action_mask & 0x2)) {
-			actions[RTE_COLOR_YELLOW] = action;
-			y_color = 1;
-		} else
-			actions[RTE_COLOR_RED] = action;
-	}
-	return 0;
-}
-
 static int
 parse_multi_token_string(char *t_str, uint16_t *port_id,
 	uint32_t *mtr_id, enum rte_color **dscp_table)
@@ -302,10 +255,6 @@ static void cmd_show_port_meter_cap_parsed(void *parsed_result,
 		cap.color_aware_trtcm_rfc2698_supported);
 	printf("cap.color_aware_trtcm_rfc4115_supported %" PRId32 "\n",
 		cap.color_aware_trtcm_rfc4115_supported);
-	printf("cap.policer_action_recolor_supported %" PRId32 "\n",
-		cap.policer_action_recolor_supported);
-	printf("cap.policer_action_drop_supported %" PRId32 "\n",
-		cap.policer_action_drop_supported);
 	printf("cap.stats_mask %" PRIx64 "\n", cap.stats_mask);
 }
 
@@ -808,12 +757,6 @@ static void cmd_create_port_meter_parsed(void *parsed_result,
 	else
 		params.meter_enable = 0;
 
-	params.action[RTE_COLOR_GREEN] =
-		string_to_policer_action(res->g_action);
-	params.action[RTE_COLOR_YELLOW] =
-		string_to_policer_action(res->y_action);
-	params.action[RTE_COLOR_RED] =
-		string_to_policer_action(res->r_action);
 	params.stats_mask = res->statistics_mask;
 
 	ret = rte_mtr_create(port_id, mtr_id, &params, shared, &error);
@@ -1181,121 +1124,6 @@ cmdline_parse_inst_t cmd_set_port_meter_dscp_table = {
 	},
 };
 
-/* *** Set Port Meter Policer Action *** */
-struct cmd_set_port_meter_policer_action_result {
-	cmdline_fixed_string_t set;
-	cmdline_fixed_string_t port;
-	cmdline_fixed_string_t meter;
-	cmdline_fixed_string_t policer;
-	cmdline_fixed_string_t action;
-	uint16_t port_id;
-	uint32_t mtr_id;
-	uint32_t action_mask;
-	cmdline_multi_string_t policer_action;
-};
-
-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_set =
-	TOKEN_STRING_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, set, "set");
-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_port =
-	TOKEN_STRING_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, port, "port");
-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_meter =
-	TOKEN_STRING_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, meter,
-		"meter");
-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_policer =
-	TOKEN_STRING_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, policer,
-		"policer");
-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_action =
-	TOKEN_STRING_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, action,
-		"action");
-cmdline_parse_token_num_t cmd_set_port_meter_policer_action_port_id =
-	TOKEN_NUM_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, port_id,
-		RTE_UINT16);
-cmdline_parse_token_num_t cmd_set_port_meter_policer_action_mtr_id =
-	TOKEN_NUM_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, mtr_id,
-		RTE_UINT32);
-cmdline_parse_token_num_t cmd_set_port_meter_policer_action_action_mask =
-	TOKEN_NUM_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, action_mask,
-		RTE_UINT32);
-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_policer_action =
-	TOKEN_STRING_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result,
-		policer_action, TOKEN_STRING_MULTI);
-
-static void cmd_set_port_meter_policer_action_parsed(void *parsed_result,
-	__rte_unused struct cmdline *cl,
-	__rte_unused void *data)
-{
-	struct cmd_set_port_meter_policer_action_result *res = parsed_result;
-	enum rte_mtr_policer_action *actions;
-	struct rte_mtr_error error;
-	uint32_t mtr_id = res->mtr_id;
-	uint32_t action_mask = res->action_mask;
-	uint16_t port_id = res->port_id;
-	char *p_str = res->policer_action;
-	int ret;
-
-	if (port_id_is_invalid(port_id, ENABLED_WARN))
-		return;
-
-	/* Check: action mask */
-	if (action_mask == 0 || (action_mask & (~0x7UL))) {
-		printf(" Policer action mask not correct (error)\n");
-		return;
-	}
-
-	/* Allocate memory for policer actions */
-	actions = (enum rte_mtr_policer_action *)malloc(RTE_COLORS *
-		sizeof(enum rte_mtr_policer_action));
-	if (actions == NULL) {
-		printf("Memory for policer actions not allocated (error)\n");
-		return;
-	}
-	/* Parse policer action string */
-	ret = parse_policer_action_string(p_str, action_mask, actions);
-	if (ret) {
-		printf(" Policer action string parse error\n");
-		free(actions);
-		return;
-	}
-
-	ret = rte_mtr_policer_actions_update(port_id, mtr_id,
-		action_mask, actions, &error);
-	if (ret != 0) {
-		free(actions);
-		print_err_msg(&error);
-		return;
-	}
-
-	free(actions);
-}
-
-cmdline_parse_inst_t cmd_set_port_meter_policer_action = {
-	.f = cmd_set_port_meter_policer_action_parsed,
-	.data = NULL,
-	.help_str = "set port meter policer action <port_id> <mtr_id> "
-		"<action_mask> <action0> [<action1> <action2>]",
-	.tokens = {
-		(void *)&cmd_set_port_meter_policer_action_set,
-		(void *)&cmd_set_port_meter_policer_action_port,
-		(void *)&cmd_set_port_meter_policer_action_meter,
-		(void *)&cmd_set_port_meter_policer_action_policer,
-		(void *)&cmd_set_port_meter_policer_action_action,
-		(void *)&cmd_set_port_meter_policer_action_port_id,
-		(void *)&cmd_set_port_meter_policer_action_mtr_id,
-		(void *)&cmd_set_port_meter_policer_action_action_mask,
-		(void *)&cmd_set_port_meter_policer_action_policer_action,
-		NULL,
-	},
-};
-
 /* *** Set Port Meter Stats Mask *** */
 struct cmd_set_port_meter_stats_mask_result {
 	cmdline_fixed_string_t set;
diff --git a/app/test-pmd/cmdline_mtr.h b/app/test-pmd/cmdline_mtr.h
index e69d6da023..7e2713cea3 100644
--- a/app/test-pmd/cmdline_mtr.h
+++ b/app/test-pmd/cmdline_mtr.h
@@ -17,7 +17,6 @@ extern cmdline_parse_inst_t cmd_disable_port_meter;
 extern cmdline_parse_inst_t cmd_del_port_meter;
 extern cmdline_parse_inst_t cmd_set_port_meter_profile;
 extern cmdline_parse_inst_t cmd_set_port_meter_dscp_table;
-extern cmdline_parse_inst_t cmd_set_port_meter_policer_action;
 extern cmdline_parse_inst_t cmd_set_port_meter_stats_mask;
 extern cmdline_parse_inst_t cmd_show_port_meter_stats;
 
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index e1b93ecedf..2f5a6e0c31 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -2841,6 +2841,27 @@ for ``RTE_FLOW_FIELD_VALUE`` and ``RTE_FLOW_FIELD_POINTER`` respectively.
    | ``value``     | immediate value or a pointer to this value               |
    +---------------+----------------------------------------------------------+
 
+Action: ``METER_COLOR``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Color the packet to reflect the meter color result.
+
+The meter action must be configured before meter color action.
+Meter color action is set to a color to reflect the meter color result.
+Set the meter color in the mbuf to the selected color.
+The meter color action output color is the output color of the packet,
+which is set in the packet meta-data (i.e. struct ``rte_mbuf::sched::color``)
+
+.. _table_rte_flow_action_meter_color:
+
+.. table:: METER_COLOR
+
+   +-----------------+--------------+
+   | Field           | Value        |
+   +=================+==============+
+   | ``meter_color`` | Packet color |
+   +-----------------+--------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/doc/guides/prog_guide/traffic_metering_and_policing.rst b/doc/guides/prog_guide/traffic_metering_and_policing.rst
index 90c781eb1d..c0537e653c 100644
--- a/doc/guides/prog_guide/traffic_metering_and_policing.rst
+++ b/doc/guides/prog_guide/traffic_metering_and_policing.rst
@@ -56,18 +56,10 @@ The processing done for each input packet hitting an MTR object is:
   color blind mode, which is equivalent to considering all input packets
   initially colored as green.
 
-* Policing: There is a separate policer action configured for each meter
-  output color, which can:
-
-  * Drop the packet.
-
-  * Keep the same packet color: the policer output color matches the meter
-    output color (essentially a no-op action).
-
-  * Recolor the packet: the policer output color is set to a different color
-    than the meter output color. The policer output color is the output color
-    of the packet, which is set in the packet meta-data (i.e. struct
-    ``rte_mbuf::sched::color``).
+* There is a meter policy API to manage pre-defined policies for meter.
+  Any rte_flow action list can be configured per color for each policy.
+  A meter object configured with a policy executes the actions per packet
+  according to the packet color.
 
 * Statistics: The set of counters maintained for each MTR object is
   configurable and subject to the implementation support. This set includes
diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst
index a0b907994a..5c4617d236 100644
--- a/doc/guides/rel_notes/release_21_05.rst
+++ b/doc/guides/rel_notes/release_21_05.rst
@@ -174,7 +174,27 @@ New Features
     ``dpdk-testpmd -- --eth-link-speed N``
   * Added command to display Rx queue used descriptor count.
     ``show port (port_id) rxq (queue_id) desc used count``
-
+  * deleted the port meter policer action command .
+    ``set port meter policer action (port_id) (mtr_id) (action_mask) ...``
+  * Added command to create meter policy.
+    ``add port meter policy (port_id) (policy_id) g_actions {action} end y_actions {action} end r_actions {action} end``
+  * Added command to delete meter policy.
+    ``del port meter policy (port_id) (policy_id)``
+
+* **Updated meter API.**
+
+  * ethdev: Deleted meter policer API to support policy API.
+    ``rte_mtr_policer_actions_update()``
+  * ethdev: Added meter API to support pre-defined policy, rte_flow action list per color.
+    ``rte_mtr_meter_policy_add()``, ``rte_mtr_meter_policy_delete()`` and
+    ``rte_mtr_create_with_policy()``
+  * ethdev: Removed rte_mtr_policer_action from rte_mtr_params structures.
+  * ethdev: Added rte_mtr_meter_policy_params structures to support policy API.
+  * ethdev: Added meter_policy_id into rte_mtr_params structures.
+  * ethdev: Removed policer_action_recolor_supported and policer_action_drop_supported from rte_mtr_capabilities structures.
+  * ethdev: Added meter_policy_n_max into rte_mtr_capabilities structures.
+  * ethdev: Added RTE_FLOW_ACTION_TYPE_METER_COLOR in enum rte_flow_action_type.
+  * ethdev: Added RTE_MTR_ERROR_TYPE_METER_POLICY_ID and RTE_MTR_ERROR_TYPE_METER_POLICY_ID into rte_mtr_error_type.
 
 Removed Items
 -------------
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 36f0a328a5..3f7a1c0e33 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2830,24 +2830,6 @@ Set meter dscp table for the ethernet device::
    testpmd> set port meter dscp table (port_id) (mtr_id) [(dscp_tbl_entry0) \
    (dscp_tbl_entry1)...(dscp_tbl_entry63)]
 
-set port meter policer action
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Set meter policer action for the ethernet device::
-
-   testpmd> set port meter policer action (port_id) (mtr_id) (action_mask) \
-   (action0) [(action1) (action1)]
-
-where:
-
-* ``action_mask``: Bit mask indicating which policer actions need to be
-  updated. One or more policer actions can be updated in a single function
-  invocation. To update the policer action associated with color C, bit
-  (1 << C) needs to be set in *action_mask* and element at position C
-  in the *actions* array needs to be valid.
-* ``actionx``: Policer action for the color x,
-  RTE_MTR_GREEN <= x < RTE_MTR_COLORS
-
 set port meter stats mask
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 9a02aa4488..a8e11023cc 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -584,14 +584,6 @@ struct mlx5_dev_shared_port {
 /* Modify this value if enum rte_mtr_color changes. */
 #define RTE_MTR_DROPPED RTE_COLORS
 
-/* Meter policer statistics */
-struct mlx5_flow_policer_stats {
-	uint32_t pass_cnt;
-	/**< Color counter for pass. */
-	uint32_t drop_cnt;
-	/**< Color counter for drop. */
-};
-
 /* Meter table structure. */
 struct mlx5_meter_domain_info {
 	struct mlx5_flow_tbl_resource *tbl;
@@ -630,24 +622,12 @@ struct mlx5_meter_domains_infos {
 
 /* Meter parameter structure. */
 struct mlx5_flow_meter_info {
-	uint32_t meter_id;
-	/**< Meter id. */
 	struct mlx5_flow_meter_profile *profile;
 	/**< Meter profile parameters. */
 	rte_spinlock_t sl; /**< Meter action spinlock. */
-	/** Policer actions (per meter output color). */
-	enum rte_mtr_policer_action action[RTE_COLORS];
 	/** Set of stats counters to be enabled.
 	 * @see enum rte_mtr_stats_type
 	 */
-	uint32_t green_bytes:1;
-	/** Set green bytes stats to be enabled. */
-	uint32_t green_pkts:1;
-	/** Set green packets stats to be enabled. */
-	uint32_t red_bytes:1;
-	/** Set red bytes stats to be enabled. */
-	uint32_t red_pkts:1;
-	/** Set red packets stats to be enabled. */
 	uint32_t bytes_dropped:1;
 	/** Set bytes dropped stats to be enabled. */
 	uint32_t pkts_dropped:1;
@@ -682,8 +662,8 @@ struct mlx5_flow_meter_info {
 	uint32_t transfer:1;
 	struct mlx5_meter_domains_infos *mfts;
 	/**< Flow table created for this meter. */
-	struct mlx5_flow_policer_stats policer_stats;
-	/**< Meter policer statistics. */
+	uint32_t drop_cnt;
+	/**< Color counter for drop. */
 	uint32_t ref_cnt;
 	/**< Use count. */
 	struct mlx5_indexed_pool *flow_ipool;
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 242c6f2288..ee2c351649 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -6647,52 +6647,6 @@ mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,
 	return fops->destroy_mtr_tbls(dev, tbls);
 }
 
-/**
- * Prepare policer rules.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] attr
- *   Pointer to flow attributes.
- *
- * @return
- *   0 on success, -1 otherwise.
- */
-int
-mlx5_flow_prepare_policer_rules(struct rte_eth_dev *dev,
-			       struct mlx5_flow_meter_info *fm,
-			       const struct rte_flow_attr *attr)
-{
-	const struct mlx5_flow_driver_ops *fops;
-
-	fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
-	return fops->prepare_policer_rules(dev, fm, attr);
-}
-
-/**
- * Destroy policer rules.
- *
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] attr
- *   Pointer to flow attributes.
- *
- * @return
- *   0 on success, -1 otherwise.
- */
-int
-mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,
-				struct mlx5_flow_meter_info *fm,
-				const struct rte_flow_attr *attr)
-{
-	const struct mlx5_flow_driver_ops *fops;
-
-	fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
-	return fops->destroy_policer_rules(dev, fm, attr);
-}
-
 /**
  * Allocate the needed aso flow meter id.
  *
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index cb2803d080..7fa15eef7b 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -839,6 +839,8 @@ struct mlx5_legacy_flow_meter {
 	/* Must be the first in struct. */
 	TAILQ_ENTRY(mlx5_legacy_flow_meter) next;
 	/**< Pointer to the next flow meter structure. */
+	uint32_t meter_id;
+	/**< Meter id. */
 	uint32_t idx; /* Index to meter object. */
 };
 
@@ -1097,14 +1099,6 @@ typedef struct mlx5_meter_domains_infos *(*mlx5_flow_create_mtr_tbls_t)
 					    (struct rte_eth_dev *dev);
 typedef int (*mlx5_flow_destroy_mtr_tbls_t)(struct rte_eth_dev *dev,
 					struct mlx5_meter_domains_infos *tbls);
-typedef int (*mlx5_flow_create_policer_rules_t)
-					(struct rte_eth_dev *dev,
-					 struct mlx5_flow_meter_info *fm,
-					 const struct rte_flow_attr *attr);
-typedef int (*mlx5_flow_destroy_policer_rules_t)
-					(struct rte_eth_dev *dev,
-					 const struct mlx5_flow_meter_info *fm,
-					 const struct rte_flow_attr *attr);
 typedef uint32_t (*mlx5_flow_mtr_alloc_t)
 					    (struct rte_eth_dev *dev);
 typedef void (*mlx5_flow_mtr_free_t)(struct rte_eth_dev *dev,
@@ -1161,8 +1155,6 @@ struct mlx5_flow_driver_ops {
 	mlx5_flow_query_t query;
 	mlx5_flow_create_mtr_tbls_t create_mtr_tbls;
 	mlx5_flow_destroy_mtr_tbls_t destroy_mtr_tbls;
-	mlx5_flow_create_policer_rules_t prepare_policer_rules;
-	mlx5_flow_destroy_policer_rules_t destroy_policer_rules;
 	mlx5_flow_mtr_alloc_t create_meter;
 	mlx5_flow_mtr_free_t free_meter;
 	mlx5_flow_counter_alloc_t counter_alloc;
@@ -1392,12 +1384,6 @@ struct mlx5_meter_domains_infos *mlx5_flow_create_mtr_tbls
 					(struct rte_eth_dev *dev);
 int mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,
 			       struct mlx5_meter_domains_infos *tbl);
-int mlx5_flow_prepare_policer_rules(struct rte_eth_dev *dev,
-				   struct mlx5_flow_meter_info *fm,
-				   const struct rte_flow_attr *attr);
-int mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,
-				    struct mlx5_flow_meter_info *fm,
-				    const struct rte_flow_attr *attr);
 int mlx5_flow_meter_flush(struct rte_eth_dev *dev,
 			  struct rte_mtr_error *error);
 int mlx5_flow_dv_discover_counter_offset_support(struct rte_eth_dev *dev);
diff --git a/drivers/net/mlx5/mlx5_flow_aso.c b/drivers/net/mlx5/mlx5_flow_aso.c
index cd2cc016b9..62d2df054b 100644
--- a/drivers/net/mlx5/mlx5_flow_aso.c
+++ b/drivers/net/mlx5/mlx5_flow_aso.c
@@ -808,8 +808,8 @@ mlx5_aso_meter_update_by_wqe(struct mlx5_dev_ctx_shared *sh,
 		/* Waiting for wqe resource. */
 		rte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
 	} while (--poll_wqe_times);
-	DRV_LOG(ERR, "Fail to send WQE for ASO meter %d",
-			mtr->fm.meter_id);
+	DRV_LOG(ERR, "Fail to send WQE for ASO meter offset %d",
+			mtr->offset);
 	return -1;
 }
 
@@ -844,7 +844,7 @@ mlx5_aso_mtr_wait(struct mlx5_dev_ctx_shared *sh,
 		/* Waiting for CQE ready. */
 		rte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
 	} while (--poll_cqe_times);
-	DRV_LOG(ERR, "Fail to poll CQE ready for ASO meter %d",
-			mtr->fm.meter_id);
+	DRV_LOG(ERR, "Fail to poll CQE ready for ASO meter offset %d",
+			mtr->offset);
 	return -1;
 }
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index d8ea440668..af3397fb55 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -184,31 +184,6 @@ flow_dv_attr_init(const struct rte_flow_item *item, union flow_dv_attr *attr,
 	attr->valid = 1;
 }
 
-/**
- * Convert rte_mtr_color to mlx5 color.
- *
- * @param[in] rcol
- *   rte_mtr_color.
- *
- * @return
- *   mlx5 color.
- */
-static int
-rte_col_2_mlx5_col(enum rte_color rcol)
-{
-	switch (rcol) {
-	case RTE_COLOR_GREEN:
-		return MLX5_FLOW_COLOR_GREEN;
-	case RTE_COLOR_YELLOW:
-		return MLX5_FLOW_COLOR_YELLOW;
-	case RTE_COLOR_RED:
-		return MLX5_FLOW_COLOR_RED;
-	default:
-		break;
-	}
-	return MLX5_FLOW_COLOR_UNDEFINED;
-}
-
 struct field_modify_info {
 	uint32_t size; /* Size of field in protocol header, in bytes. */
 	uint32_t offset; /* Offset of field in protocol header, in bytes. */
@@ -6025,12 +6000,10 @@ flow_dv_mtr_pool_create(struct rte_eth_dev *dev,
 	mtrmng->n_valid++;
 	for (i = 1; i < MLX5_ASO_MTRS_PER_POOL; ++i) {
 		pool->mtrs[i].offset = i;
-		pool->mtrs[i].fm.meter_id = UINT32_MAX;
 		LIST_INSERT_HEAD(&mtrmng->meters,
 						&pool->mtrs[i], next);
 	}
 	pool->mtrs[0].offset = 0;
-	pool->mtrs[0].fm.meter_id = UINT32_MAX;
 	*mtr_free = &pool->mtrs[0];
 	return pool;
 }
@@ -6054,7 +6027,6 @@ flow_dv_aso_mtr_release_to_pool(struct rte_eth_dev *dev, uint32_t mtr_idx)
 	rte_spinlock_lock(&mtrmng->mtrsl);
 	memset(&aso_mtr->fm, 0, sizeof(struct mlx5_flow_meter_info));
 	aso_mtr->state = ASO_METER_FREE;
-	aso_mtr->fm.meter_id = UINT32_MAX;
 	LIST_INSERT_HEAD(&mtrmng->meters, aso_mtr, next);
 	rte_spinlock_unlock(&mtrmng->mtrsl);
 }
@@ -6094,8 +6066,8 @@ flow_dv_mtr_alloc(struct rte_eth_dev *dev)
 	mtr_free->state = ASO_METER_WAIT;
 	rte_spinlock_unlock(&mtrmng->mtrsl);
 	pool = container_of(mtr_free,
-					struct mlx5_aso_mtr_pool,
-					mtrs[mtr_free->offset]);
+			struct mlx5_aso_mtr_pool,
+			mtrs[mtr_free->offset]);
 	mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, mtr_free->offset);
 	if (!mtr_free->fm.meter_action) {
 #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
@@ -13702,433 +13674,6 @@ flow_dv_create_mtr_tbl(struct rte_eth_dev *dev)
 	return NULL;
 }
 
-/**
- * Destroy the meter table matchers.
- * Lock free, (mutex should be acquired by caller).
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in,out] dtb
- *   Pointer to DV meter table.
- *
- * @return
- *   Always 0.
- */
-static int
-flow_dv_destroy_mtr_matchers(struct rte_eth_dev *dev,
-			     struct mlx5_meter_domain_info *dtb)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_flow_tbl_data_entry *tbl;
-
-	if (!priv->config.dv_flow_en)
-		return 0;
-	if (dtb->drop_matcher) {
-		tbl = container_of(dtb->drop_matcher->tbl, typeof(*tbl), tbl);
-		mlx5_cache_unregister(&tbl->matchers,
-				      &dtb->drop_matcher->entry);
-		dtb->drop_matcher = NULL;
-	}
-	if (dtb->color_matcher) {
-		tbl = container_of(dtb->color_matcher->tbl, typeof(*tbl), tbl);
-		mlx5_cache_unregister(&tbl->matchers,
-				      &dtb->color_matcher->entry);
-		dtb->color_matcher = NULL;
-	}
-	return 0;
-}
-
-/**
- * Create the matchers for meter table.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] color_reg_c_idx
- *   Reg C index for color match.
- * @param[in] mtr_id_reg_c_idx
- *   Reg C index for meter_id match.
- * @param[in] mtr_id_mask
- *   Mask for meter_id match criteria.
- * @param[in,out] dtb
- *   Pointer to DV meter table.
- * @param[out] error
- *   Perform verbose error reporting if not NULL.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-flow_dv_prepare_mtr_matchers(struct rte_eth_dev *dev,
-			     uint32_t color_reg_c_idx,
-			     uint32_t mtr_id_reg_c_idx,
-			     uint32_t mtr_id_mask,
-			     struct mlx5_meter_domain_info *dtb,
-			     struct rte_flow_error *error)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_flow_tbl_data_entry *tbl_data;
-	struct mlx5_cache_entry *entry;
-	struct mlx5_flow_dv_matcher matcher = {
-		.mask = {
-			.size = sizeof(matcher.mask.buf) -
-				MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-		},
-		.tbl = dtb->tbl,
-	};
-	struct mlx5_flow_dv_match_params value = {
-		.size = sizeof(value.buf) -
-			MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-	};
-	struct mlx5_flow_cb_ctx ctx = {
-		.error = error,
-		.data = &matcher,
-	};
-	uint32_t color_mask = (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
-
-	tbl_data = container_of(dtb->tbl, struct mlx5_flow_tbl_data_entry, tbl);
-	if (!dtb->drop_matcher) {
-		/* Create matchers for Drop. */
-		flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-				       mtr_id_reg_c_idx, 0, mtr_id_mask);
-		matcher.priority = MLX5_REG_BITS * 2 - priv->max_mtr_bits;
-		matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
-					matcher.mask.size);
-		entry = mlx5_cache_register(&tbl_data->matchers, &ctx);
-		if (!entry) {
-			DRV_LOG(ERR, "Failed to register meter drop matcher.");
-			return -1;
-		}
-		dtb->drop_matcher =
-			container_of(entry, struct mlx5_flow_dv_matcher, entry);
-	}
-	if (!dtb->color_matcher) {
-		/* Create matchers for Color + meter_id. */
-		if (priv->mtr_reg_share) {
-			flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-					color_reg_c_idx, 0,
-					(mtr_id_mask | color_mask));
-		} else {
-			flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-					color_reg_c_idx, 0, color_mask);
-			flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-					mtr_id_reg_c_idx, 0, mtr_id_mask);
-		}
-		matcher.priority = MLX5_REG_BITS - priv->max_mtr_bits;
-		matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
-					matcher.mask.size);
-		entry = mlx5_cache_register(&tbl_data->matchers, &ctx);
-		if (!entry) {
-			DRV_LOG(ERR, "Failed to register meter color matcher.");
-			return -1;
-		}
-		dtb->color_matcher =
-			container_of(entry, struct mlx5_flow_dv_matcher, entry);
-	}
-	return 0;
-}
-
-/**
- * Destroy domain policer rule.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] dt
- *   Pointer to domain table.
- */
-static void
-flow_dv_destroy_domain_policer_rule(struct rte_eth_dev *dev,
-				    struct mlx5_meter_domain_info *dt)
-{
-	if (dt->drop_rule) {
-		claim_zero(mlx5_flow_os_destroy_flow(dt->drop_rule));
-		dt->drop_rule = NULL;
-	}
-	if (dt->green_rule) {
-		claim_zero(mlx5_flow_os_destroy_flow(dt->green_rule));
-		dt->green_rule = NULL;
-	}
-	flow_dv_destroy_mtr_matchers(dev, dt);
-	if (dt->jump_actn) {
-		claim_zero(mlx5_flow_os_destroy_flow_action(dt->jump_actn));
-		dt->jump_actn = NULL;
-	}
-}
-
-/**
- * Destroy policer rules.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] attr
- *   Pointer to flow attributes.
- *
- * @return
- *   Always 0.
- */
-static int
-flow_dv_destroy_policer_rules(struct rte_eth_dev *dev,
-			      const struct mlx5_flow_meter_info *fm,
-			      const struct rte_flow_attr *attr)
-{
-	struct mlx5_meter_domains_infos *mtb = fm ? fm->mfts : NULL;
-
-	if (!mtb)
-		return 0;
-	if (attr->egress)
-		flow_dv_destroy_domain_policer_rule(dev, &mtb->egress);
-	if (attr->ingress)
-		flow_dv_destroy_domain_policer_rule(dev, &mtb->ingress);
-	if (attr->transfer)
-		flow_dv_destroy_domain_policer_rule(dev, &mtb->transfer);
-	return 0;
-}
-
-/**
- * Create specify domain meter policer rule.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] mtr_idx
- *   meter index.
- * @param[in] mtb
- *   Pointer to DV meter table set.
- * @param[out] drop_rule
- *   The address of pointer saving drop rule.
- * @param[out] color_rule
- *   The address of pointer saving green rule.
- *
- * @return
- *   0 on success, -1 otherwise.
- */
-static int
-flow_dv_create_policer_forward_rule(struct rte_eth_dev *dev,
-				    struct mlx5_flow_meter_info *fm,
-				    uint32_t mtr_idx,
-				    struct mlx5_meter_domain_info *dtb,
-				    void **drop_rule,
-				    void **green_rule)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_flow_dv_match_params matcher = {
-		.size = sizeof(matcher.buf) -
-			MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-	};
-	struct mlx5_flow_dv_match_params value = {
-		.size = sizeof(value.buf) -
-			MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-	};
-	struct mlx5_meter_domains_infos *mtb = fm->mfts;
-	struct rte_flow_error error;
-	uint32_t color_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR,
-						    0, &error);
-	uint32_t mtr_id_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_ID,
-						     0, &error);
-	uint8_t mtr_id_offset = priv->mtr_reg_share ? MLX5_MTR_COLOR_BITS : 0;
-	uint32_t mtr_id_mask =
-		((UINT32_C(1) << priv->max_mtr_bits) - 1) << mtr_id_offset;
-	void *actions[METER_ACTIONS];
-	int i;
-	int ret = 0;
-
-	/* Create jump action. */
-	if (!dtb->jump_actn)
-		ret = mlx5_flow_os_create_flow_action_dest_flow_tbl
-				(dtb->sfx_tbl->obj, &dtb->jump_actn);
-	if (ret) {
-		DRV_LOG(ERR, "Failed to create policer jump action.");
-		goto error;
-	}
-	/* Prepare matchers. */
-	if (!dtb->drop_matcher || !dtb->color_matcher) {
-		ret = flow_dv_prepare_mtr_matchers(dev, color_reg_c,
-						   mtr_id_reg_c, mtr_id_mask,
-						   dtb, &error);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to setup matchers for mtr table.");
-			goto error;
-		}
-	}
-	/* Create Drop flow, matching meter_id only. */
-	i = 0;
-	flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c,
-			       (mtr_idx << mtr_id_offset), UINT32_MAX);
-	if (mtb->drop_count)
-		actions[i++] = mtb->drop_count;
-	actions[i++] = priv->sh->dr_drop_action;
-	ret = mlx5_flow_os_create_flow(dtb->drop_matcher->matcher_object,
-				       (void *)&value, i, actions, drop_rule);
-	if (ret) {
-		DRV_LOG(ERR, "Failed to create meter policer drop rule.");
-		goto error;
-	}
-	/* Create flow matching Green color + meter_id. */
-	i = 0;
-	if (priv->mtr_reg_share) {
-		flow_dv_match_meta_reg(matcher.buf, value.buf, color_reg_c,
-				       ((mtr_idx << mtr_id_offset) |
-					rte_col_2_mlx5_col(RTE_COLOR_GREEN)),
-				       UINT32_MAX);
-	} else {
-		flow_dv_match_meta_reg(matcher.buf, value.buf, color_reg_c,
-				       rte_col_2_mlx5_col(RTE_COLOR_GREEN),
-				       UINT32_MAX);
-		flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c,
-				       mtr_idx, UINT32_MAX);
-	}
-	if (mtb->green_count)
-		actions[i++] = mtb->green_count;
-	actions[i++] = dtb->jump_actn;
-	ret = mlx5_flow_os_create_flow(dtb->color_matcher->matcher_object,
-				       (void *)&value, i, actions, green_rule);
-	if (ret) {
-		DRV_LOG(ERR, "Failed to create meter policer color rule.");
-		goto error;
-	}
-	return 0;
-error:
-	rte_errno = errno;
-	return -1;
-}
-
-/**
- * Prepare policer rules for all domains.
- * If meter already initialized, this will replace all old rules with new ones.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] attr
- *   Pointer to flow attributes.
- *
- * @return
- *   0 on success, -1 otherwise.
- */
-static int
-flow_dv_prepare_policer_rules(struct rte_eth_dev *dev,
-			      struct mlx5_flow_meter_info *fm,
-			      const struct rte_flow_attr *attr)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_meter_domains_infos *mtb = fm->mfts;
-	bool initialized = false;
-	struct mlx5_flow_counter *cnt;
-	void *egress_drop_rule = NULL;
-	void *egress_green_rule = NULL;
-	void *ingress_drop_rule = NULL;
-	void *ingress_green_rule = NULL;
-	void *transfer_drop_rule = NULL;
-	void *transfer_green_rule = NULL;
-	uint32_t mtr_idx;
-	int ret;
-
-	/* Get the statistics counters for green/drop. */
-	if (fm->policer_stats.pass_cnt) {
-		cnt = flow_dv_counter_get_by_idx(dev,
-					fm->policer_stats.pass_cnt,
-					NULL);
-		mtb->green_count = cnt->action;
-	} else {
-		mtb->green_count = NULL;
-	}
-	if (fm->policer_stats.drop_cnt) {
-		cnt = flow_dv_counter_get_by_idx(dev,
-					fm->policer_stats.drop_cnt,
-					NULL);
-		mtb->drop_count = cnt->action;
-	} else {
-		mtb->drop_count = NULL;
-	}
-	/**
-	 * If flow meter has been initialized, all policer rules
-	 * are created. So can get if meter initialized by checking
-	 * any policer rule.
-	 */
-	if (mtb->egress.drop_rule)
-		initialized = true;
-	if (priv->sh->meter_aso_en) {
-		struct mlx5_aso_mtr *aso_mtr = NULL;
-		struct mlx5_aso_mtr_pool *pool;
-
-		aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
-		pool = container_of(aso_mtr, struct mlx5_aso_mtr_pool,
-				    mtrs[aso_mtr->offset]);
-		mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, aso_mtr->offset);
-	} else {
-		struct mlx5_legacy_flow_meter *legacy_fm;
-
-		legacy_fm = container_of(fm, struct mlx5_legacy_flow_meter, fm);
-		mtr_idx = legacy_fm->idx;
-	}
-	if (attr->egress) {
-		ret = flow_dv_create_policer_forward_rule(dev,
-				fm, mtr_idx, &mtb->egress,
-				&egress_drop_rule, &egress_green_rule);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to create egress policer.");
-			goto error;
-		}
-	}
-	if (attr->ingress) {
-		ret = flow_dv_create_policer_forward_rule(dev,
-				fm, mtr_idx, &mtb->ingress,
-				&ingress_drop_rule, &ingress_green_rule);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to create ingress policer.");
-			goto error;
-		}
-	}
-	if (attr->transfer) {
-		ret = flow_dv_create_policer_forward_rule(dev,
-				fm, mtr_idx, &mtb->transfer,
-				&transfer_drop_rule, &transfer_green_rule);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to create transfer policer.");
-			goto error;
-		}
-	}
-	/* Replace old flows if existing. */
-	if (mtb->egress.drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->egress.drop_rule));
-	if (mtb->egress.green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->egress.green_rule));
-	if (mtb->ingress.drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->ingress.drop_rule));
-	if (mtb->ingress.green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->ingress.green_rule));
-	if (mtb->transfer.drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->transfer.drop_rule));
-	if (mtb->transfer.green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->transfer.green_rule));
-	mtb->egress.drop_rule = egress_drop_rule;
-	mtb->egress.green_rule = egress_green_rule;
-	mtb->ingress.drop_rule = ingress_drop_rule;
-	mtb->ingress.green_rule = ingress_green_rule;
-	mtb->transfer.drop_rule = transfer_drop_rule;
-	mtb->transfer.green_rule = transfer_green_rule;
-	return 0;
-error:
-	if (egress_drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(egress_drop_rule));
-	if (egress_green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(egress_green_rule));
-	if (ingress_drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(ingress_drop_rule));
-	if (ingress_green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(ingress_green_rule));
-	if (transfer_drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(transfer_drop_rule));
-	if (transfer_green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(transfer_green_rule));
-	if (!initialized)
-		flow_dv_destroy_policer_rules(dev, fm, attr);
-	return -1;
-}
-
 /**
  * Validate the batch counter support in root table.
  *
@@ -14423,8 +13968,6 @@ const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {
 	.query = flow_dv_query,
 	.create_mtr_tbls = flow_dv_create_mtr_tbl,
 	.destroy_mtr_tbls = flow_dv_destroy_mtr_tbl,
-	.prepare_policer_rules = flow_dv_prepare_policer_rules,
-	.destroy_policer_rules = flow_dv_destroy_policer_rules,
 	.create_meter = flow_dv_mtr_alloc,
 	.free_meter = flow_dv_aso_mtr_release_to_pool,
 	.counter_alloc = flow_dv_counter_allocate,
diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c
index 714b382d55..af0a1c18cb 100644
--- a/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/drivers/net/mlx5/mlx5_flow_meter.c
@@ -329,7 +329,6 @@ mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
 	cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
 	cap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap->n_max : 0;
 	cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */
-	cap->policer_action_drop_supported = 1;
 	cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED |
 			  RTE_MTR_STATS_N_PKTS_DROPPED;
 	return 0;
@@ -436,90 +435,6 @@ mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,
 	return 0;
 }
 
-/**
- * Convert wrong color setting action to verbose error.
- *
- * @param[in] action
- *   Policy color action.
- *
- * @return
- *   Verbose meter color error type.
- */
-static inline enum rte_mtr_error_type
-action2error(enum rte_mtr_policer_action action)
-{
-	switch (action) {
-	case MTR_POLICER_ACTION_COLOR_GREEN:
-		return RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN;
-	case MTR_POLICER_ACTION_COLOR_YELLOW:
-		return RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW;
-	case MTR_POLICER_ACTION_COLOR_RED:
-		return RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED;
-	default:
-		break;
-	}
-	return RTE_MTR_ERROR_TYPE_UNSPECIFIED;
-}
-
-/**
- * Check meter validation.
- *
- * @param[in] priv
- *   Pointer to mlx5 private data structure.
- * @param[in] meter_id
- *   Meter id.
- * @param[in] params
- *   Pointer to rte meter parameters.
- * @param[out] error
- *   Pointer to rte meter error structure.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,
-			 struct rte_mtr_params *params,
-			 struct rte_mtr_error *error)
-{
-	/* Meter must use global drop action. */
-	if (!priv->sh->dr_drop_action)
-		return -rte_mtr_error_set(error, ENOTSUP,
-					  RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-					  NULL,
-					  "No drop action ready for meter.");
-	/* Meter params must not be NULL. */
-	if (params == NULL)
-		return -rte_mtr_error_set(error, EINVAL,
-					  RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-					  NULL, "Meter object params null.");
-	/* Previous meter color is not supported. */
-	if (params->use_prev_mtr_color)
-		return -rte_mtr_error_set(error, ENOTSUP,
-					  RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-					  NULL,
-					  "Previous meter color "
-					  "not supported.");
-	/* Validate policer settings. */
-	if (params->action[RTE_COLOR_RED] != MTR_POLICER_ACTION_DROP)
-		return -rte_mtr_error_set
-				(error, ENOTSUP,
-				 action2error(params->action[RTE_COLOR_RED]),
-				 NULL,
-				 "Red color only supports drop action.");
-	if (params->action[RTE_COLOR_GREEN] != MTR_POLICER_ACTION_COLOR_GREEN)
-		return -rte_mtr_error_set
-				(error, ENOTSUP,
-				 action2error(params->action[RTE_COLOR_GREEN]),
-				 NULL,
-				 "Green color only supports recolor green action.");
-	/* Validate meter id. */
-	if (mlx5_flow_meter_find(priv, meter_id, NULL))
-		return -rte_mtr_error_set(error, EEXIST,
-					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
-					  "Meter object already exists.");
-	return 0;
-}
-
 /**
  * Modify the flow meter action.
  *
@@ -629,167 +544,14 @@ static void
 mlx5_flow_meter_stats_enable_update(struct mlx5_flow_meter_info *fm,
 				uint64_t stats_mask)
 {
-	fm->green_bytes = (stats_mask & RTE_MTR_STATS_N_BYTES_GREEN) ? 1 : 0;
-	fm->green_pkts = (stats_mask & RTE_MTR_STATS_N_PKTS_GREEN) ? 1 : 0;
-	fm->red_bytes = (stats_mask & RTE_MTR_STATS_N_BYTES_RED) ? 1 : 0;
-	fm->red_pkts = (stats_mask & RTE_MTR_STATS_N_PKTS_RED) ? 1 : 0;
 	fm->bytes_dropped =
 		(stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) ? 1 : 0;
 	fm->pkts_dropped = (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED) ? 1 : 0;
 }
 
-/**
- * Create meter rules.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] meter_id
- *   Meter id.
- * @param[in] params
- *   Pointer to rte meter parameters.
- * @param[in] shared
- *   Meter shared with other flow or not.
- * @param[out] error
- *   Pointer to rte meter error structure.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
-		       struct rte_mtr_params *params, int shared,
-		       struct rte_mtr_error *error)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
-	struct mlx5_flow_meter_profile *fmp;
-	struct mlx5_legacy_flow_meter *legacy_fm;
-	struct mlx5_flow_meter_info *fm;
-	const struct rte_flow_attr attr = {
-				.ingress = 1,
-				.egress = 1,
-				.transfer = priv->config.dv_esw_en ? 1 : 0,
-			};
-	struct mlx5_indexed_pool_config flow_ipool_cfg = {
-		.size = 0,
-		.trunk_size = 64,
-		.need_lock = 1,
-		.type = "mlx5_flow_mtr_flow_id_pool",
-	};
-	struct mlx5_aso_mtr *aso_mtr;
-	union mlx5_l3t_data data;
-	uint32_t mtr_idx;
-	int ret;
-	uint8_t mtr_id_bits;
-	uint8_t mtr_reg_bits = priv->mtr_reg_share ?
-				MLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS;
-
-	if (!priv->mtr_en)
-		return -rte_mtr_error_set(error, ENOTSUP,
-					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Meter is not supported");
-	/* Validate the parameters. */
-	ret = mlx5_flow_meter_validate(priv, meter_id, params, error);
-	if (ret)
-		return ret;
-	/* Meter profile must exist. */
-	fmp = mlx5_flow_meter_profile_find(priv, params->meter_profile_id);
-	if (fmp == NULL)
-		return -rte_mtr_error_set(error, ENOENT,
-					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-					  NULL, "Meter profile id not valid.");
-	/* Allocate the flow meter memory. */
-	if (priv->sh->meter_aso_en) {
-		mtr_idx = mlx5_flow_mtr_alloc(dev);
-		if (!mtr_idx)
-			return -rte_mtr_error_set(error, ENOMEM,
-				RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-				"Memory alloc failed for meter.");
-		aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
-		fm = &aso_mtr->fm;
-	} else {
-		legacy_fm = mlx5_ipool_zmalloc
-				(priv->sh->ipool[MLX5_IPOOL_MTR], &mtr_idx);
-		if (legacy_fm == NULL)
-			return -rte_mtr_error_set(error, ENOMEM,
-				RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-				"Memory alloc failed for meter.");
-		legacy_fm->idx = mtr_idx;
-		fm = &legacy_fm->fm;
-	}
-	mtr_id_bits = MLX5_REG_BITS - __builtin_clz(mtr_idx);
-	if ((mtr_id_bits + priv->max_mtr_flow_bits) > mtr_reg_bits) {
-		DRV_LOG(ERR, "Meter number exceeds max limit.");
-		goto error;
-	}
-	if (mtr_id_bits > priv->max_mtr_bits)
-		priv->max_mtr_bits = mtr_id_bits;
-	/* Fill the flow meter parameters. */
-	fm->meter_id = meter_id;
-	fm->profile = fmp;
-	memcpy(fm->action, params->action, sizeof(params->action));
-	mlx5_flow_meter_stats_enable_update(fm, params->stats_mask);
-	/* Alloc policer counters. */
-	if (fm->green_bytes || fm->green_pkts) {
-		fm->policer_stats.pass_cnt = mlx5_counter_alloc(dev);
-		if (!fm->policer_stats.pass_cnt)
-			goto error;
-	}
-	if (fm->red_bytes || fm->red_pkts ||
-	    fm->bytes_dropped || fm->pkts_dropped) {
-		fm->policer_stats.drop_cnt = mlx5_counter_alloc(dev);
-		if (!fm->policer_stats.drop_cnt)
-			goto error;
-	}
-	fm->mfts = mlx5_flow_create_mtr_tbls(dev);
-	if (!fm->mfts)
-		goto error;
-	ret = mlx5_flow_prepare_policer_rules(dev, fm, &attr);
-	if (ret)
-		goto error;
-	/* Add to the flow meter list. */
-	if (!priv->sh->meter_aso_en)
-		TAILQ_INSERT_TAIL(fms, legacy_fm, next);
-	fm->active_state = 1; /* Config meter starts as active. */
-	fm->is_enable = 1;
-	fm->shared = !!shared;
-	__atomic_add_fetch(&fm->profile->ref_cnt, 1, __ATOMIC_RELAXED);
-	fm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg);
-	if (!fm->flow_ipool)
-		goto error;
-	rte_spinlock_init(&fm->sl);
-	/* If ASO meter supported, allocate ASO flow meter. */
-	if (priv->sh->meter_aso_en) {
-		aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
-		ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
-		if (ret)
-			goto error;
-		data.dword = mtr_idx;
-		if (mlx5_l3t_set_entry(priv->mtr_idx_tbl, meter_id, &data))
-			goto error;
-	}
-	return 0;
-error:
-	mlx5_flow_destroy_policer_rules(dev, fm, &attr);
-	mlx5_flow_destroy_mtr_tbls(dev, fm->mfts);
-	/* Free policer counters. */
-	if (fm->policer_stats.pass_cnt)
-		mlx5_counter_free(dev, fm->policer_stats.pass_cnt);
-	if (fm->policer_stats.drop_cnt)
-		mlx5_counter_free(dev, fm->policer_stats.drop_cnt);
-	if (priv->sh->meter_aso_en)
-		mlx5_flow_mtr_free(dev, mtr_idx);
-	else
-		mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], mtr_idx);
-	return -rte_mtr_error_set(error, -ret,
-				  RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Failed to create devx meter.");
-}
-
 static int
 mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
 			struct mlx5_flow_meter_info *fm,
-			const struct rte_flow_attr *attr,
 			uint32_t mtr_idx)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
@@ -810,15 +572,12 @@ mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
 		legacy_fm = container_of(fm, struct mlx5_legacy_flow_meter, fm);
 		TAILQ_REMOVE(fms, legacy_fm, next);
 	}
-	/* Free policer counters. */
-	if (fm->policer_stats.pass_cnt)
-		mlx5_counter_free(dev, fm->policer_stats.pass_cnt);
-	if (fm->policer_stats.drop_cnt)
-		mlx5_counter_free(dev, fm->policer_stats.drop_cnt);
+	/* Free drop counters. */
+	if (fm->drop_cnt)
+		mlx5_counter_free(dev, fm->drop_cnt);
 	/* Free meter flow table. */
 	if (fm->flow_ipool)
 		mlx5_ipool_destroy(fm->flow_ipool);
-	mlx5_flow_destroy_policer_rules(dev, fm, attr);
 	mlx5_flow_destroy_mtr_tbls(dev, fm->mfts);
 	if (priv->sh->meter_aso_en)
 		mlx5_flow_mtr_free(dev, mtr_idx);
@@ -847,11 +606,6 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_flow_meter_info *fm;
-	const struct rte_flow_attr attr = {
-				.ingress = 1,
-				.egress = 1,
-				.transfer = priv->config.dv_esw_en ? 1 : 0,
-			};
 	uint32_t mtr_idx = 0;
 
 	if (!priv->mtr_en)
@@ -876,7 +630,7 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
 				"Fail to delete ASO Meter in index table.");
 	}
 	/* Destroy the meter profile. */
-	if (mlx5_flow_meter_params_flush(dev, fm, &attr, mtr_idx))
+	if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
 		return -rte_mtr_error_set(error, EINVAL,
 					RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
 					NULL, "MTR object meter profile invalid.");
@@ -1102,13 +856,6 @@ mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_flow_meter_info *fm;
-	const struct rte_flow_attr attr = {
-				.ingress = 1,
-				.egress = 1,
-				.transfer = priv->config.dv_esw_en ? 1 : 0,
-			};
-	bool need_updated = false;
-	struct mlx5_flow_policer_stats old_policer_stats;
 
 	if (!priv->mtr_en)
 		return -rte_mtr_error_set(error, ENOTSUP,
@@ -1120,69 +867,6 @@ mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
 		return -rte_mtr_error_set(error, ENOENT,
 					  RTE_MTR_ERROR_TYPE_MTR_ID,
 					  NULL, "Meter object id not valid.");
-	old_policer_stats.pass_cnt = 0;
-	old_policer_stats.drop_cnt = 0;
-	if (!!((RTE_MTR_STATS_N_PKTS_GREEN |
-				RTE_MTR_STATS_N_BYTES_GREEN) & stats_mask) !=
-		!!fm->policer_stats.pass_cnt) {
-		need_updated = true;
-		if (fm->policer_stats.pass_cnt) {
-			old_policer_stats.pass_cnt = fm->policer_stats.pass_cnt;
-			fm->policer_stats.pass_cnt = 0;
-		} else {
-			fm->policer_stats.pass_cnt =
-				mlx5_counter_alloc(dev);
-			if (!fm->policer_stats.pass_cnt)
-				return -rte_mtr_error_set(error, ENOMEM,
-					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Counter alloc failed for meter.");
-		}
-	}
-	if (!!((RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_BYTES_RED |
-		RTE_MTR_STATS_N_PKTS_DROPPED | RTE_MTR_STATS_N_BYTES_DROPPED) &
-		stats_mask) !=
-		!!fm->policer_stats.drop_cnt) {
-		need_updated = true;
-		if (fm->policer_stats.drop_cnt) {
-			old_policer_stats.drop_cnt = fm->policer_stats.drop_cnt;
-			fm->policer_stats.drop_cnt = 0;
-		} else {
-			fm->policer_stats.drop_cnt =
-				mlx5_counter_alloc(dev);
-			if (!fm->policer_stats.drop_cnt)
-				return -rte_mtr_error_set(error, ENOMEM,
-					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Counter alloc failed for meter.");
-		}
-	}
-	if (need_updated) {
-		if (mlx5_flow_prepare_policer_rules(dev, fm, &attr)) {
-			if (fm->policer_stats.pass_cnt &&
-				fm->policer_stats.pass_cnt !=
-				old_policer_stats.pass_cnt)
-				mlx5_counter_free(dev,
-					fm->policer_stats.pass_cnt);
-			fm->policer_stats.pass_cnt =
-					old_policer_stats.pass_cnt;
-			if (fm->policer_stats.drop_cnt &&
-				fm->policer_stats.drop_cnt !=
-				old_policer_stats.drop_cnt)
-				mlx5_counter_free(dev,
-					fm->policer_stats.drop_cnt);
-			fm->policer_stats.pass_cnt =
-					old_policer_stats.pass_cnt;
-			return -rte_mtr_error_set(error, ENOTSUP,
-				RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-				NULL, "Failed to create meter policer rules.");
-		}
-		/* Free old policer counters. */
-		if (old_policer_stats.pass_cnt)
-			mlx5_counter_free(dev,
-				old_policer_stats.pass_cnt);
-		if (old_policer_stats.drop_cnt)
-			mlx5_counter_free(dev,
-				old_policer_stats.drop_cnt);
-	}
 	mlx5_flow_meter_stats_enable_update(fm, stats_mask);
 	return 0;
 }
@@ -1216,7 +900,6 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_flow_meter_info *fm;
-	struct mlx5_flow_policer_stats *ps;
 	uint64_t pkts;
 	uint64_t bytes;
 	int ret = 0;
@@ -1231,35 +914,14 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
 		return -rte_mtr_error_set(error, ENOENT,
 					  RTE_MTR_ERROR_TYPE_MTR_ID,
 					  NULL, "Meter object id not valid.");
-	ps = &fm->policer_stats;
 	*stats_mask = 0;
-	if (fm->green_bytes)
-		*stats_mask |= RTE_MTR_STATS_N_BYTES_GREEN;
-	if (fm->green_pkts)
-		*stats_mask |= RTE_MTR_STATS_N_PKTS_GREEN;
-	if (fm->red_bytes)
-		*stats_mask |= RTE_MTR_STATS_N_BYTES_RED;
-	if (fm->red_pkts)
-		*stats_mask |= RTE_MTR_STATS_N_PKTS_RED;
 	if (fm->bytes_dropped)
 		*stats_mask |= RTE_MTR_STATS_N_BYTES_DROPPED;
 	if (fm->pkts_dropped)
 		*stats_mask |= RTE_MTR_STATS_N_PKTS_DROPPED;
 	memset(stats, 0, sizeof(*stats));
-	if (ps->pass_cnt) {
-		ret = mlx5_counter_query(dev, ps->pass_cnt, clear, &pkts,
-						 &bytes);
-		if (ret)
-			goto error;
-		/* If need to read the packets, set it. */
-		if (fm->green_pkts)
-			stats->n_pkts[RTE_COLOR_GREEN] = pkts;
-		/* If need to read the bytes, set it. */
-		if (fm->green_bytes)
-			stats->n_bytes[RTE_COLOR_GREEN] = bytes;
-	}
-	if (ps->drop_cnt) {
-		ret = mlx5_counter_query(dev, ps->drop_cnt, clear, &pkts,
+	if (fm->drop_cnt) {
+		ret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts,
 						 &bytes);
 		if (ret)
 			goto error;
@@ -1273,20 +935,18 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
 	return 0;
 error:
 	return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,
-				 "Failed to read policer counters.");
+				 "Failed to read meter drop counters.");
 }
 
 static const struct rte_mtr_ops mlx5_flow_mtr_ops = {
 	.capabilities_get = mlx5_flow_mtr_cap_get,
 	.meter_profile_add = mlx5_flow_meter_profile_add,
 	.meter_profile_delete = mlx5_flow_meter_profile_delete,
-	.create = mlx5_flow_meter_create,
 	.destroy = mlx5_flow_meter_destroy,
 	.meter_enable = mlx5_flow_meter_enable,
 	.meter_disable = mlx5_flow_meter_disable,
 	.meter_profile_update = mlx5_flow_meter_profile_update,
 	.meter_dscp_table_update = NULL,
-	.policer_actions_update = NULL,
 	.stats_update = mlx5_flow_meter_stats_update,
 	.stats_read = mlx5_flow_meter_stats_read,
 };
@@ -1344,12 +1004,11 @@ mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
 		aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
 		/* Remove reference taken by the mlx5_l3t_get_entry. */
 		mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);
-		MLX5_ASSERT(meter_id == aso_mtr->fm.meter_id);
 		rte_spinlock_unlock(&mtrmng->mtrsl);
 		return &aso_mtr->fm;
 	}
 	TAILQ_FOREACH(legacy_fm, fms, next)
-		if (meter_id == legacy_fm->fm.meter_id) {
+		if (meter_id == legacy_fm->meter_id) {
 			if (mtr_idx)
 				*mtr_idx = legacy_fm->idx;
 			return &legacy_fm->fm;
@@ -1517,11 +1176,6 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
 	struct mlx5_legacy_flow_meter *legacy_fm;
 	struct mlx5_flow_meter_info *fm;
 	struct mlx5_aso_mtr_pool *mtr_pool;
-	const struct rte_flow_attr attr = {
-				.ingress = 1,
-				.egress = 1,
-				.transfer = priv->config.dv_esw_en ? 1 : 0,
-			};
 	void *tmp;
 	uint32_t i, offset, mtr_idx;
 
@@ -1533,9 +1187,8 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
 				offset++) {
 				fm = &mtr_pool->mtrs[offset].fm;
 				mtr_idx = MLX5_MAKE_MTR_IDX(i, offset);
-				if (fm->meter_id != UINT32_MAX &&
-					mlx5_flow_meter_params_flush(dev,
-						fm, &attr, mtr_idx))
+				if (mlx5_flow_meter_params_flush(dev,
+						fm, mtr_idx))
 					return -rte_mtr_error_set
 					(error, EINVAL,
 					RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
@@ -1545,7 +1198,7 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
 	} else {
 		TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) {
 			fm = &legacy_fm->fm;
-			if (mlx5_flow_meter_params_flush(dev, fm, &attr, 0))
+			if (mlx5_flow_meter_params_flush(dev, fm, 0))
 				return -rte_mtr_error_set(error, EINVAL,
 					RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
 					NULL, "MTR object meter profile invalid.");
diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index 7925bad1c0..27eaf380cd 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -1166,6 +1166,7 @@ flow_rule_action_get(struct pmd_internals *softnic,
 {
 	struct softnic_table_action_profile *profile;
 	struct softnic_table_action_profile_params *params;
+	struct softnic_mtr_meter_policy *policy;
 	int n_jump_queue_rss_drop = 0;
 	int n_count = 0;
 	int n_mark = 0;
@@ -1621,15 +1622,25 @@ flow_rule_action_get(struct pmd_internals *softnic,
 					return -1;
 				}
 			}
-
+			/* Meter policy must exist */
+			policy = softnic_mtr_meter_policy_find(softnic,
+					m->params.meter_policy_id);
+			if (policy == NULL) {
+				rte_flow_error_set(error,
+						EINVAL,
+						RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+						NULL,
+						"METER: fail to find meter policy");
+				return -1;
+			}
 			/* RTE_TABLE_ACTION_METER */
 			rule_action->mtr.mtr[0].meter_profile_id = meter_profile_id;
 			rule_action->mtr.mtr[0].policer[RTE_COLOR_GREEN] =
-				softnic_table_action_policer(m->params.action[RTE_COLOR_GREEN]);
+				policy->policer[RTE_COLOR_GREEN];
 			rule_action->mtr.mtr[0].policer[RTE_COLOR_YELLOW] =
-				softnic_table_action_policer(m->params.action[RTE_COLOR_YELLOW]);
+				policy->policer[RTE_COLOR_YELLOW];
 			rule_action->mtr.mtr[0].policer[RTE_COLOR_RED] =
-				softnic_table_action_policer(m->params.action[RTE_COLOR_RED]);
+				policy->policer[RTE_COLOR_RED];
 			rule_action->mtr.tc_mask = 1;
 			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
 			break;
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index faf90a5a8c..1b3186ef0b 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -83,6 +83,16 @@ struct softnic_mtr_meter_profile {
 
 TAILQ_HEAD(softnic_mtr_meter_profile_list, softnic_mtr_meter_profile);
 
+/* MTR meter policy */
+struct softnic_mtr_meter_policy {
+	TAILQ_ENTRY(softnic_mtr_meter_policy) node;
+	uint32_t meter_policy_id;
+	enum rte_table_action_policer policer[RTE_COLORS];
+	uint32_t n_users;
+};
+
+TAILQ_HEAD(softnic_mtr_meter_policy_list, softnic_mtr_meter_policy);
+
 /* MTR meter object */
 struct softnic_mtr {
 	TAILQ_ENTRY(softnic_mtr) node;
@@ -95,6 +105,7 @@ TAILQ_HEAD(softnic_mtr_list, softnic_mtr);
 
 struct mtr_internals {
 	struct softnic_mtr_meter_profile_list meter_profiles;
+	struct softnic_mtr_meter_policy_list meter_policies;
 	struct softnic_mtr_list mtrs;
 };
 
@@ -678,6 +689,10 @@ struct softnic_mtr_meter_profile *
 softnic_mtr_meter_profile_find(struct pmd_internals *p,
 	uint32_t meter_profile_id);
 
+struct softnic_mtr_meter_policy *
+softnic_mtr_meter_policy_find(struct pmd_internals *p,
+	uint32_t meter_policy_id);
+
 extern const struct rte_mtr_ops pmd_mtr_ops;
 
 /**
@@ -841,9 +856,6 @@ softnic_table_action_profile_create(struct pmd_internals *p,
 	const char *name,
 	struct softnic_table_action_profile_params *params);
 
-enum rte_table_action_policer
-softnic_table_action_policer(enum rte_mtr_policer_action action);
-
 /**
  * Pipeline
  */
diff --git a/drivers/net/softnic/rte_eth_softnic_meter.c b/drivers/net/softnic/rte_eth_softnic_meter.c
index 31a2a0e6d9..7acc1de861 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,153 @@ 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 add */
+static int
+pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
+	uint32_t meter_policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error)
+{
+	struct pmd_internals *p = dev->data->dev_private;
+	struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
+	struct softnic_mtr_meter_policy *mp;
+	const struct rte_flow_action *act;
+	const struct rte_flow_action_meter_color *recolor;
+	uint32_t i;
+	bool valid_act_found;
+
+	if (policy == NULL)
+		return -rte_mtr_error_set(error,
+			EINVAL,
+			RTE_MTR_ERROR_TYPE_METER_POLICY,
+			NULL,
+			"Null meter policy invalid");
+
+	/* Meter policy must not 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 already exists");
+
+	for (i = 0; i < RTE_COLORS; i++) {
+		if (policy->actions[i] == NULL)
+			return -rte_mtr_error_set(error,
+				EINVAL,
+				RTE_MTR_ERROR_TYPE_METER_POLICY,
+				NULL,
+				"Null action list");
+		for (act = policy->actions[i], valid_act_found = false;
+			act && act->type != RTE_FLOW_ACTION_TYPE_END;
+			act++) {
+			/*
+			 * Support one (and one only) of
+			 * METER_COLOR or DROP action.
+			 */
+			if ((act->type != RTE_FLOW_ACTION_TYPE_METER_COLOR &&
+				act->type != RTE_FLOW_ACTION_TYPE_DROP) ||
+				valid_act_found)
+				return -rte_mtr_error_set(error,
+					EINVAL,
+					RTE_MTR_ERROR_TYPE_METER_POLICY,
+					NULL,
+					"Action invalid");
+			valid_act_found = true;
+		}
+	}
+
+	/* Memory allocation */
+	mp = calloc(1, sizeof(struct softnic_mtr_meter_policy));
+	if (mp == NULL)
+		return -rte_mtr_error_set(error,
+			ENOMEM,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			"Memory alloc failed");
+
+	/* Fill in */
+	mp->meter_policy_id = meter_policy_id;
+	for (i = 0; i < RTE_COLORS; i++) {
+		mp->policer[i] = RTE_TABLE_ACTION_POLICER_DROP;
+		act = policy->actions[i];
+		if (!act)
+			continue;
+		if (act->type == RTE_FLOW_ACTION_TYPE_METER_COLOR) {
+			recolor = act->conf;
+			switch (recolor->color) {
+			case RTE_COLOR_GREEN:
+				mp->policer[i] =
+				RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
+				break;
+			case RTE_COLOR_YELLOW:
+				mp->policer[i] =
+				RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
+				break;
+			case RTE_COLOR_RED:
+				mp->policer[i] =
+				RTE_TABLE_ACTION_POLICER_COLOR_RED;
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+	/* Add to list */
+	TAILQ_INSERT_TAIL(mpl, mp, node);
+
+	return 0;
+}
+
+/* MTR meter policy delete */
+static int
+pmd_mtr_meter_policy_delete(struct rte_eth_dev *dev,
+	uint32_t meter_policy_id,
+	struct rte_mtr_error *error)
+{
+	struct pmd_internals *p = dev->data->dev_private;
+	struct softnic_mtr_meter_policy *mp;
+
+	/* Meter policy must exist */
+	mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
+	if (mp == NULL)
+		return -rte_mtr_error_set(error,
+			EINVAL,
+			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+			NULL,
+			"Meter policy id invalid");
+
+	/* Check unused */
+	if (mp->n_users)
+		return -rte_mtr_error_set(error,
+			EBUSY,
+			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+			NULL,
+			"Meter policy in use");
+
+	/* Remove from list */
+	TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
+	free(mp);
+
+	return 0;
+}
+
 struct softnic_mtr *
 softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
 {
@@ -267,6 +393,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 +411,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 +439,7 @@ pmd_mtr_create(struct rte_eth_dev *dev,
 
 	/* Update dependencies */
 	mp->n_users++;
+	policy->n_users++;
 
 	return 0;
 }
@@ -316,6 +454,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 +482,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 +655,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);
@@ -528,28 +677,17 @@ pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,
 			NULL,
 			"MTR object id not valid");
 
-	/* Valid policer actions */
-	if (actions == NULL)
+	if (m->params.meter_policy_id == meter_policy_id)
+		return 0;
+
+	/* 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 +699,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 +723,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 +753,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 +797,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 +876,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 +898,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_add = pmd_mtr_meter_policy_add,
+	.meter_policy_delete = pmd_mtr_meter_policy_delete,
+
 	.create = pmd_mtr_create,
 	.destroy = pmd_mtr_destroy,
 	.meter_enable = NULL,
@@ -742,7 +908,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 c476a0f59d..0eedcb09be 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -32,6 +32,7 @@
 #include <rte_ecpri.h>
 #include <rte_mbuf.h>
 #include <rte_mbuf_dyn.h>
+#include <rte_meter.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -2267,6 +2268,14 @@ enum rte_flow_action_type {
 	 * See struct rte_flow_action_modify_field.
 	 */
 	RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
+
+	/**
+	 * Color the packet to reflect the meter color result.
+	 * Set the meter color in the mbuf to the selected color.
+	 *
+	 * See struct rte_flow_action_meter_color.
+	 */
+	RTE_FLOW_ACTION_TYPE_METER_COLOR,
 };
 
 /**
@@ -2859,6 +2868,19 @@ struct rte_flow_action_set_dscp {
  */
 struct rte_flow_shared_action;
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
+ * RTE_FLOW_ACTION_TYPE_METER_COLOR
+ *
+ * The meter color should be set in the packet meta-data
+ * (i.e. struct rte_mbuf::sched::color).
+ */
+struct rte_flow_action_meter_color {
+	enum rte_color color; /**< Packet color. */
+};
+
 /**
  * Field IDs for MODIFY_FIELD action.
  */
diff --git a/lib/librte_ethdev/rte_mtr.c b/lib/librte_ethdev/rte_mtr.c
index 3073ac03f2..e49fcf271c 100644
--- a/lib/librte_ethdev/rte_mtr.c
+++ b/lib/librte_ethdev/rte_mtr.c
@@ -91,6 +91,40 @@ rte_mtr_meter_profile_delete(uint16_t port_id,
 		meter_profile_id, error);
 }
 
+/* MTR meter policy validate */
+int
+rte_mtr_meter_policy_validate(uint16_t port_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_policy_validate)(dev,
+		policy, error);
+}
+
+/* MTR meter policy add */
+int
+rte_mtr_meter_policy_add(uint16_t port_id,
+	uint32_t policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_policy_add)(dev,
+		policy_id, policy, error);
+}
+
+/** MTR meter policy delete */
+int
+rte_mtr_meter_policy_delete(uint16_t port_id,
+	uint32_t policy_id,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_policy_delete)(dev,
+		policy_id, error);
+}
+
 /** MTR object create */
 int
 rte_mtr_create(uint16_t port_id,
@@ -149,29 +183,28 @@ rte_mtr_meter_profile_update(uint16_t port_id,
 		mtr_id, meter_profile_id, error);
 }
 
-/** MTR object meter DSCP table update */
+/** MTR object meter policy update */
 int
-rte_mtr_meter_dscp_table_update(uint16_t port_id,
+rte_mtr_meter_policy_update(uint16_t port_id,
 	uint32_t mtr_id,
-	enum rte_color *dscp_table,
+	uint32_t meter_policy_id,
 	struct rte_mtr_error *error)
 {
 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
-	return RTE_MTR_FUNC(port_id, meter_dscp_table_update)(dev,
-		mtr_id, dscp_table, error);
+	return RTE_MTR_FUNC(port_id, meter_policy_update)(dev,
+		mtr_id, meter_policy_id, error);
 }
 
-/** MTR object policer action update */
+/** MTR object meter DSCP table update */
 int
-rte_mtr_policer_actions_update(uint16_t port_id,
+rte_mtr_meter_dscp_table_update(uint16_t port_id,
 	uint32_t mtr_id,
-	uint32_t action_mask,
-	enum rte_mtr_policer_action *actions,
+	enum rte_color *dscp_table,
 	struct rte_mtr_error *error)
 {
 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
-	return RTE_MTR_FUNC(port_id, policer_actions_update)(dev,
-		mtr_id, action_mask, actions, error);
+	return RTE_MTR_FUNC(port_id, meter_dscp_table_update)(dev,
+		mtr_id, dscp_table, error);
 }
 
 /** MTR object enabled stats update */
diff --git a/lib/librte_ethdev/rte_mtr.h b/lib/librte_ethdev/rte_mtr.h
index 916a09c5c3..2946e483d3 100644
--- a/lib/librte_ethdev/rte_mtr.h
+++ b/lib/librte_ethdev/rte_mtr.h
@@ -49,6 +49,7 @@
 #include <rte_compat.h>
 #include <rte_common.h>
 #include <rte_meter.h>
+#include <rte_flow.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -175,20 +176,16 @@ struct rte_mtr_meter_profile {
 };
 
 /**
- * Policer actions
+ * Meter policy
  */
-enum rte_mtr_policer_action {
-	/** Recolor the packet as green. */
-	MTR_POLICER_ACTION_COLOR_GREEN = 0,
-
-	/** Recolor the packet as yellow. */
-	MTR_POLICER_ACTION_COLOR_YELLOW,
-
-	/** Recolor the packet as red. */
-	MTR_POLICER_ACTION_COLOR_RED,
-
-	/** Drop the packet. */
-	MTR_POLICER_ACTION_DROP,
+struct rte_mtr_meter_policy_params {
+	/**
+	 * Policy action list per color.
+	 * actions[i] potentially represents a chain of rte_flow actions
+	 * terminated by the END action, exactly as specified by the rte_flow
+	 * API for the flow definition, and not just a single action.
+	 */
+	const struct rte_flow_action *actions[RTE_COLORS];
 };
 
 /**
@@ -232,13 +229,13 @@ struct rte_mtr_params {
 	 */
 	int meter_enable;
 
-	/** Policer actions (per meter output color). */
-	enum rte_mtr_policer_action action[RTE_COLORS];
-
 	/** Set of stats counters to be enabled.
 	 * @see enum rte_mtr_stats_type
 	 */
 	uint64_t stats_mask;
+
+	/** Meter policy ID. */
+	uint32_t meter_policy_id;
 };
 
 /**
@@ -324,6 +321,13 @@ struct rte_mtr_capabilities {
 	 */
 	uint64_t meter_rate_max;
 
+	/**
+	 * Maximum number of policy objects that can have.
+	 * The value of 0 is invalid. Policy must be supported for meter.
+	 * The maximum value is *n_max*.
+	 */
+	uint64_t meter_policy_n_max;
+
 	/**
 	 * When non-zero, it indicates that color aware mode is supported for
 	 * the srTCM RFC 2697 metering algorithm.
@@ -342,18 +346,6 @@ struct rte_mtr_capabilities {
 	 */
 	int color_aware_trtcm_rfc4115_supported;
 
-	/** When non-zero, it indicates that the policer packet recolor actions
-	 * are supported.
-	 * @see enum rte_mtr_policer_action
-	 */
-	int policer_action_recolor_supported;
-
-	/** When non-zero, it indicates that the policer packet drop action is
-	 * supported.
-	 * @see enum rte_mtr_policer_action
-	 */
-	int policer_action_drop_supported;
-
 	/** Set of supported statistics counter types.
 	 * @see enum rte_mtr_stats_type
 	 */
@@ -379,6 +371,8 @@ enum rte_mtr_error_type {
 	RTE_MTR_ERROR_TYPE_STATS_MASK,
 	RTE_MTR_ERROR_TYPE_STATS,
 	RTE_MTR_ERROR_TYPE_SHARED,
+	RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+	RTE_MTR_ERROR_TYPE_METER_POLICY,
 };
 
 /**
@@ -462,6 +456,145 @@ rte_mtr_meter_profile_delete(uint16_t port_id,
 	uint32_t meter_profile_id,
 	struct rte_mtr_error *error);
 
+/**
+ * Check whether a meter policy can be created on a given port.
+ *
+ * The meter policy is validated for correctness and
+ * whether it could be accepted by the device given sufficient resources.
+ * The policy is checked against the current capability information
+ * meter_policy_n_max configuration.
+ * The policy may also optionally be validated against existing
+ * device policy resources.
+ * This function has no effect on the target device.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] policy
+ *   Associated action list per color.
+ *   list NULL is legal and means no special action.
+ *   (list terminated by the END action).
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+__rte_experimental
+int
+rte_mtr_meter_policy_validate(uint16_t port_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+
+/**
+ * Meter policy add
+ *
+ * Create a new meter policy. The new policy
+ * is used to create single or multiple MTR objects.
+ * The same policy can be used to create 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] policy
+ *   Associated actions per color.
+ *   list NULL is legal and means no special action.
+ *   Non-NULL list must be terminated.
+ *   (list terminated by the END action).
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+__rte_experimental
+int
+rte_mtr_meter_policy_add(uint16_t port_id,
+	uint32_t policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+
+/**
+ * Two common examples to define meter policy action list:
+ * Example #1: pass_color_policy_params
+ * GREEN - GREEN, YELLOW - YELLOW, RED - RED
+ */
+#define rte_mtr_policy_pass_color(policy) \
+struct rte_mtr_meter_policy_params policy = \
+{ \
+	.actions[RTE_COLOR_GREEN] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
+			.conf = &(struct rte_flow_action_meter_color) { \
+				.color = RTE_COLOR_GREEN, \
+			}, \
+		}, \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+	.actions[RTE_COLOR_YELLOW] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
+			.conf = &(struct rte_flow_action_meter_color) { \
+				.color = RTE_COLOR_YELLOW, \
+			}, \
+		}, \
+		{ \
+		.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+	.actions[RTE_COLOR_RED] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
+			.conf = &(struct rte_flow_action_meter_color) { \
+				.color = RTE_COLOR_RED, \
+			}, \
+		}, \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+};
+
+/**
+ *Example #2: drop_red_policy_params
+ * GREEN - Do nothing, YELLOW - Do nothing, RED - DROP
+ */
+#define rte_mtr_policy_drop_red(policy) \
+struct rte_mtr_meter_policy_params policy = \
+{ \
+	.actions[RTE_COLOR_GREEN] = NULL, \
+	.actions[RTE_COLOR_YELLOW] = NULL, \
+	.actions[RTE_COLOR_RED] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_DROP, \
+		}, \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+};
+
+/**
+ * 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 +720,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 +735,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 +760,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..62273ed3a9 100644
--- a/lib/librte_ethdev/rte_mtr_driver.h
+++ b/lib/librte_ethdev/rte_mtr_driver.h
@@ -41,6 +41,22 @@ typedef int (*rte_mtr_meter_profile_delete_t)(struct rte_eth_dev *dev,
 	struct rte_mtr_error *error);
 /**< @internal MTR meter profile delete */
 
+typedef int (*rte_mtr_meter_policy_validate_t)(struct rte_eth_dev *dev,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+/**< @internal MTR meter policy validate */
+
+typedef int (*rte_mtr_meter_policy_add_t)(struct rte_eth_dev *dev,
+	uint32_t policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+/**< @internal MTR meter policy add */
+
+typedef int (*rte_mtr_meter_policy_delete_t)(struct rte_eth_dev *dev,
+	uint32_t policy_id,
+	struct rte_mtr_error *error);
+/**< @internal MTR meter policy delete */
+
 typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
 	struct rte_mtr_params *params,
@@ -69,18 +85,17 @@ typedef int (*rte_mtr_meter_profile_update_t)(struct rte_eth_dev *dev,
 	struct rte_mtr_error *error);
 /**< @internal MTR object meter profile update */
 
-typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
+typedef int (*rte_mtr_meter_policy_update_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
-	enum rte_color *dscp_table,
+	uint32_t meter_policy_id,
 	struct rte_mtr_error *error);
-/**< @internal MTR object meter DSCP table update */
+/**< @internal MTR object meter policy update */
 
-typedef int (*rte_mtr_policer_actions_update_t)(struct rte_eth_dev *dev,
+typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
-	uint32_t action_mask,
-	enum rte_mtr_policer_action *actions,
+	enum rte_color *dscp_table,
 	struct rte_mtr_error *error);
-/**< @internal MTR object policer action update*/
+/**< @internal MTR object meter DSCP table update */
 
 typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
@@ -124,14 +139,23 @@ struct rte_mtr_ops {
 	/** MTR object meter DSCP table update */
 	rte_mtr_meter_dscp_table_update_t meter_dscp_table_update;
 
-	/** MTR object policer action update */
-	rte_mtr_policer_actions_update_t policer_actions_update;
-
 	/** MTR object enabled stats update */
 	rte_mtr_stats_update_t stats_update;
 
 	/** MTR object stats read */
 	rte_mtr_stats_read_t stats_read;
+
+	/** MTR meter policy validate */
+	rte_mtr_meter_policy_validate_t meter_policy_validate;
+
+	/** MTR meter policy add */
+	rte_mtr_meter_policy_add_t meter_policy_add;
+
+	/** 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..b3e9b83d95 100644
--- a/lib/librte_ethdev/version.map
+++ b/lib/librte_ethdev/version.map
@@ -138,7 +138,6 @@ EXPERIMENTAL {
 	rte_mtr_meter_profile_add;
 	rte_mtr_meter_profile_delete;
 	rte_mtr_meter_profile_update;
-	rte_mtr_policer_actions_update;
 	rte_mtr_stats_read;
 	rte_mtr_stats_update;
 
@@ -246,6 +245,10 @@ EXPERIMENTAL {
 
 	# added in 21.05
 	rte_eth_representor_info_get;
+	rte_mtr_meter_policy_add;
+	rte_mtr_meter_policy_delete;
+	rte_mtr_meter_policy_update;
+	rte_mtr_meter_policy_validate;
 };
 
 INTERNAL {
-- 
2.27.0


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

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

From: Haifei Luo <haifeil@nvidia.com>

Add the create/del policy CLIs to support actions per color.
The CLIs are:
Create:  add port meter policy (port_id) (policy_id) g_actions (actions)
y_actions (actions) r_actions (actions)
Delete:  del port meter policy (port_id) (policy_id)

Examples:
testpmd> add port meter policy 0 1 g_actions rss / end y_actions end
r_actions drop / end
testpmd> del port meter policy 0 1

Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
---
 app/test-pmd/cmdline.c                      |  13 ++-
 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                       |  32 ++++++
 app/test-pmd/testpmd.h                      |   2 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  30 ++++-
 7 files changed, 269 insertions(+), 14 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0bb6394314..6c6184a170 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -705,9 +705,8 @@ 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"
-			"(g_action) (y_action) (r_action) (stats_mask) (shared)\n"
-			"(use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
+			"create port meter (port_id) (mtr_id) (profile_id) (policy_id) (meter_enable)\n"
+			"(stats_mask) (shared) (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
 			"(dscp_tbl_entry63)]\n"
 			"    meter create\n\n"
 
@@ -720,6 +719,13 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"del port meter (port_id) (mtr_id)\n"
 			"    meter delete\n\n"
 
+			"add port meter policy (port_id) (policy_id) g_actions (actions)\n"
+			"y_actions (actions) r_actions (actions)\n"
+			"    meter policy add\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"
 
@@ -17069,6 +17075,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 fb7a3a8bd3..f50e7312ee 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. */
@@ -808,6 +818,9 @@ struct buffer {
 		struct {
 			int destroy;
 		} aged; /**< Aged arguments. */
+		struct {
+			uint32_t policy_id;
+		} policy;/**< Policy arguments. */
 	} args; /**< Command arguments. */
 };
 
@@ -1785,6 +1798,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);
@@ -1823,7 +1839,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 = "",
@@ -1945,6 +1961,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",
@@ -4528,6 +4551,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. */
@@ -4712,6 +4783,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,
@@ -7685,6 +7797,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 a5e82b7a97..f8b3f671cd 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
 
@@ -1465,6 +1467,36 @@ 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 *act = actions;
+	const struct rte_flow_action *start;
+	struct rte_mtr_meter_policy_params policy;
+	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)
+			policy.actions[i] = start;
+		else
+			policy.actions[i] = NULL;
+		act++;
+	}
+	ret = rte_mtr_meter_policy_add(port_id,
+			policy_id,
+			&policy, &error);
+	if (ret)
+		print_mtr_err_msg(&error);
+	return ret;
+}
+
 /** 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);
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 3f7a1c0e33..b596ee9a14 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2764,13 +2764,37 @@ Delete meter profile from the ethernet device::
 
    testpmd> del port meter profile (port_id) (profile_id)
 
+create port policy
+~~~~~~~~~~~~~~~~~~
+
+Create new policy object for the ethernet device::
+
+   testpmd> add port meter policy (port_id) (policy_id) g_actions \
+   {action} y_actions {action} r_actions {action}
+
+where:
+
+* ``policy_id``: policy ID.
+* ``action``: action lists for green/yellow/red colors.
+
+delete port policy
+~~~~~~~~~~~~~~~~~~
+
+Delete policy object for the ethernet device::
+
+   testpmd> del port meter policy (port_id) (policy_id)
+
+where:
+
+* ``policy_id``: policy ID.
+
 create port meter
 ~~~~~~~~~~~~~~~~~
 
 Create new meter object for the ethernet device::
 
    testpmd> create port meter (port_id) (mtr_id) (profile_id) \
-   (meter_enable) (g_action) (y_action) (r_action) (stats_mask) (shared) \
+   (policy_id) (meter_enable) (stats_mask) (shared) \
    (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\
    (dscp_tbl_entry63)]
 
@@ -2778,11 +2802,9 @@ where:
 
 * ``mtr_id``: meter object ID.
 * ``profile_id``: ID for the meter profile.
+* ``policy_id``: ID for the policy.
 * ``meter_enable``: When this parameter has a non-zero value, the meter object
   gets enabled at the time of creation, otherwise remains disabled.
-* ``g_action``: Policer action for the packet with green color.
-* ``y_action``: Policer action for the packet with yellow color.
-* ``r_action``: Policer action for the packet with red color.
 * ``stats_mask``: Mask of statistics counter types to be enabled for the
   meter object.
 * ``shared``:  When this parameter has a non-zero value, the meter object is
-- 
2.27.0


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

* [dpdk-dev] [PATCH v8 0/2] Support meter policy API
  2021-03-18  8:58 [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API Li Zhang
                   ` (7 preceding siblings ...)
  2021-04-15  4:54 ` [dpdk-dev] [PATCH v7 0/2] Support meter policy API Li Zhang
@ 2021-04-15  9:20 ` Li Zhang
  2021-04-15  9:20   ` [dpdk-dev] [PATCH v8 1/2] ethdev: add pre-defined " Li Zhang
                     ` (2 more replies)
  2021-04-20 17:56 ` [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined " Stephen Hemminger
  9 siblings, 3 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-15  9:20 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, cristian.dumitrescu,
	lironh, jerinj, ferruh.yigit, ajit.khaparde
  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.

Add two common policy template as macros in the header file,

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

Depends-on: series=16351  ("Add ASO meter support in MLX5 PMD ")
https://patchwork.dpdk.org/project/dpdk/list/?series=16351

V2: Delete default policy and change relation doc files.
V3: Fix coding style issues.
V4: Fix comments about Depends-on
V5: Fix comments about rte_mtr_meter_policy_add.
V6: Delete policy example.
V7: Fix comments and place two common policy template as macros.
V8: Fix rebase conflict issues and CI warning

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                        |  14 +-
 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                         |  32 ++
 app/test-pmd/testpmd.h                        |   2 +
 doc/guides/prog_guide/rte_flow.rst            |  21 +
 .../traffic_metering_and_policing.rst         |  16 +-
 doc/guides/rel_notes/release_21_05.rst        |  21 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  48 +-
 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   | 290 ++++++++---
 lib/librte_ethdev/rte_flow.h                  |  22 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 223 +++++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   5 +-
 25 files changed, 872 insertions(+), 1270 deletions(-)

-- 
2.27.0


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

* [dpdk-dev] [PATCH v8 1/2] ethdev: add pre-defined meter policy API
  2021-04-15  9:20 ` [dpdk-dev] [PATCH v8 0/2] Support meter policy API Li Zhang
@ 2021-04-15  9:20   ` Li Zhang
  2021-04-15 15:13     ` Ori Kam
  2021-04-19 12:34     ` Singh, Jasvinder
  2021-04-15  9:20   ` [dpdk-dev] [PATCH v8 2/2] app/testpmd: support policy actions per color Li Zhang
  2021-04-19 16:08   ` [dpdk-dev] [PATCH v9 0/2] Support meter policy API Jiawei Wang
  2 siblings, 2 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-15  9:20 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, cristian.dumitrescu,
	lironh, jerinj, ferruh.yigit, ajit.khaparde, Wisam Jaddo,
	Xiaoyun Li, Jasvinder Singh, Thomas Monjalon, Andrew Rybchenko,
	Ray Kinsella, Neil Horman
  Cc: dev, rasland, roniba, Haifei Luo, Jiawei Wang

Currently, the flow meter policy does not support multiple actions
per color; also the allowed action types per color are very limited.
In addition, the policy cannot be pre-defined.

Due to the growing in flow actions offload abilities there is a potential
for the user to use variety of actions per color differently.
This new meter policy API comes to allow this potential in the most ethdev
common way using rte_flow action definition.
A list of rte_flow actions will be provided by the user per color
in order to create a meter policy.
In addition, the API forces to pre-define the policy before
the meters creation in order to allow sharing of single policy
with multiple meters efficiently.

meter_policy_id is added into struct rte_mtr_params.
So that it can get the policy during the meters creation.

Allow coloring the packet using a new rte_flow_action_color
as could be done by the old policy API.

Add two common policy template as macros in the head file.

The next API function were added:
- rte_mtr_meter_policy_add
- rte_mtr_meter_policy_delete
- rte_mtr_meter_policy_update
- rte_mtr_meter_policy_validate
The next struct was changed:
- rte_mtr_params
- rte_mtr_capabilities
The next API was deleted:
- rte_mtr_policer_actions_update

To support this API the following app were changed:
app/test-flow-perf: clean meter policer
app/testpmd: clean meter policer

To support this API the following drivers were changed:
net/softnic: support meter policy API
1. cleans meter rte_mtr_policer_action.
2. Support policy API to get color action as policer action did.
   The color action will be mapped into rte_table_action_policer.

net/mlx5: clean meter creation management
Cleans and breaks part of the current meter management
in order to allow better design with policy API.

Signed-off-by: Li Zhang <lizh@nvidia.com>
Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
Acked-by: Ray Kinsella <mdr@ashroe.eu>
---
 app/test-flow-perf/main.c                     |   7 -
 app/test-pmd/cmdline.c                        |   1 -
 app/test-pmd/cmdline_mtr.c                    | 172 -------
 app/test-pmd/cmdline_mtr.h                    |   1 -
 doc/guides/prog_guide/rte_flow.rst            |  21 +
 .../traffic_metering_and_policing.rst         |  16 +-
 doc/guides/rel_notes/release_21_05.rst        |  21 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst   |  18 -
 drivers/net/mlx5/mlx5.h                       |  24 +-
 drivers/net/mlx5/mlx5_flow.c                  |  46 --
 drivers/net/mlx5/mlx5_flow.h                  |  18 +-
 drivers/net/mlx5/mlx5_flow_aso.c              |   8 +-
 drivers/net/mlx5/mlx5_flow_dv.c               | 461 +-----------------
 drivers/net/mlx5/mlx5_flow_meter.c            | 369 +-------------
 drivers/net/softnic/rte_eth_softnic_flow.c    |  19 +-
 .../net/softnic/rte_eth_softnic_internals.h   |  18 +-
 drivers/net/softnic/rte_eth_softnic_meter.c   | 290 ++++++++---
 lib/librte_ethdev/rte_flow.h                  |  22 +
 lib/librte_ethdev/rte_mtr.c                   |  55 ++-
 lib/librte_ethdev/rte_mtr.h                   | 223 +++++++--
 lib/librte_ethdev/rte_mtr_driver.h            |  44 +-
 lib/librte_ethdev/version.map                 |   5 +-
 22 files changed, 603 insertions(+), 1256 deletions(-)

diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c
index 8e229679df..9be8edc31d 100644
--- a/app/test-flow-perf/main.c
+++ b/app/test-flow-perf/main.c
@@ -928,13 +928,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 5bf1497f2b..e244df27dc 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -17074,7 +17074,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 4d9bfde78d..aa454af536 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.srtcm_rfc2697_byte_mode_supported %" PRId32 "\n",
 		cap.srtcm_rfc2697_byte_mode_supported);
 	printf("cap.srtcm_rfc2697_packet_mode_supported %" PRId32 "\n",
@@ -842,12 +791,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);
@@ -1215,121 +1158,6 @@ cmdline_parse_inst_t cmd_set_port_meter_dscp_table = {
 	},
 };
 
-/* *** Set Port Meter Policer Action *** */
-struct cmd_set_port_meter_policer_action_result {
-	cmdline_fixed_string_t set;
-	cmdline_fixed_string_t port;
-	cmdline_fixed_string_t meter;
-	cmdline_fixed_string_t policer;
-	cmdline_fixed_string_t action;
-	uint16_t port_id;
-	uint32_t mtr_id;
-	uint32_t action_mask;
-	cmdline_multi_string_t policer_action;
-};
-
-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_set =
-	TOKEN_STRING_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, set, "set");
-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_port =
-	TOKEN_STRING_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, port, "port");
-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_meter =
-	TOKEN_STRING_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, meter,
-		"meter");
-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_policer =
-	TOKEN_STRING_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, policer,
-		"policer");
-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_action =
-	TOKEN_STRING_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, action,
-		"action");
-cmdline_parse_token_num_t cmd_set_port_meter_policer_action_port_id =
-	TOKEN_NUM_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, port_id,
-		RTE_UINT16);
-cmdline_parse_token_num_t cmd_set_port_meter_policer_action_mtr_id =
-	TOKEN_NUM_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, mtr_id,
-		RTE_UINT32);
-cmdline_parse_token_num_t cmd_set_port_meter_policer_action_action_mask =
-	TOKEN_NUM_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result, action_mask,
-		RTE_UINT32);
-cmdline_parse_token_string_t cmd_set_port_meter_policer_action_policer_action =
-	TOKEN_STRING_INITIALIZER(
-		struct cmd_set_port_meter_policer_action_result,
-		policer_action, TOKEN_STRING_MULTI);
-
-static void cmd_set_port_meter_policer_action_parsed(void *parsed_result,
-	__rte_unused struct cmdline *cl,
-	__rte_unused void *data)
-{
-	struct cmd_set_port_meter_policer_action_result *res = parsed_result;
-	enum rte_mtr_policer_action *actions;
-	struct rte_mtr_error error;
-	uint32_t mtr_id = res->mtr_id;
-	uint32_t action_mask = res->action_mask;
-	uint16_t port_id = res->port_id;
-	char *p_str = res->policer_action;
-	int ret;
-
-	if (port_id_is_invalid(port_id, ENABLED_WARN))
-		return;
-
-	/* Check: action mask */
-	if (action_mask == 0 || (action_mask & (~0x7UL))) {
-		printf(" Policer action mask not correct (error)\n");
-		return;
-	}
-
-	/* Allocate memory for policer actions */
-	actions = (enum rte_mtr_policer_action *)malloc(RTE_COLORS *
-		sizeof(enum rte_mtr_policer_action));
-	if (actions == NULL) {
-		printf("Memory for policer actions not allocated (error)\n");
-		return;
-	}
-	/* Parse policer action string */
-	ret = parse_policer_action_string(p_str, action_mask, actions);
-	if (ret) {
-		printf(" Policer action string parse error\n");
-		free(actions);
-		return;
-	}
-
-	ret = rte_mtr_policer_actions_update(port_id, mtr_id,
-		action_mask, actions, &error);
-	if (ret != 0) {
-		free(actions);
-		print_err_msg(&error);
-		return;
-	}
-
-	free(actions);
-}
-
-cmdline_parse_inst_t cmd_set_port_meter_policer_action = {
-	.f = cmd_set_port_meter_policer_action_parsed,
-	.data = NULL,
-	.help_str = "set port meter policer action <port_id> <mtr_id> "
-		"<action_mask> <action0> [<action1> <action2>]",
-	.tokens = {
-		(void *)&cmd_set_port_meter_policer_action_set,
-		(void *)&cmd_set_port_meter_policer_action_port,
-		(void *)&cmd_set_port_meter_policer_action_meter,
-		(void *)&cmd_set_port_meter_policer_action_policer,
-		(void *)&cmd_set_port_meter_policer_action_action,
-		(void *)&cmd_set_port_meter_policer_action_port_id,
-		(void *)&cmd_set_port_meter_policer_action_mtr_id,
-		(void *)&cmd_set_port_meter_policer_action_action_mask,
-		(void *)&cmd_set_port_meter_policer_action_policer_action,
-		NULL,
-	},
-};
-
 /* *** Set Port Meter Stats Mask *** */
 struct cmd_set_port_meter_stats_mask_result {
 	cmdline_fixed_string_t set;
diff --git a/app/test-pmd/cmdline_mtr.h b/app/test-pmd/cmdline_mtr.h
index e69d6da023..7e2713cea3 100644
--- a/app/test-pmd/cmdline_mtr.h
+++ b/app/test-pmd/cmdline_mtr.h
@@ -17,7 +17,6 @@ extern cmdline_parse_inst_t cmd_disable_port_meter;
 extern cmdline_parse_inst_t cmd_del_port_meter;
 extern cmdline_parse_inst_t cmd_set_port_meter_profile;
 extern cmdline_parse_inst_t cmd_set_port_meter_dscp_table;
-extern cmdline_parse_inst_t cmd_set_port_meter_policer_action;
 extern cmdline_parse_inst_t cmd_set_port_meter_stats_mask;
 extern cmdline_parse_inst_t cmd_show_port_meter_stats;
 
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index e1b93ecedf..2f5a6e0c31 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -2841,6 +2841,27 @@ for ``RTE_FLOW_FIELD_VALUE`` and ``RTE_FLOW_FIELD_POINTER`` respectively.
    | ``value``     | immediate value or a pointer to this value               |
    +---------------+----------------------------------------------------------+
 
+Action: ``METER_COLOR``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Color the packet to reflect the meter color result.
+
+The meter action must be configured before meter color action.
+Meter color action is set to a color to reflect the meter color result.
+Set the meter color in the mbuf to the selected color.
+The meter color action output color is the output color of the packet,
+which is set in the packet meta-data (i.e. struct ``rte_mbuf::sched::color``)
+
+.. _table_rte_flow_action_meter_color:
+
+.. table:: METER_COLOR
+
+   +-----------------+--------------+
+   | Field           | Value        |
+   +=================+==============+
+   | ``meter_color`` | Packet color |
+   +-----------------+--------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/doc/guides/prog_guide/traffic_metering_and_policing.rst b/doc/guides/prog_guide/traffic_metering_and_policing.rst
index 90c781eb1d..c0537e653c 100644
--- a/doc/guides/prog_guide/traffic_metering_and_policing.rst
+++ b/doc/guides/prog_guide/traffic_metering_and_policing.rst
@@ -56,18 +56,10 @@ The processing done for each input packet hitting an MTR object is:
   color blind mode, which is equivalent to considering all input packets
   initially colored as green.
 
-* Policing: There is a separate policer action configured for each meter
-  output color, which can:
-
-  * Drop the packet.
-
-  * Keep the same packet color: the policer output color matches the meter
-    output color (essentially a no-op action).
-
-  * Recolor the packet: the policer output color is set to a different color
-    than the meter output color. The policer output color is the output color
-    of the packet, which is set in the packet meta-data (i.e. struct
-    ``rte_mbuf::sched::color``).
+* There is a meter policy API to manage pre-defined policies for meter.
+  Any rte_flow action list can be configured per color for each policy.
+  A meter object configured with a policy executes the actions per packet
+  according to the packet color.
 
 * Statistics: The set of counters maintained for each MTR object is
   configurable and subject to the implementation support. This set includes
diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst
index 82ee71152f..5a8eeb6446 100644
--- a/doc/guides/rel_notes/release_21_05.rst
+++ b/doc/guides/rel_notes/release_21_05.rst
@@ -192,6 +192,27 @@ New Features
   * Added command to dump internal representation information of single flow.
     ``flow dump (port_id) rule (rule_id)``
 
+  * 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_add()``, ``rte_mtr_meter_policy_delete()`` and
+    ``rte_mtr_create_with_policy()``
+  * ethdev: Removed rte_mtr_policer_action from rte_mtr_params structures.
+  * ethdev: Added rte_mtr_meter_policy_params structures to support policy API.
+  * ethdev: Added meter_policy_id into rte_mtr_params structures.
+  * ethdev: Removed policer_action_recolor_supported and policer_action_drop_supported from rte_mtr_capabilities structures.
+  * ethdev: Added meter_policy_n_max into rte_mtr_capabilities structures.
+  * ethdev: Added RTE_FLOW_ACTION_TYPE_METER_COLOR in enum rte_flow_action_type.
+  * ethdev: Added RTE_MTR_ERROR_TYPE_METER_POLICY_ID and RTE_MTR_ERROR_TYPE_METER_POLICY_ID into rte_mtr_error_type.
 
 Removed Items
 -------------
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index e3bfed566d..824d8bdf27 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2833,24 +2833,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 50e3b6de33..221e601fa9 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -584,14 +584,6 @@ struct mlx5_dev_shared_port {
 /* Modify this value if enum rte_mtr_color changes. */
 #define RTE_MTR_DROPPED RTE_COLORS
 
-/* Meter policer statistics */
-struct mlx5_flow_policer_stats {
-	uint32_t pass_cnt;
-	/**< Color counter for pass. */
-	uint32_t drop_cnt;
-	/**< Color counter for drop. */
-};
-
 /* Meter table structure. */
 struct mlx5_meter_domain_info {
 	struct mlx5_flow_tbl_resource *tbl;
@@ -630,24 +622,12 @@ struct mlx5_meter_domains_infos {
 
 /* Meter parameter structure. */
 struct mlx5_flow_meter_info {
-	uint32_t meter_id;
-	/**< Meter id. */
 	struct mlx5_flow_meter_profile *profile;
 	/**< Meter profile parameters. */
 	rte_spinlock_t sl; /**< Meter action spinlock. */
-	/** Policer actions (per meter output color). */
-	enum rte_mtr_policer_action action[RTE_COLORS];
 	/** Set of stats counters to be enabled.
 	 * @see enum rte_mtr_stats_type
 	 */
-	uint32_t green_bytes:1;
-	/** Set green bytes stats to be enabled. */
-	uint32_t green_pkts:1;
-	/** Set green packets stats to be enabled. */
-	uint32_t red_bytes:1;
-	/** Set red bytes stats to be enabled. */
-	uint32_t red_pkts:1;
-	/** Set red packets stats to be enabled. */
 	uint32_t bytes_dropped:1;
 	/** Set bytes dropped stats to be enabled. */
 	uint32_t pkts_dropped:1;
@@ -682,8 +662,8 @@ struct mlx5_flow_meter_info {
 	uint32_t transfer:1;
 	struct mlx5_meter_domains_infos *mfts;
 	/**< Flow table created for this meter. */
-	struct mlx5_flow_policer_stats policer_stats;
-	/**< Meter policer statistics. */
+	uint32_t drop_cnt;
+	/**< Color counter for drop. */
 	uint32_t ref_cnt;
 	/**< Use count. */
 	struct mlx5_indexed_pool *flow_ipool;
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index bd957e7b29..eed43a208b 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -6648,52 +6648,6 @@ mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,
 	return fops->destroy_mtr_tbls(dev, tbls);
 }
 
-/**
- * Prepare policer rules.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] attr
- *   Pointer to flow attributes.
- *
- * @return
- *   0 on success, -1 otherwise.
- */
-int
-mlx5_flow_prepare_policer_rules(struct rte_eth_dev *dev,
-			       struct mlx5_flow_meter_info *fm,
-			       const struct rte_flow_attr *attr)
-{
-	const struct mlx5_flow_driver_ops *fops;
-
-	fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
-	return fops->prepare_policer_rules(dev, fm, attr);
-}
-
-/**
- * Destroy policer rules.
- *
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] attr
- *   Pointer to flow attributes.
- *
- * @return
- *   0 on success, -1 otherwise.
- */
-int
-mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,
-				struct mlx5_flow_meter_info *fm,
-				const struct rte_flow_attr *attr)
-{
-	const struct mlx5_flow_driver_ops *fops;
-
-	fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV);
-	return fops->destroy_policer_rules(dev, fm, attr);
-}
-
 /**
  * Allocate the needed aso flow meter id.
  *
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index cb2803d080..7fa15eef7b 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -839,6 +839,8 @@ struct mlx5_legacy_flow_meter {
 	/* Must be the first in struct. */
 	TAILQ_ENTRY(mlx5_legacy_flow_meter) next;
 	/**< Pointer to the next flow meter structure. */
+	uint32_t meter_id;
+	/**< Meter id. */
 	uint32_t idx; /* Index to meter object. */
 };
 
@@ -1097,14 +1099,6 @@ typedef struct mlx5_meter_domains_infos *(*mlx5_flow_create_mtr_tbls_t)
 					    (struct rte_eth_dev *dev);
 typedef int (*mlx5_flow_destroy_mtr_tbls_t)(struct rte_eth_dev *dev,
 					struct mlx5_meter_domains_infos *tbls);
-typedef int (*mlx5_flow_create_policer_rules_t)
-					(struct rte_eth_dev *dev,
-					 struct mlx5_flow_meter_info *fm,
-					 const struct rte_flow_attr *attr);
-typedef int (*mlx5_flow_destroy_policer_rules_t)
-					(struct rte_eth_dev *dev,
-					 const struct mlx5_flow_meter_info *fm,
-					 const struct rte_flow_attr *attr);
 typedef uint32_t (*mlx5_flow_mtr_alloc_t)
 					    (struct rte_eth_dev *dev);
 typedef void (*mlx5_flow_mtr_free_t)(struct rte_eth_dev *dev,
@@ -1161,8 +1155,6 @@ struct mlx5_flow_driver_ops {
 	mlx5_flow_query_t query;
 	mlx5_flow_create_mtr_tbls_t create_mtr_tbls;
 	mlx5_flow_destroy_mtr_tbls_t destroy_mtr_tbls;
-	mlx5_flow_create_policer_rules_t prepare_policer_rules;
-	mlx5_flow_destroy_policer_rules_t destroy_policer_rules;
 	mlx5_flow_mtr_alloc_t create_meter;
 	mlx5_flow_mtr_free_t free_meter;
 	mlx5_flow_counter_alloc_t counter_alloc;
@@ -1392,12 +1384,6 @@ struct mlx5_meter_domains_infos *mlx5_flow_create_mtr_tbls
 					(struct rte_eth_dev *dev);
 int mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev,
 			       struct mlx5_meter_domains_infos *tbl);
-int mlx5_flow_prepare_policer_rules(struct rte_eth_dev *dev,
-				   struct mlx5_flow_meter_info *fm,
-				   const struct rte_flow_attr *attr);
-int mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,
-				    struct mlx5_flow_meter_info *fm,
-				    const struct rte_flow_attr *attr);
 int mlx5_flow_meter_flush(struct rte_eth_dev *dev,
 			  struct rte_mtr_error *error);
 int mlx5_flow_dv_discover_counter_offset_support(struct rte_eth_dev *dev);
diff --git a/drivers/net/mlx5/mlx5_flow_aso.c b/drivers/net/mlx5/mlx5_flow_aso.c
index cd2cc016b9..62d2df054b 100644
--- a/drivers/net/mlx5/mlx5_flow_aso.c
+++ b/drivers/net/mlx5/mlx5_flow_aso.c
@@ -808,8 +808,8 @@ mlx5_aso_meter_update_by_wqe(struct mlx5_dev_ctx_shared *sh,
 		/* Waiting for wqe resource. */
 		rte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
 	} while (--poll_wqe_times);
-	DRV_LOG(ERR, "Fail to send WQE for ASO meter %d",
-			mtr->fm.meter_id);
+	DRV_LOG(ERR, "Fail to send WQE for ASO meter offset %d",
+			mtr->offset);
 	return -1;
 }
 
@@ -844,7 +844,7 @@ mlx5_aso_mtr_wait(struct mlx5_dev_ctx_shared *sh,
 		/* Waiting for CQE ready. */
 		rte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
 	} while (--poll_cqe_times);
-	DRV_LOG(ERR, "Fail to poll CQE ready for ASO meter %d",
-			mtr->fm.meter_id);
+	DRV_LOG(ERR, "Fail to poll CQE ready for ASO meter offset %d",
+			mtr->offset);
 	return -1;
 }
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index c558147969..e7e4d17a25 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -185,31 +185,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. */
@@ -6026,12 +6001,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;
 }
@@ -6055,7 +6028,6 @@ flow_dv_aso_mtr_release_to_pool(struct rte_eth_dev *dev, uint32_t mtr_idx)
 	rte_spinlock_lock(&mtrmng->mtrsl);
 	memset(&aso_mtr->fm, 0, sizeof(struct mlx5_flow_meter_info));
 	aso_mtr->state = ASO_METER_FREE;
-	aso_mtr->fm.meter_id = UINT32_MAX;
 	LIST_INSERT_HEAD(&mtrmng->meters, aso_mtr, next);
 	rte_spinlock_unlock(&mtrmng->mtrsl);
 }
@@ -6095,8 +6067,8 @@ flow_dv_mtr_alloc(struct rte_eth_dev *dev)
 	mtr_free->state = ASO_METER_WAIT;
 	rte_spinlock_unlock(&mtrmng->mtrsl);
 	pool = container_of(mtr_free,
-					struct mlx5_aso_mtr_pool,
-					mtrs[mtr_free->offset]);
+			struct mlx5_aso_mtr_pool,
+			mtrs[mtr_free->offset]);
 	mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, mtr_free->offset);
 	if (!mtr_free->fm.meter_action) {
 #ifdef HAVE_MLX5_DR_CREATE_ACTION_ASO
@@ -13703,433 +13675,6 @@ flow_dv_create_mtr_tbl(struct rte_eth_dev *dev)
 	return NULL;
 }
 
-/**
- * Destroy the meter table matchers.
- * Lock free, (mutex should be acquired by caller).
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in,out] dtb
- *   Pointer to DV meter table.
- *
- * @return
- *   Always 0.
- */
-static int
-flow_dv_destroy_mtr_matchers(struct rte_eth_dev *dev,
-			     struct mlx5_meter_domain_info *dtb)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_flow_tbl_data_entry *tbl;
-
-	if (!priv->config.dv_flow_en)
-		return 0;
-	if (dtb->drop_matcher) {
-		tbl = container_of(dtb->drop_matcher->tbl, typeof(*tbl), tbl);
-		mlx5_cache_unregister(&tbl->matchers,
-				      &dtb->drop_matcher->entry);
-		dtb->drop_matcher = NULL;
-	}
-	if (dtb->color_matcher) {
-		tbl = container_of(dtb->color_matcher->tbl, typeof(*tbl), tbl);
-		mlx5_cache_unregister(&tbl->matchers,
-				      &dtb->color_matcher->entry);
-		dtb->color_matcher = NULL;
-	}
-	return 0;
-}
-
-/**
- * Create the matchers for meter table.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] color_reg_c_idx
- *   Reg C index for color match.
- * @param[in] mtr_id_reg_c_idx
- *   Reg C index for meter_id match.
- * @param[in] mtr_id_mask
- *   Mask for meter_id match criteria.
- * @param[in,out] dtb
- *   Pointer to DV meter table.
- * @param[out] error
- *   Perform verbose error reporting if not NULL.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-flow_dv_prepare_mtr_matchers(struct rte_eth_dev *dev,
-			     uint32_t color_reg_c_idx,
-			     uint32_t mtr_id_reg_c_idx,
-			     uint32_t mtr_id_mask,
-			     struct mlx5_meter_domain_info *dtb,
-			     struct rte_flow_error *error)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_flow_tbl_data_entry *tbl_data;
-	struct mlx5_cache_entry *entry;
-	struct mlx5_flow_dv_matcher matcher = {
-		.mask = {
-			.size = sizeof(matcher.mask.buf) -
-				MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-		},
-		.tbl = dtb->tbl,
-	};
-	struct mlx5_flow_dv_match_params value = {
-		.size = sizeof(value.buf) -
-			MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-	};
-	struct mlx5_flow_cb_ctx ctx = {
-		.error = error,
-		.data = &matcher,
-	};
-	uint32_t color_mask = (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
-
-	tbl_data = container_of(dtb->tbl, struct mlx5_flow_tbl_data_entry, tbl);
-	if (!dtb->drop_matcher) {
-		/* Create matchers for Drop. */
-		flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-				       mtr_id_reg_c_idx, 0, mtr_id_mask);
-		matcher.priority = MLX5_REG_BITS * 2 - priv->max_mtr_bits;
-		matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
-					matcher.mask.size);
-		entry = mlx5_cache_register(&tbl_data->matchers, &ctx);
-		if (!entry) {
-			DRV_LOG(ERR, "Failed to register meter drop matcher.");
-			return -1;
-		}
-		dtb->drop_matcher =
-			container_of(entry, struct mlx5_flow_dv_matcher, entry);
-	}
-	if (!dtb->color_matcher) {
-		/* Create matchers for Color + meter_id. */
-		if (priv->mtr_reg_share) {
-			flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-					color_reg_c_idx, 0,
-					(mtr_id_mask | color_mask));
-		} else {
-			flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-					color_reg_c_idx, 0, color_mask);
-			flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-					mtr_id_reg_c_idx, 0, mtr_id_mask);
-		}
-		matcher.priority = MLX5_REG_BITS - priv->max_mtr_bits;
-		matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
-					matcher.mask.size);
-		entry = mlx5_cache_register(&tbl_data->matchers, &ctx);
-		if (!entry) {
-			DRV_LOG(ERR, "Failed to register meter color matcher.");
-			return -1;
-		}
-		dtb->color_matcher =
-			container_of(entry, struct mlx5_flow_dv_matcher, entry);
-	}
-	return 0;
-}
-
-/**
- * Destroy domain policer rule.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] dt
- *   Pointer to domain table.
- */
-static void
-flow_dv_destroy_domain_policer_rule(struct rte_eth_dev *dev,
-				    struct mlx5_meter_domain_info *dt)
-{
-	if (dt->drop_rule) {
-		claim_zero(mlx5_flow_os_destroy_flow(dt->drop_rule));
-		dt->drop_rule = NULL;
-	}
-	if (dt->green_rule) {
-		claim_zero(mlx5_flow_os_destroy_flow(dt->green_rule));
-		dt->green_rule = NULL;
-	}
-	flow_dv_destroy_mtr_matchers(dev, dt);
-	if (dt->jump_actn) {
-		claim_zero(mlx5_flow_os_destroy_flow_action(dt->jump_actn));
-		dt->jump_actn = NULL;
-	}
-}
-
-/**
- * Destroy policer rules.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] attr
- *   Pointer to flow attributes.
- *
- * @return
- *   Always 0.
- */
-static int
-flow_dv_destroy_policer_rules(struct rte_eth_dev *dev,
-			      const struct mlx5_flow_meter_info *fm,
-			      const struct rte_flow_attr *attr)
-{
-	struct mlx5_meter_domains_infos *mtb = fm ? fm->mfts : NULL;
-
-	if (!mtb)
-		return 0;
-	if (attr->egress)
-		flow_dv_destroy_domain_policer_rule(dev, &mtb->egress);
-	if (attr->ingress)
-		flow_dv_destroy_domain_policer_rule(dev, &mtb->ingress);
-	if (attr->transfer)
-		flow_dv_destroy_domain_policer_rule(dev, &mtb->transfer);
-	return 0;
-}
-
-/**
- * Create specify domain meter policer rule.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] mtr_idx
- *   meter index.
- * @param[in] mtb
- *   Pointer to DV meter table set.
- * @param[out] drop_rule
- *   The address of pointer saving drop rule.
- * @param[out] color_rule
- *   The address of pointer saving green rule.
- *
- * @return
- *   0 on success, -1 otherwise.
- */
-static int
-flow_dv_create_policer_forward_rule(struct rte_eth_dev *dev,
-				    struct mlx5_flow_meter_info *fm,
-				    uint32_t mtr_idx,
-				    struct mlx5_meter_domain_info *dtb,
-				    void **drop_rule,
-				    void **green_rule)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_flow_dv_match_params matcher = {
-		.size = sizeof(matcher.buf) -
-			MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-	};
-	struct mlx5_flow_dv_match_params value = {
-		.size = sizeof(value.buf) -
-			MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-	};
-	struct mlx5_meter_domains_infos *mtb = fm->mfts;
-	struct rte_flow_error error;
-	uint32_t color_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR,
-						    0, &error);
-	uint32_t mtr_id_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_ID,
-						     0, &error);
-	uint8_t mtr_id_offset = priv->mtr_reg_share ? MLX5_MTR_COLOR_BITS : 0;
-	uint32_t mtr_id_mask =
-		((UINT32_C(1) << priv->max_mtr_bits) - 1) << mtr_id_offset;
-	void *actions[METER_ACTIONS];
-	int i;
-	int ret = 0;
-
-	/* Create jump action. */
-	if (!dtb->jump_actn)
-		ret = mlx5_flow_os_create_flow_action_dest_flow_tbl
-				(dtb->sfx_tbl->obj, &dtb->jump_actn);
-	if (ret) {
-		DRV_LOG(ERR, "Failed to create policer jump action.");
-		goto error;
-	}
-	/* Prepare matchers. */
-	if (!dtb->drop_matcher || !dtb->color_matcher) {
-		ret = flow_dv_prepare_mtr_matchers(dev, color_reg_c,
-						   mtr_id_reg_c, mtr_id_mask,
-						   dtb, &error);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to setup matchers for mtr table.");
-			goto error;
-		}
-	}
-	/* Create Drop flow, matching meter_id only. */
-	i = 0;
-	flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c,
-			       (mtr_idx << mtr_id_offset), UINT32_MAX);
-	if (mtb->drop_count)
-		actions[i++] = mtb->drop_count;
-	actions[i++] = priv->sh->dr_drop_action;
-	ret = mlx5_flow_os_create_flow(dtb->drop_matcher->matcher_object,
-				       (void *)&value, i, actions, drop_rule);
-	if (ret) {
-		DRV_LOG(ERR, "Failed to create meter policer drop rule.");
-		goto error;
-	}
-	/* Create flow matching Green color + meter_id. */
-	i = 0;
-	if (priv->mtr_reg_share) {
-		flow_dv_match_meta_reg(matcher.buf, value.buf, color_reg_c,
-				       ((mtr_idx << mtr_id_offset) |
-					rte_col_2_mlx5_col(RTE_COLOR_GREEN)),
-				       UINT32_MAX);
-	} else {
-		flow_dv_match_meta_reg(matcher.buf, value.buf, color_reg_c,
-				       rte_col_2_mlx5_col(RTE_COLOR_GREEN),
-				       UINT32_MAX);
-		flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c,
-				       mtr_idx, UINT32_MAX);
-	}
-	if (mtb->green_count)
-		actions[i++] = mtb->green_count;
-	actions[i++] = dtb->jump_actn;
-	ret = mlx5_flow_os_create_flow(dtb->color_matcher->matcher_object,
-				       (void *)&value, i, actions, green_rule);
-	if (ret) {
-		DRV_LOG(ERR, "Failed to create meter policer color rule.");
-		goto error;
-	}
-	return 0;
-error:
-	rte_errno = errno;
-	return -1;
-}
-
-/**
- * Prepare policer rules for all domains.
- * If meter already initialized, this will replace all old rules with new ones.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] attr
- *   Pointer to flow attributes.
- *
- * @return
- *   0 on success, -1 otherwise.
- */
-static int
-flow_dv_prepare_policer_rules(struct rte_eth_dev *dev,
-			      struct mlx5_flow_meter_info *fm,
-			      const struct rte_flow_attr *attr)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_meter_domains_infos *mtb = fm->mfts;
-	bool initialized = false;
-	struct mlx5_flow_counter *cnt;
-	void *egress_drop_rule = NULL;
-	void *egress_green_rule = NULL;
-	void *ingress_drop_rule = NULL;
-	void *ingress_green_rule = NULL;
-	void *transfer_drop_rule = NULL;
-	void *transfer_green_rule = NULL;
-	uint32_t mtr_idx;
-	int ret;
-
-	/* Get the statistics counters for green/drop. */
-	if (fm->policer_stats.pass_cnt) {
-		cnt = flow_dv_counter_get_by_idx(dev,
-					fm->policer_stats.pass_cnt,
-					NULL);
-		mtb->green_count = cnt->action;
-	} else {
-		mtb->green_count = NULL;
-	}
-	if (fm->policer_stats.drop_cnt) {
-		cnt = flow_dv_counter_get_by_idx(dev,
-					fm->policer_stats.drop_cnt,
-					NULL);
-		mtb->drop_count = cnt->action;
-	} else {
-		mtb->drop_count = NULL;
-	}
-	/**
-	 * If flow meter has been initialized, all policer rules
-	 * are created. So can get if meter initialized by checking
-	 * any policer rule.
-	 */
-	if (mtb->egress.drop_rule)
-		initialized = true;
-	if (priv->sh->meter_aso_en) {
-		struct mlx5_aso_mtr *aso_mtr = NULL;
-		struct mlx5_aso_mtr_pool *pool;
-
-		aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
-		pool = container_of(aso_mtr, struct mlx5_aso_mtr_pool,
-				    mtrs[aso_mtr->offset]);
-		mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, aso_mtr->offset);
-	} else {
-		struct mlx5_legacy_flow_meter *legacy_fm;
-
-		legacy_fm = container_of(fm, struct mlx5_legacy_flow_meter, fm);
-		mtr_idx = legacy_fm->idx;
-	}
-	if (attr->egress) {
-		ret = flow_dv_create_policer_forward_rule(dev,
-				fm, mtr_idx, &mtb->egress,
-				&egress_drop_rule, &egress_green_rule);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to create egress policer.");
-			goto error;
-		}
-	}
-	if (attr->ingress) {
-		ret = flow_dv_create_policer_forward_rule(dev,
-				fm, mtr_idx, &mtb->ingress,
-				&ingress_drop_rule, &ingress_green_rule);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to create ingress policer.");
-			goto error;
-		}
-	}
-	if (attr->transfer) {
-		ret = flow_dv_create_policer_forward_rule(dev,
-				fm, mtr_idx, &mtb->transfer,
-				&transfer_drop_rule, &transfer_green_rule);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to create transfer policer.");
-			goto error;
-		}
-	}
-	/* Replace old flows if existing. */
-	if (mtb->egress.drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->egress.drop_rule));
-	if (mtb->egress.green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->egress.green_rule));
-	if (mtb->ingress.drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->ingress.drop_rule));
-	if (mtb->ingress.green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->ingress.green_rule));
-	if (mtb->transfer.drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->transfer.drop_rule));
-	if (mtb->transfer.green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->transfer.green_rule));
-	mtb->egress.drop_rule = egress_drop_rule;
-	mtb->egress.green_rule = egress_green_rule;
-	mtb->ingress.drop_rule = ingress_drop_rule;
-	mtb->ingress.green_rule = ingress_green_rule;
-	mtb->transfer.drop_rule = transfer_drop_rule;
-	mtb->transfer.green_rule = transfer_green_rule;
-	return 0;
-error:
-	if (egress_drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(egress_drop_rule));
-	if (egress_green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(egress_green_rule));
-	if (ingress_drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(ingress_drop_rule));
-	if (ingress_green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(ingress_green_rule));
-	if (transfer_drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(transfer_drop_rule));
-	if (transfer_green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(transfer_green_rule));
-	if (!initialized)
-		flow_dv_destroy_policer_rules(dev, fm, attr);
-	return -1;
-}
-
 /**
  * Validate the batch counter support in root table.
  *
@@ -14424,8 +13969,6 @@ const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {
 	.query = flow_dv_query,
 	.create_mtr_tbls = flow_dv_create_mtr_tbl,
 	.destroy_mtr_tbls = flow_dv_destroy_mtr_tbl,
-	.prepare_policer_rules = flow_dv_prepare_policer_rules,
-	.destroy_policer_rules = flow_dv_destroy_policer_rules,
 	.create_meter = flow_dv_mtr_alloc,
 	.free_meter = flow_dv_aso_mtr_release_to_pool,
 	.counter_alloc = flow_dv_counter_allocate,
diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c
index 714b382d55..af0a1c18cb 100644
--- a/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/drivers/net/mlx5/mlx5_flow_meter.c
@@ -329,7 +329,6 @@ mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
 	cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */
 	cap->meter_srtcm_rfc2697_n_max = qattr->flow_meter_old ? cap->n_max : 0;
 	cap->meter_rate_max = 1ULL << 40; /* 1 Tera tokens per sec. */
-	cap->policer_action_drop_supported = 1;
 	cap->stats_mask = RTE_MTR_STATS_N_BYTES_DROPPED |
 			  RTE_MTR_STATS_N_PKTS_DROPPED;
 	return 0;
@@ -436,90 +435,6 @@ mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,
 	return 0;
 }
 
-/**
- * Convert wrong color setting action to verbose error.
- *
- * @param[in] action
- *   Policy color action.
- *
- * @return
- *   Verbose meter color error type.
- */
-static inline enum rte_mtr_error_type
-action2error(enum rte_mtr_policer_action action)
-{
-	switch (action) {
-	case MTR_POLICER_ACTION_COLOR_GREEN:
-		return RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN;
-	case MTR_POLICER_ACTION_COLOR_YELLOW:
-		return RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW;
-	case MTR_POLICER_ACTION_COLOR_RED:
-		return RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED;
-	default:
-		break;
-	}
-	return RTE_MTR_ERROR_TYPE_UNSPECIFIED;
-}
-
-/**
- * Check meter validation.
- *
- * @param[in] priv
- *   Pointer to mlx5 private data structure.
- * @param[in] meter_id
- *   Meter id.
- * @param[in] params
- *   Pointer to rte meter parameters.
- * @param[out] error
- *   Pointer to rte meter error structure.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,
-			 struct rte_mtr_params *params,
-			 struct rte_mtr_error *error)
-{
-	/* Meter must use global drop action. */
-	if (!priv->sh->dr_drop_action)
-		return -rte_mtr_error_set(error, ENOTSUP,
-					  RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-					  NULL,
-					  "No drop action ready for meter.");
-	/* Meter params must not be NULL. */
-	if (params == NULL)
-		return -rte_mtr_error_set(error, EINVAL,
-					  RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-					  NULL, "Meter object params null.");
-	/* Previous meter color is not supported. */
-	if (params->use_prev_mtr_color)
-		return -rte_mtr_error_set(error, ENOTSUP,
-					  RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-					  NULL,
-					  "Previous meter color "
-					  "not supported.");
-	/* Validate policer settings. */
-	if (params->action[RTE_COLOR_RED] != MTR_POLICER_ACTION_DROP)
-		return -rte_mtr_error_set
-				(error, ENOTSUP,
-				 action2error(params->action[RTE_COLOR_RED]),
-				 NULL,
-				 "Red color only supports drop action.");
-	if (params->action[RTE_COLOR_GREEN] != MTR_POLICER_ACTION_COLOR_GREEN)
-		return -rte_mtr_error_set
-				(error, ENOTSUP,
-				 action2error(params->action[RTE_COLOR_GREEN]),
-				 NULL,
-				 "Green color only supports recolor green action.");
-	/* Validate meter id. */
-	if (mlx5_flow_meter_find(priv, meter_id, NULL))
-		return -rte_mtr_error_set(error, EEXIST,
-					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
-					  "Meter object already exists.");
-	return 0;
-}
-
 /**
  * Modify the flow meter action.
  *
@@ -629,167 +544,14 @@ static void
 mlx5_flow_meter_stats_enable_update(struct mlx5_flow_meter_info *fm,
 				uint64_t stats_mask)
 {
-	fm->green_bytes = (stats_mask & RTE_MTR_STATS_N_BYTES_GREEN) ? 1 : 0;
-	fm->green_pkts = (stats_mask & RTE_MTR_STATS_N_PKTS_GREEN) ? 1 : 0;
-	fm->red_bytes = (stats_mask & RTE_MTR_STATS_N_BYTES_RED) ? 1 : 0;
-	fm->red_pkts = (stats_mask & RTE_MTR_STATS_N_PKTS_RED) ? 1 : 0;
 	fm->bytes_dropped =
 		(stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED) ? 1 : 0;
 	fm->pkts_dropped = (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED) ? 1 : 0;
 }
 
-/**
- * Create meter rules.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] meter_id
- *   Meter id.
- * @param[in] params
- *   Pointer to rte meter parameters.
- * @param[in] shared
- *   Meter shared with other flow or not.
- * @param[out] error
- *   Pointer to rte meter error structure.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
-		       struct rte_mtr_params *params, int shared,
-		       struct rte_mtr_error *error)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_legacy_flow_meters *fms = &priv->flow_meters;
-	struct mlx5_flow_meter_profile *fmp;
-	struct mlx5_legacy_flow_meter *legacy_fm;
-	struct mlx5_flow_meter_info *fm;
-	const struct rte_flow_attr attr = {
-				.ingress = 1,
-				.egress = 1,
-				.transfer = priv->config.dv_esw_en ? 1 : 0,
-			};
-	struct mlx5_indexed_pool_config flow_ipool_cfg = {
-		.size = 0,
-		.trunk_size = 64,
-		.need_lock = 1,
-		.type = "mlx5_flow_mtr_flow_id_pool",
-	};
-	struct mlx5_aso_mtr *aso_mtr;
-	union mlx5_l3t_data data;
-	uint32_t mtr_idx;
-	int ret;
-	uint8_t mtr_id_bits;
-	uint8_t mtr_reg_bits = priv->mtr_reg_share ?
-				MLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS;
-
-	if (!priv->mtr_en)
-		return -rte_mtr_error_set(error, ENOTSUP,
-					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Meter is not supported");
-	/* Validate the parameters. */
-	ret = mlx5_flow_meter_validate(priv, meter_id, params, error);
-	if (ret)
-		return ret;
-	/* Meter profile must exist. */
-	fmp = mlx5_flow_meter_profile_find(priv, params->meter_profile_id);
-	if (fmp == NULL)
-		return -rte_mtr_error_set(error, ENOENT,
-					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-					  NULL, "Meter profile id not valid.");
-	/* Allocate the flow meter memory. */
-	if (priv->sh->meter_aso_en) {
-		mtr_idx = mlx5_flow_mtr_alloc(dev);
-		if (!mtr_idx)
-			return -rte_mtr_error_set(error, ENOMEM,
-				RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-				"Memory alloc failed for meter.");
-		aso_mtr = mlx5_aso_meter_by_idx(priv, mtr_idx);
-		fm = &aso_mtr->fm;
-	} else {
-		legacy_fm = mlx5_ipool_zmalloc
-				(priv->sh->ipool[MLX5_IPOOL_MTR], &mtr_idx);
-		if (legacy_fm == NULL)
-			return -rte_mtr_error_set(error, ENOMEM,
-				RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-				"Memory alloc failed for meter.");
-		legacy_fm->idx = mtr_idx;
-		fm = &legacy_fm->fm;
-	}
-	mtr_id_bits = MLX5_REG_BITS - __builtin_clz(mtr_idx);
-	if ((mtr_id_bits + priv->max_mtr_flow_bits) > mtr_reg_bits) {
-		DRV_LOG(ERR, "Meter number exceeds max limit.");
-		goto error;
-	}
-	if (mtr_id_bits > priv->max_mtr_bits)
-		priv->max_mtr_bits = mtr_id_bits;
-	/* Fill the flow meter parameters. */
-	fm->meter_id = meter_id;
-	fm->profile = fmp;
-	memcpy(fm->action, params->action, sizeof(params->action));
-	mlx5_flow_meter_stats_enable_update(fm, params->stats_mask);
-	/* Alloc policer counters. */
-	if (fm->green_bytes || fm->green_pkts) {
-		fm->policer_stats.pass_cnt = mlx5_counter_alloc(dev);
-		if (!fm->policer_stats.pass_cnt)
-			goto error;
-	}
-	if (fm->red_bytes || fm->red_pkts ||
-	    fm->bytes_dropped || fm->pkts_dropped) {
-		fm->policer_stats.drop_cnt = mlx5_counter_alloc(dev);
-		if (!fm->policer_stats.drop_cnt)
-			goto error;
-	}
-	fm->mfts = mlx5_flow_create_mtr_tbls(dev);
-	if (!fm->mfts)
-		goto error;
-	ret = mlx5_flow_prepare_policer_rules(dev, fm, &attr);
-	if (ret)
-		goto error;
-	/* Add to the flow meter list. */
-	if (!priv->sh->meter_aso_en)
-		TAILQ_INSERT_TAIL(fms, legacy_fm, next);
-	fm->active_state = 1; /* Config meter starts as active. */
-	fm->is_enable = 1;
-	fm->shared = !!shared;
-	__atomic_add_fetch(&fm->profile->ref_cnt, 1, __ATOMIC_RELAXED);
-	fm->flow_ipool = mlx5_ipool_create(&flow_ipool_cfg);
-	if (!fm->flow_ipool)
-		goto error;
-	rte_spinlock_init(&fm->sl);
-	/* If ASO meter supported, allocate ASO flow meter. */
-	if (priv->sh->meter_aso_en) {
-		aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
-		ret = mlx5_aso_meter_update_by_wqe(priv->sh, aso_mtr);
-		if (ret)
-			goto error;
-		data.dword = mtr_idx;
-		if (mlx5_l3t_set_entry(priv->mtr_idx_tbl, meter_id, &data))
-			goto error;
-	}
-	return 0;
-error:
-	mlx5_flow_destroy_policer_rules(dev, fm, &attr);
-	mlx5_flow_destroy_mtr_tbls(dev, fm->mfts);
-	/* Free policer counters. */
-	if (fm->policer_stats.pass_cnt)
-		mlx5_counter_free(dev, fm->policer_stats.pass_cnt);
-	if (fm->policer_stats.drop_cnt)
-		mlx5_counter_free(dev, fm->policer_stats.drop_cnt);
-	if (priv->sh->meter_aso_en)
-		mlx5_flow_mtr_free(dev, mtr_idx);
-	else
-		mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], mtr_idx);
-	return -rte_mtr_error_set(error, -ret,
-				  RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Failed to create devx meter.");
-}
-
 static int
 mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
 			struct mlx5_flow_meter_info *fm,
-			const struct rte_flow_attr *attr,
 			uint32_t mtr_idx)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
@@ -810,15 +572,12 @@ mlx5_flow_meter_params_flush(struct rte_eth_dev *dev,
 		legacy_fm = container_of(fm, struct mlx5_legacy_flow_meter, fm);
 		TAILQ_REMOVE(fms, legacy_fm, next);
 	}
-	/* Free policer counters. */
-	if (fm->policer_stats.pass_cnt)
-		mlx5_counter_free(dev, fm->policer_stats.pass_cnt);
-	if (fm->policer_stats.drop_cnt)
-		mlx5_counter_free(dev, fm->policer_stats.drop_cnt);
+	/* Free drop counters. */
+	if (fm->drop_cnt)
+		mlx5_counter_free(dev, fm->drop_cnt);
 	/* Free meter flow table. */
 	if (fm->flow_ipool)
 		mlx5_ipool_destroy(fm->flow_ipool);
-	mlx5_flow_destroy_policer_rules(dev, fm, attr);
 	mlx5_flow_destroy_mtr_tbls(dev, fm->mfts);
 	if (priv->sh->meter_aso_en)
 		mlx5_flow_mtr_free(dev, mtr_idx);
@@ -847,11 +606,6 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_flow_meter_info *fm;
-	const struct rte_flow_attr attr = {
-				.ingress = 1,
-				.egress = 1,
-				.transfer = priv->config.dv_esw_en ? 1 : 0,
-			};
 	uint32_t mtr_idx = 0;
 
 	if (!priv->mtr_en)
@@ -876,7 +630,7 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
 				"Fail to delete ASO Meter in index table.");
 	}
 	/* Destroy the meter profile. */
-	if (mlx5_flow_meter_params_flush(dev, fm, &attr, mtr_idx))
+	if (mlx5_flow_meter_params_flush(dev, fm, mtr_idx))
 		return -rte_mtr_error_set(error, EINVAL,
 					RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
 					NULL, "MTR object meter profile invalid.");
@@ -1102,13 +856,6 @@ mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_flow_meter_info *fm;
-	const struct rte_flow_attr attr = {
-				.ingress = 1,
-				.egress = 1,
-				.transfer = priv->config.dv_esw_en ? 1 : 0,
-			};
-	bool need_updated = false;
-	struct mlx5_flow_policer_stats old_policer_stats;
 
 	if (!priv->mtr_en)
 		return -rte_mtr_error_set(error, ENOTSUP,
@@ -1120,69 +867,6 @@ mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
 		return -rte_mtr_error_set(error, ENOENT,
 					  RTE_MTR_ERROR_TYPE_MTR_ID,
 					  NULL, "Meter object id not valid.");
-	old_policer_stats.pass_cnt = 0;
-	old_policer_stats.drop_cnt = 0;
-	if (!!((RTE_MTR_STATS_N_PKTS_GREEN |
-				RTE_MTR_STATS_N_BYTES_GREEN) & stats_mask) !=
-		!!fm->policer_stats.pass_cnt) {
-		need_updated = true;
-		if (fm->policer_stats.pass_cnt) {
-			old_policer_stats.pass_cnt = fm->policer_stats.pass_cnt;
-			fm->policer_stats.pass_cnt = 0;
-		} else {
-			fm->policer_stats.pass_cnt =
-				mlx5_counter_alloc(dev);
-			if (!fm->policer_stats.pass_cnt)
-				return -rte_mtr_error_set(error, ENOMEM,
-					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Counter alloc failed for meter.");
-		}
-	}
-	if (!!((RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_BYTES_RED |
-		RTE_MTR_STATS_N_PKTS_DROPPED | RTE_MTR_STATS_N_BYTES_DROPPED) &
-		stats_mask) !=
-		!!fm->policer_stats.drop_cnt) {
-		need_updated = true;
-		if (fm->policer_stats.drop_cnt) {
-			old_policer_stats.drop_cnt = fm->policer_stats.drop_cnt;
-			fm->policer_stats.drop_cnt = 0;
-		} else {
-			fm->policer_stats.drop_cnt =
-				mlx5_counter_alloc(dev);
-			if (!fm->policer_stats.drop_cnt)
-				return -rte_mtr_error_set(error, ENOMEM,
-					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Counter alloc failed for meter.");
-		}
-	}
-	if (need_updated) {
-		if (mlx5_flow_prepare_policer_rules(dev, fm, &attr)) {
-			if (fm->policer_stats.pass_cnt &&
-				fm->policer_stats.pass_cnt !=
-				old_policer_stats.pass_cnt)
-				mlx5_counter_free(dev,
-					fm->policer_stats.pass_cnt);
-			fm->policer_stats.pass_cnt =
-					old_policer_stats.pass_cnt;
-			if (fm->policer_stats.drop_cnt &&
-				fm->policer_stats.drop_cnt !=
-				old_policer_stats.drop_cnt)
-				mlx5_counter_free(dev,
-					fm->policer_stats.drop_cnt);
-			fm->policer_stats.pass_cnt =
-					old_policer_stats.pass_cnt;
-			return -rte_mtr_error_set(error, ENOTSUP,
-				RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-				NULL, "Failed to create meter policer rules.");
-		}
-		/* Free old policer counters. */
-		if (old_policer_stats.pass_cnt)
-			mlx5_counter_free(dev,
-				old_policer_stats.pass_cnt);
-		if (old_policer_stats.drop_cnt)
-			mlx5_counter_free(dev,
-				old_policer_stats.drop_cnt);
-	}
 	mlx5_flow_meter_stats_enable_update(fm, stats_mask);
 	return 0;
 }
@@ -1216,7 +900,6 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_flow_meter_info *fm;
-	struct mlx5_flow_policer_stats *ps;
 	uint64_t pkts;
 	uint64_t bytes;
 	int ret = 0;
@@ -1231,35 +914,14 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
 		return -rte_mtr_error_set(error, ENOENT,
 					  RTE_MTR_ERROR_TYPE_MTR_ID,
 					  NULL, "Meter object id not valid.");
-	ps = &fm->policer_stats;
 	*stats_mask = 0;
-	if (fm->green_bytes)
-		*stats_mask |= RTE_MTR_STATS_N_BYTES_GREEN;
-	if (fm->green_pkts)
-		*stats_mask |= RTE_MTR_STATS_N_PKTS_GREEN;
-	if (fm->red_bytes)
-		*stats_mask |= RTE_MTR_STATS_N_BYTES_RED;
-	if (fm->red_pkts)
-		*stats_mask |= RTE_MTR_STATS_N_PKTS_RED;
 	if (fm->bytes_dropped)
 		*stats_mask |= RTE_MTR_STATS_N_BYTES_DROPPED;
 	if (fm->pkts_dropped)
 		*stats_mask |= RTE_MTR_STATS_N_PKTS_DROPPED;
 	memset(stats, 0, sizeof(*stats));
-	if (ps->pass_cnt) {
-		ret = mlx5_counter_query(dev, ps->pass_cnt, clear, &pkts,
-						 &bytes);
-		if (ret)
-			goto error;
-		/* If need to read the packets, set it. */
-		if (fm->green_pkts)
-			stats->n_pkts[RTE_COLOR_GREEN] = pkts;
-		/* If need to read the bytes, set it. */
-		if (fm->green_bytes)
-			stats->n_bytes[RTE_COLOR_GREEN] = bytes;
-	}
-	if (ps->drop_cnt) {
-		ret = mlx5_counter_query(dev, ps->drop_cnt, clear, &pkts,
+	if (fm->drop_cnt) {
+		ret = mlx5_counter_query(dev, fm->drop_cnt, clear, &pkts,
 						 &bytes);
 		if (ret)
 			goto error;
@@ -1273,20 +935,18 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
 	return 0;
 error:
 	return -rte_mtr_error_set(error, ret, RTE_MTR_ERROR_TYPE_STATS, NULL,
-				 "Failed to read policer counters.");
+				 "Failed to read meter drop counters.");
 }
 
 static const struct rte_mtr_ops mlx5_flow_mtr_ops = {
 	.capabilities_get = mlx5_flow_mtr_cap_get,
 	.meter_profile_add = mlx5_flow_meter_profile_add,
 	.meter_profile_delete = mlx5_flow_meter_profile_delete,
-	.create = mlx5_flow_meter_create,
 	.destroy = mlx5_flow_meter_destroy,
 	.meter_enable = mlx5_flow_meter_enable,
 	.meter_disable = mlx5_flow_meter_disable,
 	.meter_profile_update = mlx5_flow_meter_profile_update,
 	.meter_dscp_table_update = NULL,
-	.policer_actions_update = NULL,
 	.stats_update = mlx5_flow_meter_stats_update,
 	.stats_read = mlx5_flow_meter_stats_read,
 };
@@ -1344,12 +1004,11 @@ mlx5_flow_meter_find(struct mlx5_priv *priv, uint32_t meter_id,
 		aso_mtr = mlx5_aso_meter_by_idx(priv, data.dword);
 		/* Remove reference taken by the mlx5_l3t_get_entry. */
 		mlx5_l3t_clear_entry(priv->mtr_idx_tbl, meter_id);
-		MLX5_ASSERT(meter_id == aso_mtr->fm.meter_id);
 		rte_spinlock_unlock(&mtrmng->mtrsl);
 		return &aso_mtr->fm;
 	}
 	TAILQ_FOREACH(legacy_fm, fms, next)
-		if (meter_id == legacy_fm->fm.meter_id) {
+		if (meter_id == legacy_fm->meter_id) {
 			if (mtr_idx)
 				*mtr_idx = legacy_fm->idx;
 			return &legacy_fm->fm;
@@ -1517,11 +1176,6 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
 	struct mlx5_legacy_flow_meter *legacy_fm;
 	struct mlx5_flow_meter_info *fm;
 	struct mlx5_aso_mtr_pool *mtr_pool;
-	const struct rte_flow_attr attr = {
-				.ingress = 1,
-				.egress = 1,
-				.transfer = priv->config.dv_esw_en ? 1 : 0,
-			};
 	void *tmp;
 	uint32_t i, offset, mtr_idx;
 
@@ -1533,9 +1187,8 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
 				offset++) {
 				fm = &mtr_pool->mtrs[offset].fm;
 				mtr_idx = MLX5_MAKE_MTR_IDX(i, offset);
-				if (fm->meter_id != UINT32_MAX &&
-					mlx5_flow_meter_params_flush(dev,
-						fm, &attr, mtr_idx))
+				if (mlx5_flow_meter_params_flush(dev,
+						fm, mtr_idx))
 					return -rte_mtr_error_set
 					(error, EINVAL,
 					RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
@@ -1545,7 +1198,7 @@ mlx5_flow_meter_flush(struct rte_eth_dev *dev, struct rte_mtr_error *error)
 	} else {
 		TAILQ_FOREACH_SAFE(legacy_fm, fms, next, tmp) {
 			fm = &legacy_fm->fm;
-			if (mlx5_flow_meter_params_flush(dev, fm, &attr, 0))
+			if (mlx5_flow_meter_params_flush(dev, fm, 0))
 				return -rte_mtr_error_set(error, EINVAL,
 					RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
 					NULL, "MTR object meter profile invalid.");
diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index 7925bad1c0..27eaf380cd 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -1166,6 +1166,7 @@ flow_rule_action_get(struct pmd_internals *softnic,
 {
 	struct softnic_table_action_profile *profile;
 	struct softnic_table_action_profile_params *params;
+	struct softnic_mtr_meter_policy *policy;
 	int n_jump_queue_rss_drop = 0;
 	int n_count = 0;
 	int n_mark = 0;
@@ -1621,15 +1622,25 @@ flow_rule_action_get(struct pmd_internals *softnic,
 					return -1;
 				}
 			}
-
+			/* Meter policy must exist */
+			policy = softnic_mtr_meter_policy_find(softnic,
+					m->params.meter_policy_id);
+			if (policy == NULL) {
+				rte_flow_error_set(error,
+						EINVAL,
+						RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+						NULL,
+						"METER: fail to find meter policy");
+				return -1;
+			}
 			/* RTE_TABLE_ACTION_METER */
 			rule_action->mtr.mtr[0].meter_profile_id = meter_profile_id;
 			rule_action->mtr.mtr[0].policer[RTE_COLOR_GREEN] =
-				softnic_table_action_policer(m->params.action[RTE_COLOR_GREEN]);
+				policy->policer[RTE_COLOR_GREEN];
 			rule_action->mtr.mtr[0].policer[RTE_COLOR_YELLOW] =
-				softnic_table_action_policer(m->params.action[RTE_COLOR_YELLOW]);
+				policy->policer[RTE_COLOR_YELLOW];
 			rule_action->mtr.mtr[0].policer[RTE_COLOR_RED] =
-				softnic_table_action_policer(m->params.action[RTE_COLOR_RED]);
+				policy->policer[RTE_COLOR_RED];
 			rule_action->mtr.tc_mask = 1;
 			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
 			break;
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index faf90a5a8c..1b3186ef0b 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -83,6 +83,16 @@ struct softnic_mtr_meter_profile {
 
 TAILQ_HEAD(softnic_mtr_meter_profile_list, softnic_mtr_meter_profile);
 
+/* MTR meter policy */
+struct softnic_mtr_meter_policy {
+	TAILQ_ENTRY(softnic_mtr_meter_policy) node;
+	uint32_t meter_policy_id;
+	enum rte_table_action_policer policer[RTE_COLORS];
+	uint32_t n_users;
+};
+
+TAILQ_HEAD(softnic_mtr_meter_policy_list, softnic_mtr_meter_policy);
+
 /* MTR meter object */
 struct softnic_mtr {
 	TAILQ_ENTRY(softnic_mtr) node;
@@ -95,6 +105,7 @@ TAILQ_HEAD(softnic_mtr_list, softnic_mtr);
 
 struct mtr_internals {
 	struct softnic_mtr_meter_profile_list meter_profiles;
+	struct softnic_mtr_meter_policy_list meter_policies;
 	struct softnic_mtr_list mtrs;
 };
 
@@ -678,6 +689,10 @@ struct softnic_mtr_meter_profile *
 softnic_mtr_meter_profile_find(struct pmd_internals *p,
 	uint32_t meter_profile_id);
 
+struct softnic_mtr_meter_policy *
+softnic_mtr_meter_policy_find(struct pmd_internals *p,
+	uint32_t meter_policy_id);
+
 extern const struct rte_mtr_ops pmd_mtr_ops;
 
 /**
@@ -841,9 +856,6 @@ softnic_table_action_profile_create(struct pmd_internals *p,
 	const char *name,
 	struct softnic_table_action_profile_params *params);
 
-enum rte_table_action_policer
-softnic_table_action_policer(enum rte_mtr_policer_action action);
-
 /**
  * Pipeline
  */
diff --git a/drivers/net/softnic/rte_eth_softnic_meter.c b/drivers/net/softnic/rte_eth_softnic_meter.c
index b27b1285e9..f4e0640621 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,
@@ -208,6 +187,153 @@ 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 add */
+static int
+pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
+	uint32_t meter_policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error)
+{
+	struct pmd_internals *p = dev->data->dev_private;
+	struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
+	struct softnic_mtr_meter_policy *mp;
+	const struct rte_flow_action *act;
+	const struct rte_flow_action_meter_color *recolor;
+	uint32_t i;
+	bool valid_act_found;
+
+	if (policy == NULL)
+		return -rte_mtr_error_set(error,
+			EINVAL,
+			RTE_MTR_ERROR_TYPE_METER_POLICY,
+			NULL,
+			"Null meter policy invalid");
+
+	/* Meter policy must not 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 already exists");
+
+	for (i = 0; i < RTE_COLORS; i++) {
+		if (policy->actions[i] == NULL)
+			return -rte_mtr_error_set(error,
+				EINVAL,
+				RTE_MTR_ERROR_TYPE_METER_POLICY,
+				NULL,
+				"Null action list");
+		for (act = policy->actions[i], valid_act_found = false;
+			act && act->type != RTE_FLOW_ACTION_TYPE_END;
+			act++) {
+			/*
+			 * Support one (and one only) of
+			 * METER_COLOR or DROP action.
+			 */
+			if ((act->type != RTE_FLOW_ACTION_TYPE_METER_COLOR &&
+				act->type != RTE_FLOW_ACTION_TYPE_DROP) ||
+				valid_act_found)
+				return -rte_mtr_error_set(error,
+					EINVAL,
+					RTE_MTR_ERROR_TYPE_METER_POLICY,
+					NULL,
+					"Action invalid");
+			valid_act_found = true;
+		}
+	}
+
+	/* Memory allocation */
+	mp = calloc(1, sizeof(struct softnic_mtr_meter_policy));
+	if (mp == NULL)
+		return -rte_mtr_error_set(error,
+			ENOMEM,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			"Memory alloc failed");
+
+	/* Fill in */
+	mp->meter_policy_id = meter_policy_id;
+	for (i = 0; i < RTE_COLORS; i++) {
+		mp->policer[i] = RTE_TABLE_ACTION_POLICER_DROP;
+		act = policy->actions[i];
+		if (!act)
+			continue;
+		if (act->type == RTE_FLOW_ACTION_TYPE_METER_COLOR) {
+			recolor = act->conf;
+			switch (recolor->color) {
+			case RTE_COLOR_GREEN:
+				mp->policer[i] =
+				RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
+				break;
+			case RTE_COLOR_YELLOW:
+				mp->policer[i] =
+				RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
+				break;
+			case RTE_COLOR_RED:
+				mp->policer[i] =
+				RTE_TABLE_ACTION_POLICER_COLOR_RED;
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+	/* Add to list */
+	TAILQ_INSERT_TAIL(mpl, mp, node);
+
+	return 0;
+}
+
+/* MTR meter policy delete */
+static int
+pmd_mtr_meter_policy_delete(struct rte_eth_dev *dev,
+	uint32_t meter_policy_id,
+	struct rte_mtr_error *error)
+{
+	struct pmd_internals *p = dev->data->dev_private;
+	struct softnic_mtr_meter_policy *mp;
+
+	/* Meter policy must exist */
+	mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
+	if (mp == NULL)
+		return -rte_mtr_error_set(error,
+			EINVAL,
+			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+			NULL,
+			"Meter policy id invalid");
+
+	/* Check unused */
+	if (mp->n_users)
+		return -rte_mtr_error_set(error,
+			EBUSY,
+			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+			NULL,
+			"Meter policy in use");
+
+	/* Remove from list */
+	TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
+	free(mp);
+
+	return 0;
+}
+
 struct softnic_mtr *
 softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
 {
@@ -275,6 +401,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;
 
@@ -292,6 +419,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)
@@ -310,6 +447,7 @@ pmd_mtr_create(struct rte_eth_dev *dev,
 
 	/* Update dependencies */
 	mp->n_users++;
+	policy->n_users++;
 
 	return 0;
 }
@@ -324,6 +462,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);
@@ -351,8 +490,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);
@@ -514,18 +663,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);
@@ -536,28 +685,17 @@ pmd_mtr_policer_actions_update(struct rte_eth_dev *dev,
 			NULL,
 			"MTR object id not valid");
 
-	/* Valid policer actions */
-	if (actions == NULL)
+	if (m->params.meter_policy_id == meter_policy_id)
+		return 0;
+
+	/* 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) {
@@ -569,9 +707,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,
@@ -595,10 +731,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;
 }
@@ -615,28 +761,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];
 		}
 
@@ -647,16 +805,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];
 		}
 
@@ -722,7 +884,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);
@@ -743,6 +906,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_add = pmd_mtr_meter_policy_add,
+	.meter_policy_delete = pmd_mtr_meter_policy_delete,
+
 	.create = pmd_mtr_create,
 	.destroy = pmd_mtr_destroy,
 	.meter_enable = NULL,
@@ -750,7 +916,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 203c4cde9a..66ae3fd1ee 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -32,6 +32,7 @@
 #include <rte_ecpri.h>
 #include <rte_mbuf.h>
 #include <rte_mbuf_dyn.h>
+#include <rte_meter.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -2267,6 +2268,14 @@ enum rte_flow_action_type {
 	 * See struct rte_flow_action_modify_field.
 	 */
 	RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
+
+	/**
+	 * Color the packet to reflect the meter color result.
+	 * Set the meter color in the mbuf to the selected color.
+	 *
+	 * See struct rte_flow_action_meter_color.
+	 */
+	RTE_FLOW_ACTION_TYPE_METER_COLOR,
 };
 
 /**
@@ -2859,6 +2868,19 @@ struct rte_flow_action_set_dscp {
  */
 struct rte_flow_shared_action;
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
+ * RTE_FLOW_ACTION_TYPE_METER_COLOR
+ *
+ * The meter color should be set in the packet meta-data
+ * (i.e. struct rte_mbuf::sched::color).
+ */
+struct rte_flow_action_meter_color {
+	enum rte_color color; /**< Packet color. */
+};
+
 /**
  * Field IDs for MODIFY_FIELD action.
  */
diff --git a/lib/librte_ethdev/rte_mtr.c b/lib/librte_ethdev/rte_mtr.c
index 3073ac03f2..e49fcf271c 100644
--- a/lib/librte_ethdev/rte_mtr.c
+++ b/lib/librte_ethdev/rte_mtr.c
@@ -91,6 +91,40 @@ rte_mtr_meter_profile_delete(uint16_t port_id,
 		meter_profile_id, error);
 }
 
+/* MTR meter policy validate */
+int
+rte_mtr_meter_policy_validate(uint16_t port_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_policy_validate)(dev,
+		policy, error);
+}
+
+/* MTR meter policy add */
+int
+rte_mtr_meter_policy_add(uint16_t port_id,
+	uint32_t policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_policy_add)(dev,
+		policy_id, policy, error);
+}
+
+/** MTR meter policy delete */
+int
+rte_mtr_meter_policy_delete(uint16_t port_id,
+	uint32_t policy_id,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_policy_delete)(dev,
+		policy_id, error);
+}
+
 /** MTR object create */
 int
 rte_mtr_create(uint16_t port_id,
@@ -149,29 +183,28 @@ rte_mtr_meter_profile_update(uint16_t port_id,
 		mtr_id, meter_profile_id, error);
 }
 
-/** MTR object meter DSCP table update */
+/** MTR object meter policy update */
 int
-rte_mtr_meter_dscp_table_update(uint16_t port_id,
+rte_mtr_meter_policy_update(uint16_t port_id,
 	uint32_t mtr_id,
-	enum rte_color *dscp_table,
+	uint32_t meter_policy_id,
 	struct rte_mtr_error *error)
 {
 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
-	return RTE_MTR_FUNC(port_id, meter_dscp_table_update)(dev,
-		mtr_id, dscp_table, error);
+	return RTE_MTR_FUNC(port_id, meter_policy_update)(dev,
+		mtr_id, meter_policy_id, error);
 }
 
-/** MTR object policer action update */
+/** MTR object meter DSCP table update */
 int
-rte_mtr_policer_actions_update(uint16_t port_id,
+rte_mtr_meter_dscp_table_update(uint16_t port_id,
 	uint32_t mtr_id,
-	uint32_t action_mask,
-	enum rte_mtr_policer_action *actions,
+	enum rte_color *dscp_table,
 	struct rte_mtr_error *error)
 {
 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
-	return RTE_MTR_FUNC(port_id, policer_actions_update)(dev,
-		mtr_id, action_mask, actions, error);
+	return RTE_MTR_FUNC(port_id, meter_dscp_table_update)(dev,
+		mtr_id, dscp_table, error);
 }
 
 /** MTR object enabled stats update */
diff --git a/lib/librte_ethdev/rte_mtr.h b/lib/librte_ethdev/rte_mtr.h
index ceb5dcbef1..ca6277e5a5 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" {
@@ -200,20 +201,16 @@ struct rte_mtr_meter_profile {
 };
 
 /**
- * Policer actions
+ * Meter policy
  */
-enum rte_mtr_policer_action {
-	/** Recolor the packet as green. */
-	MTR_POLICER_ACTION_COLOR_GREEN = 0,
-
-	/** Recolor the packet as yellow. */
-	MTR_POLICER_ACTION_COLOR_YELLOW,
-
-	/** Recolor the packet as red. */
-	MTR_POLICER_ACTION_COLOR_RED,
-
-	/** Drop the packet. */
-	MTR_POLICER_ACTION_DROP,
+struct rte_mtr_meter_policy_params {
+	/**
+	 * Policy action list per color.
+	 * actions[i] potentially represents a chain of rte_flow actions
+	 * terminated by the END action, exactly as specified by the rte_flow
+	 * API for the flow definition, and not just a single action.
+	 */
+	const struct rte_flow_action *actions[RTE_COLORS];
 };
 
 /**
@@ -257,13 +254,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;
 };
 
 /**
@@ -349,6 +346,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.
@@ -367,18 +371,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;
-
 	/**
 	 * srTCM rfc2697 byte mode supported.
 	 * When non-zero, it indicates that byte mode is supported for
@@ -447,6 +439,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,
 };
 
 /**
@@ -530,6 +524,144 @@ rte_mtr_meter_profile_delete(uint16_t port_id,
 	uint32_t meter_profile_id,
 	struct rte_mtr_error *error);
 
+/**
+ * Check whether a meter policy can be created on a given port.
+ *
+ * The meter policy is validated for correctness and
+ * whether it could be accepted by the device given sufficient resources.
+ * The policy is checked against the current capability information
+ * meter_policy_n_max configuration.
+ * The policy may also optionally be validated against existing
+ * device policy resources.
+ * This function has no effect on the target device.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] policy
+ *   Associated action list per color.
+ *   list NULL is legal and means no special action.
+ *   (list terminated by the END action).
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+__rte_experimental
+int
+rte_mtr_meter_policy_validate(uint16_t port_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+
+/**
+ * Meter policy add
+ *
+ * Create a new meter policy. The new policy
+ * is used to create single or multiple MTR objects.
+ * The same policy can be used to create 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] policy
+ *   Associated actions per color.
+ *   list NULL is legal and means no special action.
+ *   Non-NULL list must be terminated.
+ *   (list terminated by the END action).
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+__rte_experimental
+int
+rte_mtr_meter_policy_add(uint16_t port_id,
+	uint32_t policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+
+/**
+ * Define meter policy action list:
+ * GREEN - GREEN, YELLOW - YELLOW, RED - RED
+ */
+#define rte_mtr_policy_pass_color(policy) \
+struct rte_mtr_meter_policy_params policy = \
+{ \
+	.actions[RTE_COLOR_GREEN] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
+			.conf = &(struct rte_flow_action_meter_color) { \
+				.color = RTE_COLOR_GREEN, \
+			}, \
+		}, \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+	.actions[RTE_COLOR_YELLOW] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
+			.conf = &(struct rte_flow_action_meter_color) { \
+				.color = RTE_COLOR_YELLOW, \
+			}, \
+		}, \
+		{ \
+		.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+	.actions[RTE_COLOR_RED] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
+			.conf = &(struct rte_flow_action_meter_color) { \
+				.color = RTE_COLOR_RED, \
+			}, \
+		}, \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+}
+
+/**
+ * Define meter policy action list:
+ * GREEN - Do nothing, YELLOW - Do nothing, RED - DROP
+ */
+#define rte_mtr_policy_drop_red(policy) \
+struct rte_mtr_meter_policy_params policy = \
+{ \
+	.actions[RTE_COLOR_GREEN] = NULL, \
+	.actions[RTE_COLOR_YELLOW] = NULL, \
+	.actions[RTE_COLOR_RED] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_DROP, \
+		}, \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+}
+
+/**
+ * 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
  *
@@ -655,18 +787,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
@@ -674,26 +802,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
@@ -701,10 +827,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..62273ed3a9 100644
--- a/lib/librte_ethdev/rte_mtr_driver.h
+++ b/lib/librte_ethdev/rte_mtr_driver.h
@@ -41,6 +41,22 @@ typedef int (*rte_mtr_meter_profile_delete_t)(struct rte_eth_dev *dev,
 	struct rte_mtr_error *error);
 /**< @internal MTR meter profile delete */
 
+typedef int (*rte_mtr_meter_policy_validate_t)(struct rte_eth_dev *dev,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+/**< @internal MTR meter policy validate */
+
+typedef int (*rte_mtr_meter_policy_add_t)(struct rte_eth_dev *dev,
+	uint32_t policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+/**< @internal MTR meter policy add */
+
+typedef int (*rte_mtr_meter_policy_delete_t)(struct rte_eth_dev *dev,
+	uint32_t policy_id,
+	struct rte_mtr_error *error);
+/**< @internal MTR meter policy delete */
+
 typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
 	struct rte_mtr_params *params,
@@ -69,18 +85,17 @@ typedef int (*rte_mtr_meter_profile_update_t)(struct rte_eth_dev *dev,
 	struct rte_mtr_error *error);
 /**< @internal MTR object meter profile update */
 
-typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
+typedef int (*rte_mtr_meter_policy_update_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
-	enum rte_color *dscp_table,
+	uint32_t meter_policy_id,
 	struct rte_mtr_error *error);
-/**< @internal MTR object meter DSCP table update */
+/**< @internal MTR object meter policy update */
 
-typedef int (*rte_mtr_policer_actions_update_t)(struct rte_eth_dev *dev,
+typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
-	uint32_t action_mask,
-	enum rte_mtr_policer_action *actions,
+	enum rte_color *dscp_table,
 	struct rte_mtr_error *error);
-/**< @internal MTR object policer action update*/
+/**< @internal MTR object meter DSCP table update */
 
 typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
@@ -124,14 +139,23 @@ struct rte_mtr_ops {
 	/** MTR object meter DSCP table update */
 	rte_mtr_meter_dscp_table_update_t meter_dscp_table_update;
 
-	/** MTR object policer action update */
-	rte_mtr_policer_actions_update_t policer_actions_update;
-
 	/** MTR object enabled stats update */
 	rte_mtr_stats_update_t stats_update;
 
 	/** MTR object stats read */
 	rte_mtr_stats_read_t stats_read;
+
+	/** MTR meter policy validate */
+	rte_mtr_meter_policy_validate_t meter_policy_validate;
+
+	/** MTR meter policy add */
+	rte_mtr_meter_policy_add_t meter_policy_add;
+
+	/** 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..b3e9b83d95 100644
--- a/lib/librte_ethdev/version.map
+++ b/lib/librte_ethdev/version.map
@@ -138,7 +138,6 @@ EXPERIMENTAL {
 	rte_mtr_meter_profile_add;
 	rte_mtr_meter_profile_delete;
 	rte_mtr_meter_profile_update;
-	rte_mtr_policer_actions_update;
 	rte_mtr_stats_read;
 	rte_mtr_stats_update;
 
@@ -246,6 +245,10 @@ EXPERIMENTAL {
 
 	# added in 21.05
 	rte_eth_representor_info_get;
+	rte_mtr_meter_policy_add;
+	rte_mtr_meter_policy_delete;
+	rte_mtr_meter_policy_update;
+	rte_mtr_meter_policy_validate;
 };
 
 INTERNAL {
-- 
2.27.0


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

* [dpdk-dev] [PATCH v8 2/2] app/testpmd: support policy actions per color
  2021-04-15  9:20 ` [dpdk-dev] [PATCH v8 0/2] Support meter policy API Li Zhang
  2021-04-15  9:20   ` [dpdk-dev] [PATCH v8 1/2] ethdev: add pre-defined " Li Zhang
@ 2021-04-15  9:20   ` Li Zhang
  2021-04-19 16:08   ` [dpdk-dev] [PATCH v9 0/2] Support meter policy API Jiawei Wang
  2 siblings, 0 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-15  9:20 UTC (permalink / raw)
  To: dekelp, orika, viacheslavo, matan, shahafs, cristian.dumitrescu,
	lironh, jerinj, ferruh.yigit, ajit.khaparde, Xiaoyun Li
  Cc: dev, thomas, rasland, roniba, Haifei Luo

From: Haifei Luo <haifeil@nvidia.com>

Add the create/del policy CLIs to support actions per color.
The CLIs are:
Create:  add port meter policy (port_id) (policy_id) g_actions (actions)
y_actions (actions) r_actions (actions)
Delete:  del port meter policy (port_id) (policy_id)

Examples:
testpmd> add port meter policy 0 1 g_actions rss / end y_actions end
r_actions drop / end
testpmd> del port meter policy 0 1

Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
---
 app/test-pmd/cmdline.c                      |  13 ++-
 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                       |  32 ++++++
 app/test-pmd/testpmd.h                      |   2 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  30 ++++-
 7 files changed, 269 insertions(+), 14 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index e244df27dc..35452dba86 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -705,9 +705,8 @@ 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"
-			"(g_action) (y_action) (r_action) (stats_mask) (shared)\n"
-			"(use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
+			"create port meter (port_id) (mtr_id) (profile_id) (policy_id) (meter_enable)\n"
+			"(stats_mask) (shared) (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
 			"(dscp_tbl_entry63)]\n"
 			"    meter create\n\n"
 
@@ -720,6 +719,13 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"del port meter (port_id) (mtr_id)\n"
 			"    meter delete\n\n"
 
+			"add port meter policy (port_id) (policy_id) g_actions (actions)\n"
+			"y_actions (actions) r_actions (actions)\n"
+			"    meter policy add\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"
 
@@ -17072,6 +17078,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 0127d9e7d6..1d69eb9c9d 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,
@@ -293,6 +297,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,
@@ -431,6 +438,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. */
@@ -814,6 +824,9 @@ struct buffer {
 		struct {
 			int destroy;
 		} aged; /**< Aged arguments. */
+		struct {
+			uint32_t policy_id;
+		} policy;/**< Policy arguments. */
 	} args; /**< Command arguments. */
 };
 
@@ -1797,6 +1810,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);
@@ -1835,7 +1851,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 = "",
@@ -1957,6 +1973,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",
@@ -4555,6 +4578,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. */
@@ -4739,6 +4810,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,
@@ -7726,6 +7838,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 aa454af536..eff2473e7b 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)
 {
@@ -705,6 +713,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;
@@ -732,6 +741,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");
@@ -775,7 +787,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) {
@@ -790,7 +802,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);
@@ -805,7 +816,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 = {
@@ -815,10 +825,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,
@@ -948,6 +956,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 40b2b29725..c4fe0d59e1 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
 
@@ -1465,6 +1467,36 @@ 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 *act = actions;
+	const struct rte_flow_action *start;
+	struct rte_mtr_meter_policy_params policy;
+	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)
+			policy.actions[i] = start;
+		else
+			policy.actions[i] = NULL;
+		act++;
+	}
+	ret = rte_mtr_meter_policy_add(port_id,
+			policy_id,
+			&policy, &error);
+	if (ret)
+		print_mtr_err_msg(&error);
+	return ret;
+}
+
 /** 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 36d8535d0c..2a9c24be26 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -838,6 +838,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);
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 824d8bdf27..91db2d6b60 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2767,13 +2767,37 @@ Delete meter profile from the ethernet device::
 
    testpmd> del port meter profile (port_id) (profile_id)
 
+create port policy
+~~~~~~~~~~~~~~~~~~
+
+Create new policy object for the ethernet device::
+
+   testpmd> add port meter policy (port_id) (policy_id) g_actions \
+   {action} y_actions {action} r_actions {action}
+
+where:
+
+* ``policy_id``: policy ID.
+* ``action``: action lists for green/yellow/red colors.
+
+delete port policy
+~~~~~~~~~~~~~~~~~~
+
+Delete policy object for the ethernet device::
+
+   testpmd> del port meter policy (port_id) (policy_id)
+
+where:
+
+* ``policy_id``: policy ID.
+
 create port meter
 ~~~~~~~~~~~~~~~~~
 
 Create new meter object for the ethernet device::
 
    testpmd> create port meter (port_id) (mtr_id) (profile_id) \
-   (meter_enable) (g_action) (y_action) (r_action) (stats_mask) (shared) \
+   (policy_id) (meter_enable) (stats_mask) (shared) \
    (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\
    (dscp_tbl_entry63)]
 
@@ -2781,11 +2805,9 @@ where:
 
 * ``mtr_id``: meter object ID.
 * ``profile_id``: ID for the meter profile.
+* ``policy_id``: ID for the policy.
 * ``meter_enable``: When this parameter has a non-zero value, the meter object
   gets enabled at the time of creation, otherwise remains disabled.
-* ``g_action``: Policer action for the packet with green color.
-* ``y_action``: Policer action for the packet with yellow color.
-* ``r_action``: Policer action for the packet with red color.
 * ``stats_mask``: Mask of statistics counter types to be enabled for the
   meter object.
 * ``shared``:  When this parameter has a non-zero value, the meter object is
-- 
2.27.0


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

* Re: [dpdk-dev] [PATCH v8 1/2] ethdev: add pre-defined meter policy API
  2021-04-15  9:20   ` [dpdk-dev] [PATCH v8 1/2] ethdev: add pre-defined " Li Zhang
@ 2021-04-15 15:13     ` Ori Kam
  2021-04-19 12:34     ` Singh, Jasvinder
  1 sibling, 0 replies; 78+ messages in thread
From: Ori Kam @ 2021-04-15 15:13 UTC (permalink / raw)
  To: Li Zhang, dekelp, Slava Ovsiienko, Matan Azrad, Shahaf Shuler,
	cristian.dumitrescu, lironh, jerinj, ferruh.yigit, ajit.khaparde,
	Wisam Monther, Xiaoyun Li, Jasvinder Singh,
	NBU-Contact-Thomas Monjalon, Andrew Rybchenko, Ray Kinsella,
	Neil Horman
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai, Haifei Luo, Jiawei(Jonny) Wang

Hi Li

> -----Original Message-----
> From: Li Zhang <lizh@nvidia.com>
> Sent: Thursday, April 15, 2021 12:20 PM
> Subject: [PATCH v8 1/2] ethdev: add pre-defined meter policy API
> 
> Currently, the flow meter policy does not support multiple actions
> per color; also the allowed action types per color are very limited.
> In addition, the policy cannot be pre-defined.
> 
> Due to the growing in flow actions offload abilities there is a potential
> for the user to use variety of actions per color differently.
> This new meter policy API comes to allow this potential in the most ethdev
> common way using rte_flow action definition.
> A list of rte_flow actions will be provided by the user per color
> in order to create a meter policy.
> In addition, the API forces to pre-define the policy before
> the meters creation in order to allow sharing of single policy
> with multiple meters efficiently.
> 
> meter_policy_id is added into struct rte_mtr_params.
> So that it can get the policy during the meters creation.
> 
> Allow coloring the packet using a new rte_flow_action_color
> as could be done by the old policy API.
> 
> Add two common policy template as macros in the head file.
> 
> The next API function were added:
> - rte_mtr_meter_policy_add
> - rte_mtr_meter_policy_delete
> - rte_mtr_meter_policy_update
> - rte_mtr_meter_policy_validate
> The next struct was changed:
> - rte_mtr_params
> - rte_mtr_capabilities
> The next API was deleted:
> - rte_mtr_policer_actions_update
> 
> To support this API the following app were changed:
> app/test-flow-perf: clean meter policer
> app/testpmd: clean meter policer
> 
> To support this API the following drivers were changed:
> net/softnic: support meter policy API
> 1. cleans meter rte_mtr_policer_action.
> 2. Support policy API to get color action as policer action did.
>    The color action will be mapped into rte_table_action_policer.
> 
> net/mlx5: clean meter creation management
> Cleans and breaks part of the current meter management
> in order to allow better design with policy API.
> 
> Signed-off-by: Li Zhang <lizh@nvidia.com>
> Signed-off-by: Haifei Luo <haifeil@nvidia.com>
> Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
> Acked-by: Matan Azrad <matan@nvidia.com>
> Acked-by: Ray Kinsella <mdr@ashroe.eu>
> ---

Acked-by: Ori Kam <orika@nvidia.com>
Thanks,
Ori

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

* Re: [dpdk-dev] [PATCH v8 1/2] ethdev: add pre-defined meter policy API
  2021-04-15  9:20   ` [dpdk-dev] [PATCH v8 1/2] ethdev: add pre-defined " Li Zhang
  2021-04-15 15:13     ` Ori Kam
@ 2021-04-19 12:34     ` Singh, Jasvinder
  2021-04-19 16:13       ` Jiawei(Jonny) Wang
  1 sibling, 1 reply; 78+ messages in thread
From: Singh, Jasvinder @ 2021-04-19 12:34 UTC (permalink / raw)
  To: Li Zhang, dekelp, orika, viacheslavo, matan, shahafs, Dumitrescu,
	Cristian, lironh, jerinj, Yigit, Ferruh, ajit.khaparde,
	Wisam Jaddo, Li, Xiaoyun, Thomas Monjalon, Andrew Rybchenko,
	Ray Kinsella, Neil Horman
  Cc: dev, rasland, roniba, Haifei Luo, Jiawei Wang

<Snip>

> +/* MTR meter policy add */
> +static int
> +pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
> +	uint32_t meter_policy_id,
> +	struct rte_mtr_meter_policy_params *policy,
> +	struct rte_mtr_error *error)
> +{
> +	struct pmd_internals *p = dev->data->dev_private;
> +	struct softnic_mtr_meter_policy_list *mpl = &p-
> >mtr.meter_policies;
> +	struct softnic_mtr_meter_policy *mp;
> +	const struct rte_flow_action *act;
> +	const struct rte_flow_action_meter_color *recolor;
> +	uint32_t i;
> +	bool valid_act_found;
> +
> +	if (policy == NULL)
> +		return -rte_mtr_error_set(error,
> +			EINVAL,
> +			RTE_MTR_ERROR_TYPE_METER_POLICY,
> +			NULL,
> +			"Null meter policy invalid");
> +
> +	/* Meter policy must not 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 already exists");
> +
> +	for (i = 0; i < RTE_COLORS; i++) {
> +		if (policy->actions[i] == NULL)
> +			return -rte_mtr_error_set(error,
> +				EINVAL,
> +				RTE_MTR_ERROR_TYPE_METER_POLICY,
> +				NULL,
> +				"Null action list");
> +		for (act = policy->actions[i], valid_act_found = false;
> +			act && act->type != RTE_FLOW_ACTION_TYPE_END;
> +			act++) {

Hi Li,  
No need to check "act" in for loop instruction as it is validated before the for loop.  Also, would be good to skip all the steps inside this loop for the actions like RTE_FLOW_ACTION_TYPE_VOID. After for loop, will be good to check "valid_act_found" is true else return an error for that color action. 

Rest seems good to me  

With above fix for softnic-
Acked-by: Jasvinder Singh <jasvinder.singh@intel.com>




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

* [dpdk-dev] [PATCH v9 0/2] Support meter policy API
  2021-04-15  9:20 ` [dpdk-dev] [PATCH v8 0/2] Support meter policy API Li Zhang
  2021-04-15  9:20   ` [dpdk-dev] [PATCH v8 1/2] ethdev: add pre-defined " Li Zhang
  2021-04-15  9:20   ` [dpdk-dev] [PATCH v8 2/2] app/testpmd: support policy actions per color Li Zhang
@ 2021-04-19 16:08   ` Jiawei Wang
  2021-04-19 16:08     ` [dpdk-dev] [PATCH v9 1/2] ethdev: add pre-defined " Jiawei Wang
                       ` (3 more replies)
  2 siblings, 4 replies; 78+ messages in thread
From: Jiawei Wang @ 2021-04-19 16:08 UTC (permalink / raw)
  To: matan, orika, viacheslavo, shahafs; +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.

Add two common policy template as macros in the header file,

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

Depends-on: series=16351  ("Add ASO meter support in MLX5 PMD ")
https://patchwork.dpdk.org/project/dpdk/list/?series=16351

V2: Delete default policy and change relation doc files.
V3: Fix coding style issues.
V4: Fix comments about Depends-on
V5: Fix comments about rte_mtr_meter_policy_add.
V6: Delete policy example.
V7: Fix comments and place two common policy template as macros.
V8: Fix rebase conflict issues and CI warning
V9: Rebase and Fix the comments for softnic driver.

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                             |  14 +-
 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                              |  32 ++
 app/test-pmd/testpmd.h                             |   2 +
 doc/guides/prog_guide/rte_flow.rst                 |  21 +
 .../prog_guide/traffic_metering_and_policing.rst   |  16 +-
 doc/guides/rel_notes/release_21_05.rst             |  21 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst        |  48 ++-
 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 +-
 drivers/net/softnic/rte_eth_softnic_internals.h    |  18 +-
 drivers/net/softnic/rte_eth_softnic_meter.c        | 297 ++++++++++---
 lib/librte_ethdev/rte_flow.h                       |  22 +
 lib/librte_ethdev/rte_mtr.c                        |  55 ++-
 lib/librte_ethdev/rte_mtr.h                        | 223 +++++++---
 lib/librte_ethdev/rte_mtr_driver.h                 |  44 +-
 lib/librte_ethdev/version.map                      |   5 +-
 25 files changed, 879 insertions(+), 1270 deletions(-)

-- 
1.8.3.1


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

* [dpdk-dev] [PATCH v9 1/2] ethdev: add pre-defined meter policy API
  2021-04-19 16:08   ` [dpdk-dev] [PATCH v9 0/2] Support meter policy API Jiawei Wang
@ 2021-04-19 16:08     ` Jiawei Wang
  2021-04-20 11:18       ` Dumitrescu, Cristian
  2021-04-19 16:08     ` [dpdk-dev] [PATCH v9 2/2] app/testpmd: support policy actions per color Jiawei Wang
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 78+ messages in thread
From: Jiawei Wang @ 2021-04-19 16:08 UTC (permalink / raw)
  To: matan, orika, viacheslavo, shahafs, Wisam Jaddo, Xiaoyun Li,
	Jasvinder Singh, Cristian Dumitrescu, Thomas Monjalon,
	Ferruh Yigit, Andrew Rybchenko, Ray Kinsella, Neil Horman
  Cc: dev, rasland, roniba, Li Zhang, Haifei Luo

From: Li Zhang <lizh@nvidia.com>

Currently, the flow meter policy does not support multiple actions
per color; also the allowed action types per color are very limited.
In addition, the policy cannot be pre-defined.

Due to the growing in flow actions offload abilities there is a potential
for the user to use variety of actions per color differently.
This new meter policy API comes to allow this potential in the most ethdev
common way using rte_flow action definition.
A list of rte_flow actions will be provided by the user per color
in order to create a meter policy.
In addition, the API forces to pre-define the policy before
the meters creation in order to allow sharing of single policy
with multiple meters efficiently.

meter_policy_id is added into struct rte_mtr_params.
So that it can get the policy during the meters creation.

Allow coloring the packet using a new rte_flow_action_color
as could be done by the old policy API.

Add two common policy template as macros in the head file.

The next API function were added:
- rte_mtr_meter_policy_add
- 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. Supports policy API to get color action as policer action did.
   The color action will be mapped into rte_table_action_policer.

net/mlx5: clean meter creation management
Cleans and breaks part of the current meter management
in order to allow better design with policy API.

Signed-off-by: Li Zhang <lizh@nvidia.com>
Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
Acked-by: Ray Kinsella <mdr@ashroe.eu>
Acked-by: Ori Kam <orika@nvidia.com>
Acked-by: Jasvinder Singh <jasvinder.singh@intel.com>
---
 app/test-flow-perf/main.c                          |   7 -
 app/test-pmd/cmdline.c                             |   1 -
 app/test-pmd/cmdline_mtr.c                         | 172 --------
 app/test-pmd/cmdline_mtr.h                         |   1 -
 doc/guides/prog_guide/rte_flow.rst                 |  21 +
 .../prog_guide/traffic_metering_and_policing.rst   |  16 +-
 doc/guides/rel_notes/release_21_05.rst             |  21 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst        |  18 -
 drivers/net/mlx5/mlx5.h                            |  24 +-
 drivers/net/mlx5/mlx5_flow.c                       |  46 --
 drivers/net/mlx5/mlx5_flow.h                       |  18 +-
 drivers/net/mlx5/mlx5_flow_aso.c                   |   8 +-
 drivers/net/mlx5/mlx5_flow_dv.c                    | 461 +--------------------
 drivers/net/mlx5/mlx5_flow_meter.c                 | 369 +----------------
 drivers/net/softnic/rte_eth_softnic_flow.c         |  19 +-
 drivers/net/softnic/rte_eth_softnic_internals.h    |  18 +-
 drivers/net/softnic/rte_eth_softnic_meter.c        | 297 ++++++++++---
 lib/librte_ethdev/rte_flow.h                       |  22 +
 lib/librte_ethdev/rte_mtr.c                        |  55 ++-
 lib/librte_ethdev/rte_mtr.h                        | 223 +++++++---
 lib/librte_ethdev/rte_mtr_driver.h                 |  44 +-
 lib/librte_ethdev/version.map                      |   5 +-
 22 files changed, 610 insertions(+), 1256 deletions(-)

diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c
index 8e22967..9be8edc 100644
--- a/app/test-flow-perf/main.c
+++ b/app/test-flow-perf/main.c
@@ -928,13 +928,6 @@ struct multi_cores_pool {
 
 	/*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 5bf1497..e244df2 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -17074,7 +17074,6 @@ struct cmd_showport_macs_result {
 	(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 4d9bfde..aa454af 100644
--- a/app/test-pmd/cmdline_mtr.c
+++ b/app/test-pmd/cmdline_mtr.c
@@ -147,53 +147,6 @@
 }
 
 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.srtcm_rfc2697_byte_mode_supported %" PRId32 "\n",
 		cap.srtcm_rfc2697_byte_mode_supported);
 	printf("cap.srtcm_rfc2697_packet_mode_supported %" PRId32 "\n",
@@ -842,12 +791,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);
@@ -1215,121 +1158,6 @@ static void cmd_set_port_meter_dscp_table_parsed(void *parsed_result,
 	},
 };
 
-/* *** 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 e69d6da..7e2713c 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_del_port_meter;
 extern cmdline_parse_inst_t cmd_set_port_meter_profile;
 extern cmdline_parse_inst_t cmd_set_port_meter_dscp_table;
-extern cmdline_parse_inst_t cmd_set_port_meter_policer_action;
 extern cmdline_parse_inst_t cmd_set_port_meter_stats_mask;
 extern cmdline_parse_inst_t cmd_show_port_meter_stats;
 
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index e1b93ec..2f5a6e0 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -2841,6 +2841,27 @@ for ``RTE_FLOW_FIELD_VALUE`` and ``RTE_FLOW_FIELD_POINTER`` respectively.
    | ``value``     | immediate value or a pointer to this value               |
    +---------------+----------------------------------------------------------+
 
+Action: ``METER_COLOR``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Color the packet to reflect the meter color result.
+
+The meter action must be configured before meter color action.
+Meter color action is set to a color to reflect the meter color result.
+Set the meter color in the mbuf to the selected color.
+The meter color action output color is the output color of the packet,
+which is set in the packet meta-data (i.e. struct ``rte_mbuf::sched::color``)
+
+.. _table_rte_flow_action_meter_color:
+
+.. table:: METER_COLOR
+
+   +-----------------+--------------+
+   | Field           | Value        |
+   +=================+==============+
+   | ``meter_color`` | Packet color |
+   +-----------------+--------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/doc/guides/prog_guide/traffic_metering_and_policing.rst b/doc/guides/prog_guide/traffic_metering_and_policing.rst
index 90c781e..c0537e6 100644
--- a/doc/guides/prog_guide/traffic_metering_and_policing.rst
+++ b/doc/guides/prog_guide/traffic_metering_and_policing.rst
@@ -56,18 +56,10 @@ The processing done for each input packet hitting an MTR object is:
   color blind mode, which is equivalent to considering all input packets
   initially colored as green.
 
-* Policing: There is a separate policer action configured for each meter
-  output color, which can:
-
-  * Drop the packet.
-
-  * Keep the same packet color: the policer output color matches the meter
-    output color (essentially a no-op action).
-
-  * Recolor the packet: the policer output color is set to a different color
-    than the meter output color. The policer output color is the output color
-    of the packet, which is set in the packet meta-data (i.e. struct
-    ``rte_mbuf::sched::color``).
+* There is a meter policy API to manage pre-defined policies for meter.
+  Any rte_flow action list can be configured per color for each policy.
+  A meter object configured with a policy executes the actions per packet
+  according to the packet color.
 
 * Statistics: The set of counters maintained for each MTR object is
   configurable and subject to the implementation support. This set includes
diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst
index 1c2e093..5e378de 100644
--- a/doc/guides/rel_notes/release_21_05.rst
+++ b/doc/guides/rel_notes/release_21_05.rst
@@ -224,6 +224,27 @@ New Features
   * Added support for crypto adapter forward mode in octeontx2 event and crypto
     device driver.
 
+  * 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_add()``, ``rte_mtr_meter_policy_delete()`` and
+    ``rte_mtr_create_with_policy()``
+  * ethdev: Removed rte_mtr_policer_action from rte_mtr_params structures.
+  * ethdev: Added rte_mtr_meter_policy_params structures to support policy API.
+  * ethdev: Added meter_policy_id into rte_mtr_params structures.
+  * ethdev: Removed policer_action_recolor_supported and policer_action_drop_supported from rte_mtr_capabilities structures.
+  * ethdev: Added meter_policy_n_max into rte_mtr_capabilities structures.
+  * ethdev: Added RTE_FLOW_ACTION_TYPE_METER_COLOR in enum rte_flow_action_type.
+  * ethdev: Added RTE_MTR_ERROR_TYPE_METER_POLICY_ID and RTE_MTR_ERROR_TYPE_METER_POLICY_ID into rte_mtr_error_type.
 
 Removed Items
 -------------
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a736e7d..e3e2c34 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2831,24 +2831,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 55ff17a..c9bc45c 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 d8e0bcb..1379b14 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -6656,52 +6656,6 @@ struct mlx5_meter_domains_infos *
 }
 
 /**
- * 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.
  *
  * @param[in] dev
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index a5b0802..718d37f 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. */
 };
 
@@ -1096,14 +1098,6 @@ typedef int (*mlx5_flow_query_t)(struct rte_eth_dev *dev,
 					    (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,
@@ -1160,8 +1154,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;
@@ -1391,12 +1383,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 cd2cc01..62d2df0 100644
--- a/drivers/net/mlx5/mlx5_flow_aso.c
+++ b/drivers/net/mlx5/mlx5_flow_aso.c
@@ -808,8 +808,8 @@
 		/* Waiting for wqe resource. */
 		rte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
 	} while (--poll_wqe_times);
-	DRV_LOG(ERR, "Fail to send WQE for ASO meter %d",
-			mtr->fm.meter_id);
+	DRV_LOG(ERR, "Fail to send WQE for ASO meter offset %d",
+			mtr->offset);
 	return -1;
 }
 
@@ -844,7 +844,7 @@
 		/* Waiting for CQE ready. */
 		rte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
 	} while (--poll_cqe_times);
-	DRV_LOG(ERR, "Fail to poll CQE ready for ASO meter %d",
-			mtr->fm.meter_id);
+	DRV_LOG(ERR, "Fail to poll CQE ready for ASO meter offset %d",
+			mtr->offset);
 	return -1;
 }
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index b443eb9..d48d5f0 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -185,31 +185,6 @@
 	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. */
@@ -6026,12 +6001,10 @@ struct mlx5_hlist_entry *
 	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;
 }
@@ -6055,7 +6028,6 @@ struct mlx5_hlist_entry *
 	rte_spinlock_lock(&mtrmng->mtrsl);
 	memset(&aso_mtr->fm, 0, sizeof(struct mlx5_flow_meter_info));
 	aso_mtr->state = ASO_METER_FREE;
-	aso_mtr->fm.meter_id = UINT32_MAX;
 	LIST_INSERT_HEAD(&mtrmng->meters, aso_mtr, next);
 	rte_spinlock_unlock(&mtrmng->mtrsl);
 }
@@ -6095,8 +6067,8 @@ struct mlx5_hlist_entry *
 	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
@@ -13719,433 +13691,6 @@ struct mlx5_cache_entry *
 }
 
 /**
- * Destroy the meter table matchers.
- * Lock free, (mutex should be acquired by caller).
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in,out] dtb
- *   Pointer to DV meter table.
- *
- * @return
- *   Always 0.
- */
-static int
-flow_dv_destroy_mtr_matchers(struct rte_eth_dev *dev,
-			     struct mlx5_meter_domain_info *dtb)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_flow_tbl_data_entry *tbl;
-
-	if (!priv->config.dv_flow_en)
-		return 0;
-	if (dtb->drop_matcher) {
-		tbl = container_of(dtb->drop_matcher->tbl, typeof(*tbl), tbl);
-		mlx5_cache_unregister(&tbl->matchers,
-				      &dtb->drop_matcher->entry);
-		dtb->drop_matcher = NULL;
-	}
-	if (dtb->color_matcher) {
-		tbl = container_of(dtb->color_matcher->tbl, typeof(*tbl), tbl);
-		mlx5_cache_unregister(&tbl->matchers,
-				      &dtb->color_matcher->entry);
-		dtb->color_matcher = NULL;
-	}
-	return 0;
-}
-
-/**
- * Create the matchers for meter table.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] color_reg_c_idx
- *   Reg C index for color match.
- * @param[in] mtr_id_reg_c_idx
- *   Reg C index for meter_id match.
- * @param[in] mtr_id_mask
- *   Mask for meter_id match criteria.
- * @param[in,out] dtb
- *   Pointer to DV meter table.
- * @param[out] error
- *   Perform verbose error reporting if not NULL.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-flow_dv_prepare_mtr_matchers(struct rte_eth_dev *dev,
-			     uint32_t color_reg_c_idx,
-			     uint32_t mtr_id_reg_c_idx,
-			     uint32_t mtr_id_mask,
-			     struct mlx5_meter_domain_info *dtb,
-			     struct rte_flow_error *error)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_flow_tbl_data_entry *tbl_data;
-	struct mlx5_cache_entry *entry;
-	struct mlx5_flow_dv_matcher matcher = {
-		.mask = {
-			.size = sizeof(matcher.mask.buf) -
-				MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-		},
-		.tbl = dtb->tbl,
-	};
-	struct mlx5_flow_dv_match_params value = {
-		.size = sizeof(value.buf) -
-			MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-	};
-	struct mlx5_flow_cb_ctx ctx = {
-		.error = error,
-		.data = &matcher,
-	};
-	uint32_t color_mask = (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
-
-	tbl_data = container_of(dtb->tbl, struct mlx5_flow_tbl_data_entry, tbl);
-	if (!dtb->drop_matcher) {
-		/* Create matchers for Drop. */
-		flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-				       mtr_id_reg_c_idx, 0, mtr_id_mask);
-		matcher.priority = MLX5_REG_BITS * 2 - priv->max_mtr_bits;
-		matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
-					matcher.mask.size);
-		entry = mlx5_cache_register(&tbl_data->matchers, &ctx);
-		if (!entry) {
-			DRV_LOG(ERR, "Failed to register meter drop matcher.");
-			return -1;
-		}
-		dtb->drop_matcher =
-			container_of(entry, struct mlx5_flow_dv_matcher, entry);
-	}
-	if (!dtb->color_matcher) {
-		/* Create matchers for Color + meter_id. */
-		if (priv->mtr_reg_share) {
-			flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-					color_reg_c_idx, 0,
-					(mtr_id_mask | color_mask));
-		} else {
-			flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-					color_reg_c_idx, 0, color_mask);
-			flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-					mtr_id_reg_c_idx, 0, mtr_id_mask);
-		}
-		matcher.priority = MLX5_REG_BITS - priv->max_mtr_bits;
-		matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
-					matcher.mask.size);
-		entry = mlx5_cache_register(&tbl_data->matchers, &ctx);
-		if (!entry) {
-			DRV_LOG(ERR, "Failed to register meter color matcher.");
-			return -1;
-		}
-		dtb->color_matcher =
-			container_of(entry, struct mlx5_flow_dv_matcher, entry);
-	}
-	return 0;
-}
-
-/**
- * Destroy domain policer rule.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] dt
- *   Pointer to domain table.
- */
-static void
-flow_dv_destroy_domain_policer_rule(struct rte_eth_dev *dev,
-				    struct mlx5_meter_domain_info *dt)
-{
-	if (dt->drop_rule) {
-		claim_zero(mlx5_flow_os_destroy_flow(dt->drop_rule));
-		dt->drop_rule = NULL;
-	}
-	if (dt->green_rule) {
-		claim_zero(mlx5_flow_os_destroy_flow(dt->green_rule));
-		dt->green_rule = NULL;
-	}
-	flow_dv_destroy_mtr_matchers(dev, dt);
-	if (dt->jump_actn) {
-		claim_zero(mlx5_flow_os_destroy_flow_action(dt->jump_actn));
-		dt->jump_actn = NULL;
-	}
-}
-
-/**
- * Destroy policer rules.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] attr
- *   Pointer to flow attributes.
- *
- * @return
- *   Always 0.
- */
-static int
-flow_dv_destroy_policer_rules(struct rte_eth_dev *dev,
-			      const struct mlx5_flow_meter_info *fm,
-			      const struct rte_flow_attr *attr)
-{
-	struct mlx5_meter_domains_infos *mtb = fm ? fm->mfts : NULL;
-
-	if (!mtb)
-		return 0;
-	if (attr->egress)
-		flow_dv_destroy_domain_policer_rule(dev, &mtb->egress);
-	if (attr->ingress)
-		flow_dv_destroy_domain_policer_rule(dev, &mtb->ingress);
-	if (attr->transfer)
-		flow_dv_destroy_domain_policer_rule(dev, &mtb->transfer);
-	return 0;
-}
-
-/**
- * Create specify domain meter policer rule.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] mtr_idx
- *   meter index.
- * @param[in] mtb
- *   Pointer to DV meter table set.
- * @param[out] drop_rule
- *   The address of pointer saving drop rule.
- * @param[out] color_rule
- *   The address of pointer saving green rule.
- *
- * @return
- *   0 on success, -1 otherwise.
- */
-static int
-flow_dv_create_policer_forward_rule(struct rte_eth_dev *dev,
-				    struct mlx5_flow_meter_info *fm,
-				    uint32_t mtr_idx,
-				    struct mlx5_meter_domain_info *dtb,
-				    void **drop_rule,
-				    void **green_rule)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_flow_dv_match_params matcher = {
-		.size = sizeof(matcher.buf) -
-			MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-	};
-	struct mlx5_flow_dv_match_params value = {
-		.size = sizeof(value.buf) -
-			MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-	};
-	struct mlx5_meter_domains_infos *mtb = fm->mfts;
-	struct rte_flow_error error;
-	uint32_t color_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR,
-						    0, &error);
-	uint32_t mtr_id_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_ID,
-						     0, &error);
-	uint8_t mtr_id_offset = priv->mtr_reg_share ? MLX5_MTR_COLOR_BITS : 0;
-	uint32_t mtr_id_mask =
-		((UINT32_C(1) << priv->max_mtr_bits) - 1) << mtr_id_offset;
-	void *actions[METER_ACTIONS];
-	int i;
-	int ret = 0;
-
-	/* Create jump action. */
-	if (!dtb->jump_actn)
-		ret = mlx5_flow_os_create_flow_action_dest_flow_tbl
-				(dtb->sfx_tbl->obj, &dtb->jump_actn);
-	if (ret) {
-		DRV_LOG(ERR, "Failed to create policer jump action.");
-		goto error;
-	}
-	/* Prepare matchers. */
-	if (!dtb->drop_matcher || !dtb->color_matcher) {
-		ret = flow_dv_prepare_mtr_matchers(dev, color_reg_c,
-						   mtr_id_reg_c, mtr_id_mask,
-						   dtb, &error);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to setup matchers for mtr table.");
-			goto error;
-		}
-	}
-	/* Create Drop flow, matching meter_id only. */
-	i = 0;
-	flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c,
-			       (mtr_idx << mtr_id_offset), UINT32_MAX);
-	if (mtb->drop_count)
-		actions[i++] = mtb->drop_count;
-	actions[i++] = priv->sh->dr_drop_action;
-	ret = mlx5_flow_os_create_flow(dtb->drop_matcher->matcher_object,
-				       (void *)&value, i, actions, drop_rule);
-	if (ret) {
-		DRV_LOG(ERR, "Failed to create meter policer drop rule.");
-		goto error;
-	}
-	/* Create flow matching Green color + meter_id. */
-	i = 0;
-	if (priv->mtr_reg_share) {
-		flow_dv_match_meta_reg(matcher.buf, value.buf, color_reg_c,
-				       ((mtr_idx << mtr_id_offset) |
-					rte_col_2_mlx5_col(RTE_COLOR_GREEN)),
-				       UINT32_MAX);
-	} else {
-		flow_dv_match_meta_reg(matcher.buf, value.buf, color_reg_c,
-				       rte_col_2_mlx5_col(RTE_COLOR_GREEN),
-				       UINT32_MAX);
-		flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c,
-				       mtr_idx, UINT32_MAX);
-	}
-	if (mtb->green_count)
-		actions[i++] = mtb->green_count;
-	actions[i++] = dtb->jump_actn;
-	ret = mlx5_flow_os_create_flow(dtb->color_matcher->matcher_object,
-				       (void *)&value, i, actions, green_rule);
-	if (ret) {
-		DRV_LOG(ERR, "Failed to create meter policer color rule.");
-		goto error;
-	}
-	return 0;
-error:
-	rte_errno = errno;
-	return -1;
-}
-
-/**
- * Prepare policer rules for all domains.
- * If meter already initialized, this will replace all old rules with new ones.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] attr
- *   Pointer to flow attributes.
- *
- * @return
- *   0 on success, -1 otherwise.
- */
-static int
-flow_dv_prepare_policer_rules(struct rte_eth_dev *dev,
-			      struct mlx5_flow_meter_info *fm,
-			      const struct rte_flow_attr *attr)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_meter_domains_infos *mtb = fm->mfts;
-	bool initialized = false;
-	struct mlx5_flow_counter *cnt;
-	void *egress_drop_rule = NULL;
-	void *egress_green_rule = NULL;
-	void *ingress_drop_rule = NULL;
-	void *ingress_green_rule = NULL;
-	void *transfer_drop_rule = NULL;
-	void *transfer_green_rule = NULL;
-	uint32_t mtr_idx;
-	int ret;
-
-	/* Get the statistics counters for green/drop. */
-	if (fm->policer_stats.pass_cnt) {
-		cnt = flow_dv_counter_get_by_idx(dev,
-					fm->policer_stats.pass_cnt,
-					NULL);
-		mtb->green_count = cnt->action;
-	} else {
-		mtb->green_count = NULL;
-	}
-	if (fm->policer_stats.drop_cnt) {
-		cnt = flow_dv_counter_get_by_idx(dev,
-					fm->policer_stats.drop_cnt,
-					NULL);
-		mtb->drop_count = cnt->action;
-	} else {
-		mtb->drop_count = NULL;
-	}
-	/**
-	 * If flow meter has been initialized, all policer rules
-	 * are created. So can get if meter initialized by checking
-	 * any policer rule.
-	 */
-	if (mtb->egress.drop_rule)
-		initialized = true;
-	if (priv->sh->meter_aso_en) {
-		struct mlx5_aso_mtr *aso_mtr = NULL;
-		struct mlx5_aso_mtr_pool *pool;
-
-		aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
-		pool = container_of(aso_mtr, struct mlx5_aso_mtr_pool,
-				    mtrs[aso_mtr->offset]);
-		mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, aso_mtr->offset);
-	} else {
-		struct mlx5_legacy_flow_meter *legacy_fm;
-
-		legacy_fm = container_of(fm, struct mlx5_legacy_flow_meter, fm);
-		mtr_idx = legacy_fm->idx;
-	}
-	if (attr->egress) {
-		ret = flow_dv_create_policer_forward_rule(dev,
-				fm, mtr_idx, &mtb->egress,
-				&egress_drop_rule, &egress_green_rule);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to create egress policer.");
-			goto error;
-		}
-	}
-	if (attr->ingress) {
-		ret = flow_dv_create_policer_forward_rule(dev,
-				fm, mtr_idx, &mtb->ingress,
-				&ingress_drop_rule, &ingress_green_rule);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to create ingress policer.");
-			goto error;
-		}
-	}
-	if (attr->transfer) {
-		ret = flow_dv_create_policer_forward_rule(dev,
-				fm, mtr_idx, &mtb->transfer,
-				&transfer_drop_rule, &transfer_green_rule);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to create transfer policer.");
-			goto error;
-		}
-	}
-	/* Replace old flows if existing. */
-	if (mtb->egress.drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->egress.drop_rule));
-	if (mtb->egress.green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->egress.green_rule));
-	if (mtb->ingress.drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->ingress.drop_rule));
-	if (mtb->ingress.green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->ingress.green_rule));
-	if (mtb->transfer.drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->transfer.drop_rule));
-	if (mtb->transfer.green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->transfer.green_rule));
-	mtb->egress.drop_rule = egress_drop_rule;
-	mtb->egress.green_rule = egress_green_rule;
-	mtb->ingress.drop_rule = ingress_drop_rule;
-	mtb->ingress.green_rule = ingress_green_rule;
-	mtb->transfer.drop_rule = transfer_drop_rule;
-	mtb->transfer.green_rule = transfer_green_rule;
-	return 0;
-error:
-	if (egress_drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(egress_drop_rule));
-	if (egress_green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(egress_green_rule));
-	if (ingress_drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(ingress_drop_rule));
-	if (ingress_green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(ingress_green_rule));
-	if (transfer_drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(transfer_drop_rule));
-	if (transfer_green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(transfer_green_rule));
-	if (!initialized)
-		flow_dv_destroy_policer_rules(dev, fm, attr);
-	return -1;
-}
-
-/**
  * Validate the batch counter support in root table.
  *
  * Create a simple flow with invalid counter and drop action on root table to
@@ -14439,8 +13984,6 @@ struct mlx5_cache_entry *
 	.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 714b382..af0a1c1 100644
--- a/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/drivers/net/mlx5/mlx5_flow_meter.c
@@ -329,7 +329,6 @@
 	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;
@@ -437,90 +436,6 @@
 }
 
 /**
- * Convert wrong color setting action to verbose error.
- *
- * @param[in] action
- *   Policy color action.
- *
- * @return
- *   Verbose meter color error type.
- */
-static inline enum rte_mtr_error_type
-action2error(enum rte_mtr_policer_action action)
-{
-	switch (action) {
-	case MTR_POLICER_ACTION_COLOR_GREEN:
-		return RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN;
-	case MTR_POLICER_ACTION_COLOR_YELLOW:
-		return RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW;
-	case MTR_POLICER_ACTION_COLOR_RED:
-		return RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED;
-	default:
-		break;
-	}
-	return RTE_MTR_ERROR_TYPE_UNSPECIFIED;
-}
-
-/**
- * Check meter validation.
- *
- * @param[in] priv
- *   Pointer to mlx5 private data structure.
- * @param[in] meter_id
- *   Meter id.
- * @param[in] params
- *   Pointer to rte meter parameters.
- * @param[out] error
- *   Pointer to rte meter error structure.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,
-			 struct rte_mtr_params *params,
-			 struct rte_mtr_error *error)
-{
-	/* Meter must use global drop action. */
-	if (!priv->sh->dr_drop_action)
-		return -rte_mtr_error_set(error, ENOTSUP,
-					  RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-					  NULL,
-					  "No drop action ready for meter.");
-	/* Meter params must not be NULL. */
-	if (params == NULL)
-		return -rte_mtr_error_set(error, EINVAL,
-					  RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-					  NULL, "Meter object params null.");
-	/* Previous meter color is not supported. */
-	if (params->use_prev_mtr_color)
-		return -rte_mtr_error_set(error, ENOTSUP,
-					  RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-					  NULL,
-					  "Previous meter color "
-					  "not supported.");
-	/* Validate policer settings. */
-	if (params->action[RTE_COLOR_RED] != MTR_POLICER_ACTION_DROP)
-		return -rte_mtr_error_set
-				(error, ENOTSUP,
-				 action2error(params->action[RTE_COLOR_RED]),
-				 NULL,
-				 "Red color only supports drop action.");
-	if (params->action[RTE_COLOR_GREEN] != MTR_POLICER_ACTION_COLOR_GREEN)
-		return -rte_mtr_error_set
-				(error, ENOTSUP,
-				 action2error(params->action[RTE_COLOR_GREEN]),
-				 NULL,
-				 "Green color only supports recolor green action.");
-	/* Validate meter id. */
-	if (mlx5_flow_meter_find(priv, meter_id, NULL))
-		return -rte_mtr_error_set(error, EEXIST,
-					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
-					  "Meter object already exists.");
-	return 0;
-}
-
-/**
  * Modify the flow meter action.
  *
  * @param[in] priv
@@ -629,167 +544,14 @@
 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 @@
 		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 @@
 {
 	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 @@
 				"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 @@
 {
 	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 @@
 		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 @@
 {
 	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 @@
 		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 @@
 	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 @@ struct mlx5_flow_meter_info *
 		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 @@ struct mlx5_flow_meter_info *
 	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 @@ struct mlx5_flow_meter_info *
 				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 @@ struct mlx5_flow_meter_info *
 	} 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 7925bad..27eaf38 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -1166,6 +1166,7 @@ struct flow_attr_map *
 {
 	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 @@ struct flow_attr_map *
 					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 faf90a5..1b3186e 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 @@ struct 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 @@ struct softnic_table_action_profile *
 	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 b27b128..acb8b87 100644
--- a/drivers/net/softnic/rte_eth_softnic_meter.c
+++ b/drivers/net/softnic/rte_eth_softnic_meter.c
@@ -65,27 +65,6 @@ struct softnic_mtr_meter_profile *
 	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,
@@ -208,6 +187,160 @@ enum rte_table_action_policer
 	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 add */
+static int
+pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
+	uint32_t meter_policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error)
+{
+	struct pmd_internals *p = dev->data->dev_private;
+	struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
+	struct softnic_mtr_meter_policy *mp;
+	const struct rte_flow_action *act;
+	const struct rte_flow_action_meter_color *recolor;
+	uint32_t i;
+	bool valid_act_found;
+
+	if (policy == NULL)
+		return -rte_mtr_error_set(error,
+			EINVAL,
+			RTE_MTR_ERROR_TYPE_METER_POLICY,
+			NULL,
+			"Null meter policy invalid");
+
+	/* Meter policy must not 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 already exists");
+
+	for (i = 0; i < RTE_COLORS; i++) {
+		if (policy->actions[i] == NULL)
+			return -rte_mtr_error_set(error,
+				EINVAL,
+				RTE_MTR_ERROR_TYPE_METER_POLICY,
+				NULL,
+				"Null action list");
+		for (act = policy->actions[i], valid_act_found = false;
+		     act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
+			if (act->type == RTE_FLOW_ACTION_TYPE_VOID)
+				continue;
+			/*
+			 * Support one (and one only) of
+			 * METER_COLOR or DROP action.
+			 */
+			if ((act->type != RTE_FLOW_ACTION_TYPE_METER_COLOR &&
+				act->type != RTE_FLOW_ACTION_TYPE_DROP) ||
+				valid_act_found)
+				return -rte_mtr_error_set(error,
+					EINVAL,
+					RTE_MTR_ERROR_TYPE_METER_POLICY,
+					NULL,
+					"Action invalid");
+			valid_act_found = true;
+		}
+		if (!valid_act_found)
+			return -rte_mtr_error_set(error,
+				EINVAL,
+				RTE_MTR_ERROR_TYPE_METER_POLICY,
+				NULL,
+				"No valid action found");
+	}
+
+	/* Memory allocation */
+	mp = calloc(1, sizeof(struct softnic_mtr_meter_policy));
+	if (mp == NULL)
+		return -rte_mtr_error_set(error,
+			ENOMEM,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			"Memory alloc failed");
+
+	/* Fill in */
+	mp->meter_policy_id = meter_policy_id;
+	for (i = 0; i < RTE_COLORS; i++) {
+		mp->policer[i] = RTE_TABLE_ACTION_POLICER_DROP;
+		act = policy->actions[i];
+		if (!act)
+			continue;
+		if (act->type == RTE_FLOW_ACTION_TYPE_METER_COLOR) {
+			recolor = act->conf;
+			switch (recolor->color) {
+			case RTE_COLOR_GREEN:
+				mp->policer[i] =
+				RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
+				break;
+			case RTE_COLOR_YELLOW:
+				mp->policer[i] =
+				RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
+				break;
+			case RTE_COLOR_RED:
+				mp->policer[i] =
+				RTE_TABLE_ACTION_POLICER_COLOR_RED;
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+	/* Add to list */
+	TAILQ_INSERT_TAIL(mpl, mp, node);
+
+	return 0;
+}
+
+/* MTR meter policy delete */
+static int
+pmd_mtr_meter_policy_delete(struct rte_eth_dev *dev,
+	uint32_t meter_policy_id,
+	struct rte_mtr_error *error)
+{
+	struct pmd_internals *p = dev->data->dev_private;
+	struct softnic_mtr_meter_policy *mp;
+
+	/* Meter policy must exist */
+	mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
+	if (mp == NULL)
+		return -rte_mtr_error_set(error,
+			EINVAL,
+			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+			NULL,
+			"Meter policy id invalid");
+
+	/* Check unused */
+	if (mp->n_users)
+		return -rte_mtr_error_set(error,
+			EBUSY,
+			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+			NULL,
+			"Meter policy in use");
+
+	/* Remove from list */
+	TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
+	free(mp);
+
+	return 0;
+}
+
 struct softnic_mtr *
 softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
 {
@@ -275,6 +408,7 @@ struct softnic_mtr *
 	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;
 
@@ -292,6 +426,16 @@ struct softnic_mtr *
 			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)
@@ -310,6 +454,7 @@ struct softnic_mtr *
 
 	/* Update dependencies */
 	mp->n_users++;
+	policy->n_users++;
 
 	return 0;
 }
@@ -324,6 +469,7 @@ struct softnic_mtr *
 	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);
@@ -351,8 +497,18 @@ struct softnic_mtr *
 			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);
@@ -514,18 +670,18 @@ struct softnic_mtr *
 	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);
@@ -536,28 +692,17 @@ struct softnic_mtr *
 			NULL,
 			"MTR object id not valid");
 
-	/* Valid policer actions */
-	if (actions == NULL)
+	if (m->params.meter_policy_id == meter_policy_id)
+		return 0;
+
+	/* 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) {
@@ -569,9 +714,7 @@ struct softnic_mtr *
 
 		/* 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,
@@ -595,10 +738,20 @@ struct softnic_mtr *
 			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;
 }
@@ -615,28 +768,40 @@ struct softnic_mtr *
 
 /* 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];
 		}
 
@@ -647,16 +812,20 @@ struct softnic_mtr *
 		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];
 		}
 
@@ -722,7 +891,8 @@ struct softnic_mtr *
 		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);
@@ -743,6 +913,9 @@ struct softnic_mtr *
 	.meter_profile_add = pmd_mtr_meter_profile_add,
 	.meter_profile_delete = pmd_mtr_meter_profile_delete,
 
+	.meter_policy_add = pmd_mtr_meter_policy_add,
+	.meter_policy_delete = pmd_mtr_meter_policy_delete,
+
 	.create = pmd_mtr_create,
 	.destroy = pmd_mtr_destroy,
 	.meter_enable = NULL,
@@ -750,7 +923,7 @@ struct softnic_mtr *
 
 	.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 203c4cd..66ae3fd 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -32,6 +32,7 @@
 #include <rte_ecpri.h>
 #include <rte_mbuf.h>
 #include <rte_mbuf_dyn.h>
+#include <rte_meter.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -2267,6 +2268,14 @@ enum rte_flow_action_type {
 	 * See struct rte_flow_action_modify_field.
 	 */
 	RTE_FLOW_ACTION_TYPE_MODIFY_FIELD,
+
+	/**
+	 * Color the packet to reflect the meter color result.
+	 * Set the meter color in the mbuf to the selected color.
+	 *
+	 * See struct rte_flow_action_meter_color.
+	 */
+	RTE_FLOW_ACTION_TYPE_METER_COLOR,
 };
 
 /**
@@ -2860,6 +2869,19 @@ struct rte_flow_action_set_dscp {
 struct rte_flow_shared_action;
 
 /**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
+ * RTE_FLOW_ACTION_TYPE_METER_COLOR
+ *
+ * The meter color should be set in the packet meta-data
+ * (i.e. struct rte_mbuf::sched::color).
+ */
+struct rte_flow_action_meter_color {
+	enum rte_color color; /**< Packet color. */
+};
+
+/**
  * Field IDs for MODIFY_FIELD action.
  */
 enum rte_flow_field_id {
diff --git a/lib/librte_ethdev/rte_mtr.c b/lib/librte_ethdev/rte_mtr.c
index 3073ac0..e49fcf2 100644
--- a/lib/librte_ethdev/rte_mtr.c
+++ b/lib/librte_ethdev/rte_mtr.c
@@ -91,6 +91,40 @@
 		meter_profile_id, error);
 }
 
+/* MTR meter policy validate */
+int
+rte_mtr_meter_policy_validate(uint16_t port_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_policy_validate)(dev,
+		policy, error);
+}
+
+/* MTR meter policy add */
+int
+rte_mtr_meter_policy_add(uint16_t port_id,
+	uint32_t policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_policy_add)(dev,
+		policy_id, policy, error);
+}
+
+/** MTR meter policy delete */
+int
+rte_mtr_meter_policy_delete(uint16_t port_id,
+	uint32_t policy_id,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_policy_delete)(dev,
+		policy_id, error);
+}
+
 /** MTR object create */
 int
 rte_mtr_create(uint16_t port_id,
@@ -149,29 +183,28 @@
 		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 ceb5dcb..dc246dd 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" {
@@ -200,20 +201,16 @@ struct rte_mtr_meter_profile {
 };
 
 /**
- * Policer actions
+ * Meter policy
  */
-enum rte_mtr_policer_action {
-	/** Recolor the packet as green. */
-	MTR_POLICER_ACTION_COLOR_GREEN = 0,
-
-	/** Recolor the packet as yellow. */
-	MTR_POLICER_ACTION_COLOR_YELLOW,
-
-	/** Recolor the packet as red. */
-	MTR_POLICER_ACTION_COLOR_RED,
-
-	/** Drop the packet. */
-	MTR_POLICER_ACTION_DROP,
+struct rte_mtr_meter_policy_params {
+	/**
+	 * Policy action list per color.
+	 * actions[i] potentially represents a chain of rte_flow actions
+	 * terminated by the END action, exactly as specified by the rte_flow
+	 * API for the flow definition, and not just a single action.
+	 */
+	const struct rte_flow_action *actions[RTE_COLORS];
 };
 
 /**
@@ -257,13 +254,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;
 };
 
 /**
@@ -350,6 +347,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.
 	 */
@@ -367,18 +371,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;
-
 	/**
 	 * srTCM rfc2697 byte mode supported.
 	 * When non-zero, it indicates that byte mode is supported for
@@ -447,6 +439,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,
 };
 
 /**
@@ -531,6 +525,144 @@ struct rte_mtr_error {
 	struct rte_mtr_error *error);
 
 /**
+ * Check whether a meter policy can be created on a given port.
+ *
+ * The meter policy is validated for correctness and
+ * whether it could be accepted by the device given sufficient resources.
+ * The policy is checked against the current capability information
+ * meter_policy_n_max configuration.
+ * The policy may also optionally be validated against existing
+ * device policy resources.
+ * This function has no effect on the target device.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] policy
+ *   Associated action list per color.
+ *   list NULL is legal and means no special action.
+ *   (list terminated by the END action).
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+__rte_experimental
+int
+rte_mtr_meter_policy_validate(uint16_t port_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+
+/**
+ * Meter policy add
+ *
+ * Create a new meter policy. The new policy
+ * is used to create single or multiple MTR objects.
+ * The same policy can be used to create 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] policy
+ *   Associated actions per color.
+ *   list NULL is legal and means no special action.
+ *   Non-NULL list must be terminated.
+ *   (list terminated by the END action).
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+__rte_experimental
+int
+rte_mtr_meter_policy_add(uint16_t port_id,
+	uint32_t policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+
+/**
+ * Define meter policy action list:
+ * GREEN - GREEN, YELLOW - YELLOW, RED - RED
+ */
+#define rte_mtr_policy_pass_color(policy) \
+struct rte_mtr_meter_policy_params policy = \
+{ \
+	.actions[RTE_COLOR_GREEN] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
+			.conf = &(struct rte_flow_action_meter_color) { \
+				.color = RTE_COLOR_GREEN, \
+			}, \
+		}, \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+	.actions[RTE_COLOR_YELLOW] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
+			.conf = &(struct rte_flow_action_meter_color) { \
+				.color = RTE_COLOR_YELLOW, \
+			}, \
+		}, \
+		{ \
+		.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+	.actions[RTE_COLOR_RED] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
+			.conf = &(struct rte_flow_action_meter_color) { \
+				.color = RTE_COLOR_RED, \
+			}, \
+		}, \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+}
+
+/**
+ * Define meter policy action list:
+ * GREEN - Do nothing, YELLOW - Do nothing, RED - DROP
+ */
+#define rte_mtr_policy_drop_red(policy) \
+struct rte_mtr_meter_policy_params policy = \
+{ \
+	.actions[RTE_COLOR_GREEN] = NULL, \
+	.actions[RTE_COLOR_YELLOW] = NULL, \
+	.actions[RTE_COLOR_RED] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_DROP, \
+		}, \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+}
+
+/**
+ * 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
  *
  * Create a new MTR object for the current port. This object is run as part of
@@ -655,18 +787,14 @@ struct rte_mtr_error {
 	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
@@ -674,26 +802,24 @@ struct rte_mtr_error {
  */
 __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
@@ -701,10 +827,9 @@ struct rte_mtr_error {
  */
 __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 a0ddc2b..62273ed 100644
--- a/lib/librte_ethdev/rte_mtr_driver.h
+++ b/lib/librte_ethdev/rte_mtr_driver.h
@@ -41,6 +41,22 @@ typedef int (*rte_mtr_meter_profile_delete_t)(struct rte_eth_dev *dev,
 	struct rte_mtr_error *error);
 /**< @internal MTR meter profile delete */
 
+typedef int (*rte_mtr_meter_policy_validate_t)(struct rte_eth_dev *dev,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+/**< @internal MTR meter policy validate */
+
+typedef int (*rte_mtr_meter_policy_add_t)(struct rte_eth_dev *dev,
+	uint32_t policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+/**< @internal MTR meter policy add */
+
+typedef int (*rte_mtr_meter_policy_delete_t)(struct rte_eth_dev *dev,
+	uint32_t policy_id,
+	struct rte_mtr_error *error);
+/**< @internal MTR meter policy delete */
+
 typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
 	struct rte_mtr_params *params,
@@ -69,18 +85,17 @@ typedef int (*rte_mtr_meter_profile_update_t)(struct rte_eth_dev *dev,
 	struct rte_mtr_error *error);
 /**< @internal MTR object meter profile update */
 
-typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
+typedef int (*rte_mtr_meter_policy_update_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
-	enum rte_color *dscp_table,
+	uint32_t meter_policy_id,
 	struct rte_mtr_error *error);
-/**< @internal MTR object meter DSCP table update */
+/**< @internal MTR object meter policy update */
 
-typedef int (*rte_mtr_policer_actions_update_t)(struct rte_eth_dev *dev,
+typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
-	uint32_t action_mask,
-	enum rte_mtr_policer_action *actions,
+	enum rte_color *dscp_table,
 	struct rte_mtr_error *error);
-/**< @internal MTR object policer action update*/
+/**< @internal MTR object meter DSCP table update */
 
 typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
@@ -124,14 +139,23 @@ struct rte_mtr_ops {
 	/** MTR object meter DSCP table update */
 	rte_mtr_meter_dscp_table_update_t meter_dscp_table_update;
 
-	/** MTR object policer action update */
-	rte_mtr_policer_actions_update_t policer_actions_update;
-
 	/** MTR object enabled stats update */
 	rte_mtr_stats_update_t stats_update;
 
 	/** MTR object stats read */
 	rte_mtr_stats_read_t stats_read;
+
+	/** MTR meter policy validate */
+	rte_mtr_meter_policy_validate_t meter_policy_validate;
+
+	/** MTR meter policy add */
+	rte_mtr_meter_policy_add_t meter_policy_add;
+
+	/** 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 93ad388..b3e9b83 100644
--- a/lib/librte_ethdev/version.map
+++ b/lib/librte_ethdev/version.map
@@ -138,7 +138,6 @@ EXPERIMENTAL {
 	rte_mtr_meter_profile_add;
 	rte_mtr_meter_profile_delete;
 	rte_mtr_meter_profile_update;
-	rte_mtr_policer_actions_update;
 	rte_mtr_stats_read;
 	rte_mtr_stats_update;
 
@@ -246,6 +245,10 @@ EXPERIMENTAL {
 
 	# added in 21.05
 	rte_eth_representor_info_get;
+	rte_mtr_meter_policy_add;
+	rte_mtr_meter_policy_delete;
+	rte_mtr_meter_policy_update;
+	rte_mtr_meter_policy_validate;
 };
 
 INTERNAL {
-- 
1.8.3.1


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

* [dpdk-dev] [PATCH v9 2/2] app/testpmd: support policy actions per color
  2021-04-19 16:08   ` [dpdk-dev] [PATCH v9 0/2] Support meter policy API Jiawei Wang
  2021-04-19 16:08     ` [dpdk-dev] [PATCH v9 1/2] ethdev: add pre-defined " Jiawei Wang
@ 2021-04-19 16:08     ` Jiawei Wang
  2021-04-20 11:36     ` [dpdk-dev] [PATCH v9 0/2] Support meter policy API Ferruh Yigit
  2021-04-20 14:04     ` [dpdk-dev] [PATCH v10 " Jiawei Wang
  3 siblings, 0 replies; 78+ messages in thread
From: Jiawei Wang @ 2021-04-19 16:08 UTC (permalink / raw)
  To: matan, orika, viacheslavo, shahafs, Xiaoyun Li
  Cc: dev, thomas, rasland, roniba, Haifei Luo

From: Haifei Luo <haifeil@nvidia.com>

Add the create/del policy CLIs to support actions per color.
The CLIs are:
Create:  add port meter policy (port_id) (policy_id) g_actions (actions)
y_actions (actions) r_actions (actions)
Delete:  del port meter policy (port_id) (policy_id)

Examples:
testpmd> add port meter policy 0 1 g_actions rss / end y_actions end
r_actions drop / end
testpmd> del port meter policy 0 1

Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
---
 app/test-pmd/cmdline.c                      |  13 ++-
 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                       |  32 ++++++++
 app/test-pmd/testpmd.h                      |   2 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  30 ++++++-
 7 files changed, 269 insertions(+), 14 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index e244df2..35452db 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -705,9 +705,8 @@ 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"
-			"(g_action) (y_action) (r_action) (stats_mask) (shared)\n"
-			"(use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
+			"create port meter (port_id) (mtr_id) (profile_id) (policy_id) (meter_enable)\n"
+			"(stats_mask) (shared) (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
 			"(dscp_tbl_entry63)]\n"
 			"    meter create\n\n"
 
@@ -720,6 +719,13 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"del port meter (port_id) (mtr_id)\n"
 			"    meter delete\n\n"
 
+			"add port meter policy (port_id) (policy_id) g_actions (actions)\n"
+			"y_actions (actions) r_actions (actions)\n"
+			"    meter policy add\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"
 
@@ -17072,6 +17078,7 @@ struct cmd_showport_macs_result {
 	(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 0127d9e..1d69eb9 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,
@@ -293,6 +297,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,
@@ -431,6 +438,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. */
@@ -814,6 +824,9 @@ struct buffer {
 		struct {
 			int destroy;
 		} aged; /**< Aged arguments. */
+		struct {
+			uint32_t policy_id;
+		} policy;/**< Policy arguments. */
 	} args; /**< Command arguments. */
 };
 
@@ -1797,6 +1810,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);
@@ -1835,7 +1851,7 @@ static int comp_set_modify_field_id(struct context *, const struct token *,
 	[ZERO] = {
 		.name = "ZERO",
 		.help = "null entry, abused as the entry point",
-		.next = NEXT(NEXT_ENTRY(FLOW)),
+		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
 	},
 	[END] = {
 		.name = "",
@@ -1957,6 +1973,13 @@ static int comp_set_modify_field_id(struct context *, const struct token *,
 		.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",
@@ -4555,6 +4578,54 @@ static int comp_set_modify_field_id(struct context *, const struct token *,
 		.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. */
@@ -4739,6 +4810,47 @@ static int comp_set_modify_field_id(struct context *, const struct 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,
@@ -7726,6 +7838,10 @@ static int comp_set_modify_field_id(struct context *, const struct token *,
 	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 aa454af..eff2473 100644
--- a/app/test-pmd/cmdline_mtr.c
+++ b/app/test-pmd/cmdline_mtr.c
@@ -37,6 +37,8 @@
 		[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 @@
 		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)
 {
@@ -705,6 +713,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;
@@ -732,6 +741,9 @@ struct cmd_create_port_meter_result {
 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");
@@ -775,7 +787,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) {
@@ -790,7 +802,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);
@@ -805,7 +816,6 @@ static void cmd_create_port_meter_parsed(void *parsed_result,
 	.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 = {
@@ -815,10 +825,8 @@ static void cmd_create_port_meter_parsed(void *parsed_result,
 		(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,
@@ -948,6 +956,71 @@ static void cmd_disable_port_meter_parsed(void *parsed_result,
 	},
 };
 
+/* *** 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 7e2713c..2415fc1 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_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 d4b0e85..5e81d24 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,36 @@ void port_flow_tunnel_create(portid_t port_id, const struct tunnel_ops *ops)
 	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 *act = actions;
+	const struct rte_flow_action *start;
+	struct rte_mtr_meter_policy_params policy;
+	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)
+			policy.actions[i] = start;
+		else
+			policy.actions[i] = NULL;
+		act++;
+	}
+	ret = rte_mtr_meter_policy_add(port_id,
+			policy_id,
+			&policy, &error);
+	if (ret)
+		print_mtr_err_msg(&error);
+	return ret;
+}
+
 /** 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 36d8535..2a9c24b 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -838,6 +838,8 @@ struct port_flow_tunnel *
 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);
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index e3e2c34..232468e 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2765,13 +2765,37 @@ Delete meter profile from the ethernet device::
 
    testpmd> del port meter profile (port_id) (profile_id)
 
+create port policy
+~~~~~~~~~~~~~~~~~~
+
+Create new policy object for the ethernet device::
+
+   testpmd> add port meter policy (port_id) (policy_id) g_actions \
+   {action} y_actions {action} r_actions {action}
+
+where:
+
+* ``policy_id``: policy ID.
+* ``action``: action lists for green/yellow/red colors.
+
+delete port policy
+~~~~~~~~~~~~~~~~~~
+
+Delete policy object for the ethernet device::
+
+   testpmd> del port meter policy (port_id) (policy_id)
+
+where:
+
+* ``policy_id``: policy ID.
+
 create port meter
 ~~~~~~~~~~~~~~~~~
 
 Create new meter object for the ethernet device::
 
    testpmd> create port meter (port_id) (mtr_id) (profile_id) \
-   (meter_enable) (g_action) (y_action) (r_action) (stats_mask) (shared) \
+   (policy_id) (meter_enable) (stats_mask) (shared) \
    (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\
    (dscp_tbl_entry63)]
 
@@ -2779,11 +2803,9 @@ where:
 
 * ``mtr_id``: meter object ID.
 * ``profile_id``: ID for the meter profile.
+* ``policy_id``: ID for the policy.
 * ``meter_enable``: When this parameter has a non-zero value, the meter object
   gets enabled at the time of creation, otherwise remains disabled.
-* ``g_action``: Policer action for the packet with green color.
-* ``y_action``: Policer action for the packet with yellow color.
-* ``r_action``: Policer action for the packet with red color.
 * ``stats_mask``: Mask of statistics counter types to be enabled for the
   meter object.
 * ``shared``:  When this parameter has a non-zero value, the meter object is
-- 
1.8.3.1


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

* Re: [dpdk-dev] [PATCH v8 1/2] ethdev: add pre-defined meter policy API
  2021-04-19 12:34     ` Singh, Jasvinder
@ 2021-04-19 16:13       ` Jiawei(Jonny) Wang
  0 siblings, 0 replies; 78+ messages in thread
From: Jiawei(Jonny) Wang @ 2021-04-19 16:13 UTC (permalink / raw)
  To: Singh, Jasvinder, Li Zhang, dekelp, Ori Kam, Slava Ovsiienko,
	Matan Azrad, Shahaf Shuler, Dumitrescu, Cristian, lironh, jerinj,
	Yigit, Ferruh, ajit.khaparde, Wisam Monther, Li, Xiaoyun,
	NBU-Contact-Thomas Monjalon, Andrew Rybchenko, Ray Kinsella,
	Neil Horman
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai, Haifei Luo

Thanks Jasvinder's comments!
Li is on vacation so I help to update the code changes based on your comments, V9 is sent with your ack.

> -----Original Message-----
> From: Singh, Jasvinder <jasvinder.singh@intel.com>
> Sent: Monday, April 19, 2021 8:35 PM
> To: Li Zhang <lizh@nvidia.com>; dekelp@nvidia.com; Ori Kam
> <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; Matan
> Azrad <matan@nvidia.com>; Shahaf Shuler <shahafs@nvidia.com>;
> Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; lironh@marvell.com;
> jerinj@marvell.com; Yigit, Ferruh <ferruh.yigit@intel.com>;
> ajit.khaparde@broadcom.com; Wisam Monther <wisamm@nvidia.com>; Li,
> Xiaoyun <xiaoyun.li@intel.com>; NBU-Contact-Thomas Monjalon
> <thomas@monjalon.net>; 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>; Jiawei(Jonny) Wang
> <jiaweiw@nvidia.com>
> Subject: RE: [PATCH v8 1/2] ethdev: add pre-defined meter policy API
> 
> <Snip>
> 
> > +/* MTR meter policy add */
> > +static int
> > +pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
> > +	uint32_t meter_policy_id,
> > +	struct rte_mtr_meter_policy_params *policy,
> > +	struct rte_mtr_error *error)
> > +{
> > +	struct pmd_internals *p = dev->data->dev_private;
> > +	struct softnic_mtr_meter_policy_list *mpl = &p-
> > >mtr.meter_policies;
> > +	struct softnic_mtr_meter_policy *mp;
> > +	const struct rte_flow_action *act;
> > +	const struct rte_flow_action_meter_color *recolor;
> > +	uint32_t i;
> > +	bool valid_act_found;
> > +
> > +	if (policy == NULL)
> > +		return -rte_mtr_error_set(error,
> > +			EINVAL,
> > +			RTE_MTR_ERROR_TYPE_METER_POLICY,
> > +			NULL,
> > +			"Null meter policy invalid");
> > +
> > +	/* Meter policy must not 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 already exists");
> > +
> > +	for (i = 0; i < RTE_COLORS; i++) {
> > +		if (policy->actions[i] == NULL)
> > +			return -rte_mtr_error_set(error,
> > +				EINVAL,
> > +				RTE_MTR_ERROR_TYPE_METER_POLICY,
> > +				NULL,
> > +				"Null action list");
> > +		for (act = policy->actions[i], valid_act_found = false;
> > +			act && act->type != RTE_FLOW_ACTION_TYPE_END;
> > +			act++) {
> 
> Hi Li,
> No need to check "act" in for loop instruction as it is validated before the for
> loop.  Also, would be good to skip all the steps inside this loop for the actions
> like RTE_FLOW_ACTION_TYPE_VOID. After for loop, will be good to check
> "valid_act_found" is true else return an error for that color action.
> 
> Rest seems good to me
> 
> With above fix for softnic-
> Acked-by: Jasvinder Singh <jasvinder.singh@intel.com>
> 
> 


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

* Re: [dpdk-dev] [PATCH v9 1/2] ethdev: add pre-defined meter policy API
  2021-04-19 16:08     ` [dpdk-dev] [PATCH v9 1/2] ethdev: add pre-defined " Jiawei Wang
@ 2021-04-20 11:18       ` Dumitrescu, Cristian
  2021-04-20 12:55         ` Asaf Penso
  0 siblings, 1 reply; 78+ messages in thread
From: Dumitrescu, Cristian @ 2021-04-20 11:18 UTC (permalink / raw)
  To: Jiawei Wang, matan, orika, viacheslavo, shahafs, Wisam Jaddo, Li,
	Xiaoyun, Singh, Jasvinder, Thomas Monjalon, Yigit, Ferruh,
	Andrew Rybchenko, Ray Kinsella, Neil Horman
  Cc: dev, rasland, roniba, Li Zhang, Haifei Luo



> -----Original Message-----
> From: Jiawei Wang <jiaweiw@nvidia.com>
> Sent: Monday, April 19, 2021 5:08 PM
> To: matan@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
> shahafs@nvidia.com; Wisam Jaddo <wisamm@nvidia.com>; Li, Xiaoyun
> <xiaoyun.li@intel.com>; Singh, Jasvinder <jasvinder.singh@intel.com>;
> Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; Thomas Monjalon
> <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> Rybchenko <andrew.rybchenko@oktetlabs.ru>; Ray Kinsella
> <mdr@ashroe.eu>; Neil Horman <nhorman@tuxdriver.com>
> Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com; Li Zhang
> <lizh@nvidia.com>; Haifei Luo <haifeil@nvidia.com>
> Subject: [PATCH v9 1/2] ethdev: add pre-defined meter policy API
> 
> From: Li Zhang <lizh@nvidia.com>
> 
> Currently, the flow meter policy does not support multiple actions
> per color; also the allowed action types per color are very limited.
> In addition, the policy cannot be pre-defined.
> 
> Due to the growing in flow actions offload abilities there is a potential
> for the user to use variety of actions per color differently.
> This new meter policy API comes to allow this potential in the most ethdev
> common way using rte_flow action definition.
> A list of rte_flow actions will be provided by the user per color
> in order to create a meter policy.
> In addition, the API forces to pre-define the policy before
> the meters creation in order to allow sharing of single policy
> with multiple meters efficiently.
> 
> meter_policy_id is added into struct rte_mtr_params.
> So that it can get the policy during the meters creation.
> 
> Allow coloring the packet using a new rte_flow_action_color
> as could be done by the old policy API.
> 
> Add two common policy template as macros in the head file.
> 
> The next API function were added:
> - rte_mtr_meter_policy_add
> - 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. Supports policy API to get color action as policer action did.
>    The color action will be mapped into rte_table_action_policer.
> 
> net/mlx5: clean meter creation management
> Cleans and breaks part of the current meter management
> in order to allow better design with policy API.
> 
> Signed-off-by: Li Zhang <lizh@nvidia.com>
> Signed-off-by: Haifei Luo <haifeil@nvidia.com>
> Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
> Acked-by: Matan Azrad <matan@nvidia.com>
> Acked-by: Ray Kinsella <mdr@ashroe.eu>
> Acked-by: Ori Kam <orika@nvidia.com>
> Acked-by: Jasvinder Singh <jasvinder.singh@intel.com>

Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>


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

* Re: [dpdk-dev] [PATCH v9 0/2] Support meter policy API
  2021-04-19 16:08   ` [dpdk-dev] [PATCH v9 0/2] Support meter policy API Jiawei Wang
  2021-04-19 16:08     ` [dpdk-dev] [PATCH v9 1/2] ethdev: add pre-defined " Jiawei Wang
  2021-04-19 16:08     ` [dpdk-dev] [PATCH v9 2/2] app/testpmd: support policy actions per color Jiawei Wang
@ 2021-04-20 11:36     ` Ferruh Yigit
  2021-04-20 14:08       ` Jiawei(Jonny) Wang
  2021-04-20 14:04     ` [dpdk-dev] [PATCH v10 " Jiawei Wang
  3 siblings, 1 reply; 78+ messages in thread
From: Ferruh Yigit @ 2021-04-20 11:36 UTC (permalink / raw)
  To: Jiawei Wang, matan, orika, viacheslavo, shahafs
  Cc: dev, thomas, rasland, roniba

On 4/19/2021 5:08 PM, Jiawei Wang wrote:
> 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.
> 
> Add two common policy template as macros in the header file,
> 
> RFC ("ethdev: add pre-defined meter policy API")
> https://patchwork.dpdk.org/project/dpdk/patch/20210318085815.804896-1-lizh@nvidia.com/
> 
> Depends-on: series=16351  ("Add ASO meter support in MLX5 PMD ")
> https://patchwork.dpdk.org/project/dpdk/list/?series=16351
> 
> V2: Delete default policy and change relation doc files.
> V3: Fix coding style issues.
> V4: Fix comments about Depends-on
> V5: Fix comments about rte_mtr_meter_policy_add.
> V6: Delete policy example.
> V7: Fix comments and place two common policy template as macros.
> V8: Fix rebase conflict issues and CI warning
> V9: Rebase and Fix the comments for softnic driver.
> 
> Haifei Luo (1):
>    app/testpmd: support policy actions per color
> 
> Li Zhang (1):
>    ethdev: add pre-defined meter policy API
> 

Hi Li, Haifei,

This patch conflicts with merged integrity check/conntrack features, also the 
dependent mlx5 ASO set send a new version.

Can you please send a new version rebasing on latest versions?




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

* Re: [dpdk-dev] [PATCH v9 1/2] ethdev: add pre-defined meter policy API
  2021-04-20 11:18       ` Dumitrescu, Cristian
@ 2021-04-20 12:55         ` Asaf Penso
  2021-04-20 21:01           ` Dumitrescu, Cristian
  0 siblings, 1 reply; 78+ messages in thread
From: Asaf Penso @ 2021-04-20 12:55 UTC (permalink / raw)
  To: Dumitrescu, Cristian, Jiawei(Jonny) Wang, Matan Azrad, Ori Kam,
	Slava Ovsiienko, Shahaf Shuler, Wisam Monther, Li, Xiaoyun,
	Singh, Jasvinder, NBU-Contact-Thomas Monjalon, Yigit, Ferruh,
	Andrew Rybchenko, Ray Kinsella, Neil Horman
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai, Li Zhang, Haifei Luo

Thank you, Cristian, appreciate this extra effort!

Regards,
Asaf Penso

>-----Original Message-----
>From: dev <dev-bounces@dpdk.org> On Behalf Of Dumitrescu, Cristian
>Sent: Tuesday, April 20, 2021 2:18 PM
>To: Jiawei(Jonny) Wang <jiaweiw@nvidia.com>; Matan Azrad
><matan@nvidia.com>; Ori Kam <orika@nvidia.com>; Slava Ovsiienko
><viacheslavo@nvidia.com>; Shahaf Shuler <shahafs@nvidia.com>; Wisam
>Monther <wisamm@nvidia.com>; Li, Xiaoyun <xiaoyun.li@intel.com>; Singh,
>Jasvinder <jasvinder.singh@intel.com>; NBU-Contact-Thomas Monjalon
><thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
>Rybchenko <andrew.rybchenko@oktetlabs.ru>; Ray Kinsella
><mdr@ashroe.eu>; Neil Horman <nhorman@tuxdriver.com>
>Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar Yanai
><roniba@nvidia.com>; Li Zhang <lizh@nvidia.com>; Haifei Luo
><haifeil@nvidia.com>
>Subject: Re: [dpdk-dev] [PATCH v9 1/2] ethdev: add pre-defined meter policy
>API
>
>
>
>> -----Original Message-----
>> From: Jiawei Wang <jiaweiw@nvidia.com>
>> Sent: Monday, April 19, 2021 5:08 PM
>> To: matan@nvidia.com; orika@nvidia.com; viacheslavo@nvidia.com;
>> shahafs@nvidia.com; Wisam Jaddo <wisamm@nvidia.com>; Li, Xiaoyun
>> <xiaoyun.li@intel.com>; Singh, Jasvinder <jasvinder.singh@intel.com>;
>> Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; Thomas Monjalon
>> <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
>> Rybchenko <andrew.rybchenko@oktetlabs.ru>; Ray Kinsella
>> <mdr@ashroe.eu>; Neil Horman <nhorman@tuxdriver.com>
>> Cc: dev@dpdk.org; rasland@nvidia.com; roniba@nvidia.com; Li Zhang
>> <lizh@nvidia.com>; Haifei Luo <haifeil@nvidia.com>
>> Subject: [PATCH v9 1/2] ethdev: add pre-defined meter policy API
>>
>> From: Li Zhang <lizh@nvidia.com>
>>
>> Currently, the flow meter policy does not support multiple actions per
>> color; also the allowed action types per color are very limited.
>> In addition, the policy cannot be pre-defined.
>>
>> Due to the growing in flow actions offload abilities there is a
>> potential for the user to use variety of actions per color differently.
>> This new meter policy API comes to allow this potential in the most
>> ethdev common way using rte_flow action definition.
>> A list of rte_flow actions will be provided by the user per color in
>> order to create a meter policy.
>> In addition, the API forces to pre-define the policy before the meters
>> creation in order to allow sharing of single policy with multiple
>> meters efficiently.
>>
>> meter_policy_id is added into struct rte_mtr_params.
>> So that it can get the policy during the meters creation.
>>
>> Allow coloring the packet using a new rte_flow_action_color as could
>> be done by the old policy API.
>>
>> Add two common policy template as macros in the head file.
>>
>> The next API function were added:
>> - rte_mtr_meter_policy_add
>> - 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. Supports policy API to get color action as policer action did.
>>    The color action will be mapped into rte_table_action_policer.
>>
>> net/mlx5: clean meter creation management Cleans and breaks part of
>> the current meter management in order to allow better design with
>> policy API.
>>
>> Signed-off-by: Li Zhang <lizh@nvidia.com>
>> Signed-off-by: Haifei Luo <haifeil@nvidia.com>
>> Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
>> Acked-by: Matan Azrad <matan@nvidia.com>
>> Acked-by: Ray Kinsella <mdr@ashroe.eu>
>> Acked-by: Ori Kam <orika@nvidia.com>
>> Acked-by: Jasvinder Singh <jasvinder.singh@intel.com>
>
>Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>


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

* [dpdk-dev] [PATCH v10 0/2] Support meter policy API
  2021-04-19 16:08   ` [dpdk-dev] [PATCH v9 0/2] Support meter policy API Jiawei Wang
                       ` (2 preceding siblings ...)
  2021-04-20 11:36     ` [dpdk-dev] [PATCH v9 0/2] Support meter policy API Ferruh Yigit
@ 2021-04-20 14:04     ` Jiawei Wang
  2021-04-20 14:04       ` [dpdk-dev] [PATCH v10 1/2] ethdev: add pre-defined " Jiawei Wang
                         ` (2 more replies)
  3 siblings, 3 replies; 78+ messages in thread
From: Jiawei Wang @ 2021-04-20 14:04 UTC (permalink / raw)
  To: matan, orika, viacheslavo, shahafs, ferruh.yigit
  Cc: dev, thomas, rasland, roniba, asafp

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.

Add two common policy template as macros in the header file,

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

Depends-on: series=16520  ("Add ASO meter support in MLX5 PMD ")
https://patchwork.dpdk.org/project/dpdk/list/?series=16520

v10:
* Rebase.

v9:
* Rebase.
* Fix the comments for softnic driver.

v8:
* Fix rebase conflict issues and CI warning.

v7:
* Fix comments and place two common policy template as macros.

v6:
* Delete policy example.

v5:
* Fix comments about rte_mtr_meter_policy_add.

v4:
* Fix comments about Depends-on.

v3:
* Fix coding style issues.

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                             |  14 +-
 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                              |  32 ++
 app/test-pmd/testpmd.h                             |   2 +
 doc/guides/prog_guide/rte_flow.rst                 |  21 +
 .../prog_guide/traffic_metering_and_policing.rst   |  16 +-
 doc/guides/rel_notes/release_21_05.rst             |  21 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst        |  48 ++-
 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 +-
 drivers/net/softnic/rte_eth_softnic_internals.h    |  18 +-
 drivers/net/softnic/rte_eth_softnic_meter.c        | 297 ++++++++++---
 lib/librte_ethdev/rte_flow.h                       |  22 +
 lib/librte_ethdev/rte_mtr.c                        |  55 ++-
 lib/librte_ethdev/rte_mtr.h                        | 223 +++++++---
 lib/librte_ethdev/rte_mtr_driver.h                 |  44 +-
 lib/librte_ethdev/version.map                      |   5 +-
 25 files changed, 879 insertions(+), 1270 deletions(-)

-- 
1.8.3.1


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

* [dpdk-dev] [PATCH v10 1/2] ethdev: add pre-defined meter policy API
  2021-04-20 14:04     ` [dpdk-dev] [PATCH v10 " Jiawei Wang
@ 2021-04-20 14:04       ` Jiawei Wang
  2021-04-20 17:12         ` Ajit Khaparde
  2021-04-21 19:43         ` Thomas Monjalon
  2021-04-20 14:04       ` [dpdk-dev] [PATCH v10 2/2] app/testpmd: support policy actions per color Jiawei Wang
  2021-04-21 10:23       ` [dpdk-dev] [PATCH v10 0/2] Support meter policy API Ferruh Yigit
  2 siblings, 2 replies; 78+ messages in thread
From: Jiawei Wang @ 2021-04-20 14:04 UTC (permalink / raw)
  To: matan, orika, viacheslavo, shahafs, ferruh.yigit, Wisam Jaddo,
	Xiaoyun Li, Jasvinder Singh, Cristian Dumitrescu,
	Thomas Monjalon, Andrew Rybchenko, Ray Kinsella, Neil Horman
  Cc: dev, rasland, roniba, asafp, Li Zhang, Haifei Luo

From: Li Zhang <lizh@nvidia.com>

Currently, the flow meter policy does not support multiple actions
per color; also the allowed action types per color are very limited.
In addition, the policy cannot be pre-defined.

Due to the growing in flow actions offload abilities there is a potential
for the user to use variety of actions per color differently.
This new meter policy API comes to allow this potential in the most ethdev
common way using rte_flow action definition.
A list of rte_flow actions will be provided by the user per color
in order to create a meter policy.
In addition, the API forces to pre-define the policy before
the meters creation in order to allow sharing of single policy
with multiple meters efficiently.

meter_policy_id is added into struct rte_mtr_params.
So that it can get the policy during the meters creation.

Allow coloring the packet using a new rte_flow_action_color
as could be done by the old policy API.

Add two common policy template as macros in the head file.

The next API function were added:
- rte_mtr_meter_policy_add
- 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. Supports policy API to get color action as policer action did.
   The color action will be mapped into rte_table_action_policer.

net/mlx5: clean meter creation management
Cleans and breaks part of the current meter management
in order to allow better design with policy API.

Signed-off-by: Li Zhang <lizh@nvidia.com>
Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
Acked-by: Ray Kinsella <mdr@ashroe.eu>
Acked-by: Ori Kam <orika@nvidia.com>
Acked-by: Jasvinder Singh <jasvinder.singh@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 app/test-flow-perf/main.c                          |   7 -
 app/test-pmd/cmdline.c                             |   1 -
 app/test-pmd/cmdline_mtr.c                         | 172 --------
 app/test-pmd/cmdline_mtr.h                         |   1 -
 doc/guides/prog_guide/rte_flow.rst                 |  21 +
 .../prog_guide/traffic_metering_and_policing.rst   |  16 +-
 doc/guides/rel_notes/release_21_05.rst             |  21 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst        |  18 -
 drivers/net/mlx5/mlx5.h                            |  24 +-
 drivers/net/mlx5/mlx5_flow.c                       |  46 --
 drivers/net/mlx5/mlx5_flow.h                       |  18 +-
 drivers/net/mlx5/mlx5_flow_aso.c                   |   8 +-
 drivers/net/mlx5/mlx5_flow_dv.c                    | 461 +--------------------
 drivers/net/mlx5/mlx5_flow_meter.c                 | 369 +----------------
 drivers/net/softnic/rte_eth_softnic_flow.c         |  19 +-
 drivers/net/softnic/rte_eth_softnic_internals.h    |  18 +-
 drivers/net/softnic/rte_eth_softnic_meter.c        | 297 ++++++++++---
 lib/librte_ethdev/rte_flow.h                       |  22 +
 lib/librte_ethdev/rte_mtr.c                        |  55 ++-
 lib/librte_ethdev/rte_mtr.h                        | 223 +++++++---
 lib/librte_ethdev/rte_mtr_driver.h                 |  44 +-
 lib/librte_ethdev/version.map                      |   5 +-
 22 files changed, 610 insertions(+), 1256 deletions(-)

diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c
index 8e22967..9be8edc 100644
--- a/app/test-flow-perf/main.c
+++ b/app/test-flow-perf/main.c
@@ -928,13 +928,6 @@ struct multi_cores_pool {
 
 	/*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 ccaeefa..fd2834e 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -17510,7 +17510,6 @@ struct cmd_showport_macs_result {
 	(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 4d9bfde..aa454af 100644
--- a/app/test-pmd/cmdline_mtr.c
+++ b/app/test-pmd/cmdline_mtr.c
@@ -147,53 +147,6 @@
 }
 
 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.srtcm_rfc2697_byte_mode_supported %" PRId32 "\n",
 		cap.srtcm_rfc2697_byte_mode_supported);
 	printf("cap.srtcm_rfc2697_packet_mode_supported %" PRId32 "\n",
@@ -842,12 +791,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);
@@ -1215,121 +1158,6 @@ static void cmd_set_port_meter_dscp_table_parsed(void *parsed_result,
 	},
 };
 
-/* *** 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 e69d6da..7e2713c 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_del_port_meter;
 extern cmdline_parse_inst_t cmd_set_port_meter_profile;
 extern cmdline_parse_inst_t cmd_set_port_meter_dscp_table;
-extern cmdline_parse_inst_t cmd_set_port_meter_policer_action;
 extern cmdline_parse_inst_t cmd_set_port_meter_stats_mask;
 extern cmdline_parse_inst_t cmd_show_port_meter_stats;
 
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 1a70dde..1bacbdc 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -2982,6 +2982,27 @@ The current conntrack context information could be queried via the
    | ``reserved``   | reserved bits                                   |
    +----------------+-------------------------------------------------+
 
+Action: ``METER_COLOR``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Color the packet to reflect the meter color result.
+
+The meter action must be configured before meter color action.
+Meter color action is set to a color to reflect the meter color result.
+Set the meter color in the mbuf to the selected color.
+The meter color action output color is the output color of the packet,
+which is set in the packet meta-data (i.e. struct ``rte_mbuf::sched::color``)
+
+.. _table_rte_flow_action_meter_color:
+
+.. table:: METER_COLOR
+
+   +-----------------+--------------+
+   | Field           | Value        |
+   +=================+==============+
+   | ``meter_color`` | Packet color |
+   +-----------------+--------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/doc/guides/prog_guide/traffic_metering_and_policing.rst b/doc/guides/prog_guide/traffic_metering_and_policing.rst
index 90c781e..c0537e6 100644
--- a/doc/guides/prog_guide/traffic_metering_and_policing.rst
+++ b/doc/guides/prog_guide/traffic_metering_and_policing.rst
@@ -56,18 +56,10 @@ The processing done for each input packet hitting an MTR object is:
   color blind mode, which is equivalent to considering all input packets
   initially colored as green.
 
-* Policing: There is a separate policer action configured for each meter
-  output color, which can:
-
-  * Drop the packet.
-
-  * Keep the same packet color: the policer output color matches the meter
-    output color (essentially a no-op action).
-
-  * Recolor the packet: the policer output color is set to a different color
-    than the meter output color. The policer output color is the output color
-    of the packet, which is set in the packet meta-data (i.e. struct
-    ``rte_mbuf::sched::color``).
+* There is a meter policy API to manage pre-defined policies for meter.
+  Any rte_flow action list can be configured per color for each policy.
+  A meter object configured with a policy executes the actions per packet
+  according to the packet color.
 
 * Statistics: The set of counters maintained for each MTR object is
   configurable and subject to the implementation support. This set includes
diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst
index 0c98f51..42b9e15 100644
--- a/doc/guides/rel_notes/release_21_05.rst
+++ b/doc/guides/rel_notes/release_21_05.rst
@@ -244,6 +244,27 @@ New Features
   * Added support for crypto adapter forward mode in octeontx2 event and crypto
     device driver.
 
+  * 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_add()``, ``rte_mtr_meter_policy_delete()`` and
+    ``rte_mtr_create_with_policy()``
+  * ethdev: Removed rte_mtr_policer_action from rte_mtr_params structures.
+  * ethdev: Added rte_mtr_meter_policy_params structures to support policy API.
+  * ethdev: Added meter_policy_id into rte_mtr_params structures.
+  * ethdev: Removed policer_action_recolor_supported and policer_action_drop_supported from rte_mtr_capabilities structures.
+  * ethdev: Added meter_policy_n_max into rte_mtr_capabilities structures.
+  * ethdev: Added RTE_FLOW_ACTION_TYPE_METER_COLOR in enum rte_flow_action_type.
+  * ethdev: Added RTE_MTR_ERROR_TYPE_METER_POLICY_ID and RTE_MTR_ERROR_TYPE_METER_POLICY_ID into rte_mtr_error_type.
 
 Removed Items
 -------------
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 5dd98c2..d9d6841 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2838,24 +2838,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 55ff17a..c9bc45c 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 bed8f31..05d86b5 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -6656,52 +6656,6 @@ struct mlx5_meter_domains_infos *
 }
 
 /**
- * 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.
  *
  * @param[in] dev
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 1a74b17..5c80dc8 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. */
 };
 
@@ -1096,14 +1098,6 @@ typedef int (*mlx5_flow_query_t)(struct rte_eth_dev *dev,
 					    (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,
@@ -1160,8 +1154,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;
@@ -1391,12 +1383,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 cd2cc01..62d2df0 100644
--- a/drivers/net/mlx5/mlx5_flow_aso.c
+++ b/drivers/net/mlx5/mlx5_flow_aso.c
@@ -808,8 +808,8 @@
 		/* Waiting for wqe resource. */
 		rte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
 	} while (--poll_wqe_times);
-	DRV_LOG(ERR, "Fail to send WQE for ASO meter %d",
-			mtr->fm.meter_id);
+	DRV_LOG(ERR, "Fail to send WQE for ASO meter offset %d",
+			mtr->offset);
 	return -1;
 }
 
@@ -844,7 +844,7 @@
 		/* Waiting for CQE ready. */
 		rte_delay_us_sleep(MLX5_ASO_WQE_CQE_RESPONSE_DELAY);
 	} while (--poll_cqe_times);
-	DRV_LOG(ERR, "Fail to poll CQE ready for ASO meter %d",
-			mtr->fm.meter_id);
+	DRV_LOG(ERR, "Fail to poll CQE ready for ASO meter offset %d",
+			mtr->offset);
 	return -1;
 }
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index ffd9f63..4fdcfce 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -185,31 +185,6 @@
 	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. */
@@ -6026,12 +6001,10 @@ struct mlx5_hlist_entry *
 	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;
 }
@@ -6055,7 +6028,6 @@ struct mlx5_hlist_entry *
 	rte_spinlock_lock(&mtrmng->mtrsl);
 	memset(&aso_mtr->fm, 0, sizeof(struct mlx5_flow_meter_info));
 	aso_mtr->state = ASO_METER_FREE;
-	aso_mtr->fm.meter_id = UINT32_MAX;
 	LIST_INSERT_HEAD(&mtrmng->meters, aso_mtr, next);
 	rte_spinlock_unlock(&mtrmng->mtrsl);
 }
@@ -6095,8 +6067,8 @@ struct mlx5_hlist_entry *
 	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
@@ -13722,433 +13694,6 @@ struct mlx5_cache_entry *
 }
 
 /**
- * Destroy the meter table matchers.
- * Lock free, (mutex should be acquired by caller).
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in,out] dtb
- *   Pointer to DV meter table.
- *
- * @return
- *   Always 0.
- */
-static int
-flow_dv_destroy_mtr_matchers(struct rte_eth_dev *dev,
-			     struct mlx5_meter_domain_info *dtb)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_flow_tbl_data_entry *tbl;
-
-	if (!priv->config.dv_flow_en)
-		return 0;
-	if (dtb->drop_matcher) {
-		tbl = container_of(dtb->drop_matcher->tbl, typeof(*tbl), tbl);
-		mlx5_cache_unregister(&tbl->matchers,
-				      &dtb->drop_matcher->entry);
-		dtb->drop_matcher = NULL;
-	}
-	if (dtb->color_matcher) {
-		tbl = container_of(dtb->color_matcher->tbl, typeof(*tbl), tbl);
-		mlx5_cache_unregister(&tbl->matchers,
-				      &dtb->color_matcher->entry);
-		dtb->color_matcher = NULL;
-	}
-	return 0;
-}
-
-/**
- * Create the matchers for meter table.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] color_reg_c_idx
- *   Reg C index for color match.
- * @param[in] mtr_id_reg_c_idx
- *   Reg C index for meter_id match.
- * @param[in] mtr_id_mask
- *   Mask for meter_id match criteria.
- * @param[in,out] dtb
- *   Pointer to DV meter table.
- * @param[out] error
- *   Perform verbose error reporting if not NULL.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-flow_dv_prepare_mtr_matchers(struct rte_eth_dev *dev,
-			     uint32_t color_reg_c_idx,
-			     uint32_t mtr_id_reg_c_idx,
-			     uint32_t mtr_id_mask,
-			     struct mlx5_meter_domain_info *dtb,
-			     struct rte_flow_error *error)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_flow_tbl_data_entry *tbl_data;
-	struct mlx5_cache_entry *entry;
-	struct mlx5_flow_dv_matcher matcher = {
-		.mask = {
-			.size = sizeof(matcher.mask.buf) -
-				MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-		},
-		.tbl = dtb->tbl,
-	};
-	struct mlx5_flow_dv_match_params value = {
-		.size = sizeof(value.buf) -
-			MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-	};
-	struct mlx5_flow_cb_ctx ctx = {
-		.error = error,
-		.data = &matcher,
-	};
-	uint32_t color_mask = (UINT32_C(1) << MLX5_MTR_COLOR_BITS) - 1;
-
-	tbl_data = container_of(dtb->tbl, struct mlx5_flow_tbl_data_entry, tbl);
-	if (!dtb->drop_matcher) {
-		/* Create matchers for Drop. */
-		flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-				       mtr_id_reg_c_idx, 0, mtr_id_mask);
-		matcher.priority = MLX5_REG_BITS * 2 - priv->max_mtr_bits;
-		matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
-					matcher.mask.size);
-		entry = mlx5_cache_register(&tbl_data->matchers, &ctx);
-		if (!entry) {
-			DRV_LOG(ERR, "Failed to register meter drop matcher.");
-			return -1;
-		}
-		dtb->drop_matcher =
-			container_of(entry, struct mlx5_flow_dv_matcher, entry);
-	}
-	if (!dtb->color_matcher) {
-		/* Create matchers for Color + meter_id. */
-		if (priv->mtr_reg_share) {
-			flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-					color_reg_c_idx, 0,
-					(mtr_id_mask | color_mask));
-		} else {
-			flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-					color_reg_c_idx, 0, color_mask);
-			flow_dv_match_meta_reg(matcher.mask.buf, value.buf,
-					mtr_id_reg_c_idx, 0, mtr_id_mask);
-		}
-		matcher.priority = MLX5_REG_BITS - priv->max_mtr_bits;
-		matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
-					matcher.mask.size);
-		entry = mlx5_cache_register(&tbl_data->matchers, &ctx);
-		if (!entry) {
-			DRV_LOG(ERR, "Failed to register meter color matcher.");
-			return -1;
-		}
-		dtb->color_matcher =
-			container_of(entry, struct mlx5_flow_dv_matcher, entry);
-	}
-	return 0;
-}
-
-/**
- * Destroy domain policer rule.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] dt
- *   Pointer to domain table.
- */
-static void
-flow_dv_destroy_domain_policer_rule(struct rte_eth_dev *dev,
-				    struct mlx5_meter_domain_info *dt)
-{
-	if (dt->drop_rule) {
-		claim_zero(mlx5_flow_os_destroy_flow(dt->drop_rule));
-		dt->drop_rule = NULL;
-	}
-	if (dt->green_rule) {
-		claim_zero(mlx5_flow_os_destroy_flow(dt->green_rule));
-		dt->green_rule = NULL;
-	}
-	flow_dv_destroy_mtr_matchers(dev, dt);
-	if (dt->jump_actn) {
-		claim_zero(mlx5_flow_os_destroy_flow_action(dt->jump_actn));
-		dt->jump_actn = NULL;
-	}
-}
-
-/**
- * Destroy policer rules.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] attr
- *   Pointer to flow attributes.
- *
- * @return
- *   Always 0.
- */
-static int
-flow_dv_destroy_policer_rules(struct rte_eth_dev *dev,
-			      const struct mlx5_flow_meter_info *fm,
-			      const struct rte_flow_attr *attr)
-{
-	struct mlx5_meter_domains_infos *mtb = fm ? fm->mfts : NULL;
-
-	if (!mtb)
-		return 0;
-	if (attr->egress)
-		flow_dv_destroy_domain_policer_rule(dev, &mtb->egress);
-	if (attr->ingress)
-		flow_dv_destroy_domain_policer_rule(dev, &mtb->ingress);
-	if (attr->transfer)
-		flow_dv_destroy_domain_policer_rule(dev, &mtb->transfer);
-	return 0;
-}
-
-/**
- * Create specify domain meter policer rule.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] mtr_idx
- *   meter index.
- * @param[in] mtb
- *   Pointer to DV meter table set.
- * @param[out] drop_rule
- *   The address of pointer saving drop rule.
- * @param[out] color_rule
- *   The address of pointer saving green rule.
- *
- * @return
- *   0 on success, -1 otherwise.
- */
-static int
-flow_dv_create_policer_forward_rule(struct rte_eth_dev *dev,
-				    struct mlx5_flow_meter_info *fm,
-				    uint32_t mtr_idx,
-				    struct mlx5_meter_domain_info *dtb,
-				    void **drop_rule,
-				    void **green_rule)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_flow_dv_match_params matcher = {
-		.size = sizeof(matcher.buf) -
-			MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-	};
-	struct mlx5_flow_dv_match_params value = {
-		.size = sizeof(value.buf) -
-			MLX5_ST_SZ_BYTES(fte_match_set_misc4),
-	};
-	struct mlx5_meter_domains_infos *mtb = fm->mfts;
-	struct rte_flow_error error;
-	uint32_t color_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR,
-						    0, &error);
-	uint32_t mtr_id_reg_c = mlx5_flow_get_reg_id(dev, MLX5_MTR_ID,
-						     0, &error);
-	uint8_t mtr_id_offset = priv->mtr_reg_share ? MLX5_MTR_COLOR_BITS : 0;
-	uint32_t mtr_id_mask =
-		((UINT32_C(1) << priv->max_mtr_bits) - 1) << mtr_id_offset;
-	void *actions[METER_ACTIONS];
-	int i;
-	int ret = 0;
-
-	/* Create jump action. */
-	if (!dtb->jump_actn)
-		ret = mlx5_flow_os_create_flow_action_dest_flow_tbl
-				(dtb->sfx_tbl->obj, &dtb->jump_actn);
-	if (ret) {
-		DRV_LOG(ERR, "Failed to create policer jump action.");
-		goto error;
-	}
-	/* Prepare matchers. */
-	if (!dtb->drop_matcher || !dtb->color_matcher) {
-		ret = flow_dv_prepare_mtr_matchers(dev, color_reg_c,
-						   mtr_id_reg_c, mtr_id_mask,
-						   dtb, &error);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to setup matchers for mtr table.");
-			goto error;
-		}
-	}
-	/* Create Drop flow, matching meter_id only. */
-	i = 0;
-	flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c,
-			       (mtr_idx << mtr_id_offset), UINT32_MAX);
-	if (mtb->drop_count)
-		actions[i++] = mtb->drop_count;
-	actions[i++] = priv->sh->dr_drop_action;
-	ret = mlx5_flow_os_create_flow(dtb->drop_matcher->matcher_object,
-				       (void *)&value, i, actions, drop_rule);
-	if (ret) {
-		DRV_LOG(ERR, "Failed to create meter policer drop rule.");
-		goto error;
-	}
-	/* Create flow matching Green color + meter_id. */
-	i = 0;
-	if (priv->mtr_reg_share) {
-		flow_dv_match_meta_reg(matcher.buf, value.buf, color_reg_c,
-				       ((mtr_idx << mtr_id_offset) |
-					rte_col_2_mlx5_col(RTE_COLOR_GREEN)),
-				       UINT32_MAX);
-	} else {
-		flow_dv_match_meta_reg(matcher.buf, value.buf, color_reg_c,
-				       rte_col_2_mlx5_col(RTE_COLOR_GREEN),
-				       UINT32_MAX);
-		flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_id_reg_c,
-				       mtr_idx, UINT32_MAX);
-	}
-	if (mtb->green_count)
-		actions[i++] = mtb->green_count;
-	actions[i++] = dtb->jump_actn;
-	ret = mlx5_flow_os_create_flow(dtb->color_matcher->matcher_object,
-				       (void *)&value, i, actions, green_rule);
-	if (ret) {
-		DRV_LOG(ERR, "Failed to create meter policer color rule.");
-		goto error;
-	}
-	return 0;
-error:
-	rte_errno = errno;
-	return -1;
-}
-
-/**
- * Prepare policer rules for all domains.
- * If meter already initialized, this will replace all old rules with new ones.
- *
- * @param[in] dev
- *   Pointer to Ethernet device.
- * @param[in] fm
- *   Pointer to flow meter structure.
- * @param[in] attr
- *   Pointer to flow attributes.
- *
- * @return
- *   0 on success, -1 otherwise.
- */
-static int
-flow_dv_prepare_policer_rules(struct rte_eth_dev *dev,
-			      struct mlx5_flow_meter_info *fm,
-			      const struct rte_flow_attr *attr)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_meter_domains_infos *mtb = fm->mfts;
-	bool initialized = false;
-	struct mlx5_flow_counter *cnt;
-	void *egress_drop_rule = NULL;
-	void *egress_green_rule = NULL;
-	void *ingress_drop_rule = NULL;
-	void *ingress_green_rule = NULL;
-	void *transfer_drop_rule = NULL;
-	void *transfer_green_rule = NULL;
-	uint32_t mtr_idx;
-	int ret;
-
-	/* Get the statistics counters for green/drop. */
-	if (fm->policer_stats.pass_cnt) {
-		cnt = flow_dv_counter_get_by_idx(dev,
-					fm->policer_stats.pass_cnt,
-					NULL);
-		mtb->green_count = cnt->action;
-	} else {
-		mtb->green_count = NULL;
-	}
-	if (fm->policer_stats.drop_cnt) {
-		cnt = flow_dv_counter_get_by_idx(dev,
-					fm->policer_stats.drop_cnt,
-					NULL);
-		mtb->drop_count = cnt->action;
-	} else {
-		mtb->drop_count = NULL;
-	}
-	/**
-	 * If flow meter has been initialized, all policer rules
-	 * are created. So can get if meter initialized by checking
-	 * any policer rule.
-	 */
-	if (mtb->egress.drop_rule)
-		initialized = true;
-	if (priv->sh->meter_aso_en) {
-		struct mlx5_aso_mtr *aso_mtr = NULL;
-		struct mlx5_aso_mtr_pool *pool;
-
-		aso_mtr = container_of(fm, struct mlx5_aso_mtr, fm);
-		pool = container_of(aso_mtr, struct mlx5_aso_mtr_pool,
-				    mtrs[aso_mtr->offset]);
-		mtr_idx = MLX5_MAKE_MTR_IDX(pool->index, aso_mtr->offset);
-	} else {
-		struct mlx5_legacy_flow_meter *legacy_fm;
-
-		legacy_fm = container_of(fm, struct mlx5_legacy_flow_meter, fm);
-		mtr_idx = legacy_fm->idx;
-	}
-	if (attr->egress) {
-		ret = flow_dv_create_policer_forward_rule(dev,
-				fm, mtr_idx, &mtb->egress,
-				&egress_drop_rule, &egress_green_rule);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to create egress policer.");
-			goto error;
-		}
-	}
-	if (attr->ingress) {
-		ret = flow_dv_create_policer_forward_rule(dev,
-				fm, mtr_idx, &mtb->ingress,
-				&ingress_drop_rule, &ingress_green_rule);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to create ingress policer.");
-			goto error;
-		}
-	}
-	if (attr->transfer) {
-		ret = flow_dv_create_policer_forward_rule(dev,
-				fm, mtr_idx, &mtb->transfer,
-				&transfer_drop_rule, &transfer_green_rule);
-		if (ret) {
-			DRV_LOG(ERR, "Failed to create transfer policer.");
-			goto error;
-		}
-	}
-	/* Replace old flows if existing. */
-	if (mtb->egress.drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->egress.drop_rule));
-	if (mtb->egress.green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->egress.green_rule));
-	if (mtb->ingress.drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->ingress.drop_rule));
-	if (mtb->ingress.green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->ingress.green_rule));
-	if (mtb->transfer.drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->transfer.drop_rule));
-	if (mtb->transfer.green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(mtb->transfer.green_rule));
-	mtb->egress.drop_rule = egress_drop_rule;
-	mtb->egress.green_rule = egress_green_rule;
-	mtb->ingress.drop_rule = ingress_drop_rule;
-	mtb->ingress.green_rule = ingress_green_rule;
-	mtb->transfer.drop_rule = transfer_drop_rule;
-	mtb->transfer.green_rule = transfer_green_rule;
-	return 0;
-error:
-	if (egress_drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(egress_drop_rule));
-	if (egress_green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(egress_green_rule));
-	if (ingress_drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(ingress_drop_rule));
-	if (ingress_green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(ingress_green_rule));
-	if (transfer_drop_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(transfer_drop_rule));
-	if (transfer_green_rule)
-		claim_zero(mlx5_flow_os_destroy_flow(transfer_green_rule));
-	if (!initialized)
-		flow_dv_destroy_policer_rules(dev, fm, attr);
-	return -1;
-}
-
-/**
  * Validate the batch counter support in root table.
  *
  * Create a simple flow with invalid counter and drop action on root table to
@@ -14442,8 +13987,6 @@ struct mlx5_cache_entry *
 	.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 714b382..af0a1c1 100644
--- a/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/drivers/net/mlx5/mlx5_flow_meter.c
@@ -329,7 +329,6 @@
 	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;
@@ -437,90 +436,6 @@
 }
 
 /**
- * Convert wrong color setting action to verbose error.
- *
- * @param[in] action
- *   Policy color action.
- *
- * @return
- *   Verbose meter color error type.
- */
-static inline enum rte_mtr_error_type
-action2error(enum rte_mtr_policer_action action)
-{
-	switch (action) {
-	case MTR_POLICER_ACTION_COLOR_GREEN:
-		return RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN;
-	case MTR_POLICER_ACTION_COLOR_YELLOW:
-		return RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW;
-	case MTR_POLICER_ACTION_COLOR_RED:
-		return RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED;
-	default:
-		break;
-	}
-	return RTE_MTR_ERROR_TYPE_UNSPECIFIED;
-}
-
-/**
- * Check meter validation.
- *
- * @param[in] priv
- *   Pointer to mlx5 private data structure.
- * @param[in] meter_id
- *   Meter id.
- * @param[in] params
- *   Pointer to rte meter parameters.
- * @param[out] error
- *   Pointer to rte meter error structure.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-mlx5_flow_meter_validate(struct mlx5_priv *priv, uint32_t meter_id,
-			 struct rte_mtr_params *params,
-			 struct rte_mtr_error *error)
-{
-	/* Meter must use global drop action. */
-	if (!priv->sh->dr_drop_action)
-		return -rte_mtr_error_set(error, ENOTSUP,
-					  RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-					  NULL,
-					  "No drop action ready for meter.");
-	/* Meter params must not be NULL. */
-	if (params == NULL)
-		return -rte_mtr_error_set(error, EINVAL,
-					  RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-					  NULL, "Meter object params null.");
-	/* Previous meter color is not supported. */
-	if (params->use_prev_mtr_color)
-		return -rte_mtr_error_set(error, ENOTSUP,
-					  RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-					  NULL,
-					  "Previous meter color "
-					  "not supported.");
-	/* Validate policer settings. */
-	if (params->action[RTE_COLOR_RED] != MTR_POLICER_ACTION_DROP)
-		return -rte_mtr_error_set
-				(error, ENOTSUP,
-				 action2error(params->action[RTE_COLOR_RED]),
-				 NULL,
-				 "Red color only supports drop action.");
-	if (params->action[RTE_COLOR_GREEN] != MTR_POLICER_ACTION_COLOR_GREEN)
-		return -rte_mtr_error_set
-				(error, ENOTSUP,
-				 action2error(params->action[RTE_COLOR_GREEN]),
-				 NULL,
-				 "Green color only supports recolor green action.");
-	/* Validate meter id. */
-	if (mlx5_flow_meter_find(priv, meter_id, NULL))
-		return -rte_mtr_error_set(error, EEXIST,
-					  RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
-					  "Meter object already exists.");
-	return 0;
-}
-
-/**
  * Modify the flow meter action.
  *
  * @param[in] priv
@@ -629,167 +544,14 @@
 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 @@
 		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 @@
 {
 	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 @@
 				"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 @@
 {
 	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 @@
 		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 @@
 {
 	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 @@
 		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 @@
 	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 @@ struct mlx5_flow_meter_info *
 		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 @@ struct mlx5_flow_meter_info *
 	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 @@ struct mlx5_flow_meter_info *
 				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 @@ struct mlx5_flow_meter_info *
 	} 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 7925bad..27eaf38 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -1166,6 +1166,7 @@ struct flow_attr_map *
 {
 	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 @@ struct flow_attr_map *
 					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 faf90a5..1b3186e 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 @@ struct 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 @@ struct softnic_table_action_profile *
 	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 b27b128..acb8b87 100644
--- a/drivers/net/softnic/rte_eth_softnic_meter.c
+++ b/drivers/net/softnic/rte_eth_softnic_meter.c
@@ -65,27 +65,6 @@ struct softnic_mtr_meter_profile *
 	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,
@@ -208,6 +187,160 @@ enum rte_table_action_policer
 	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 add */
+static int
+pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
+	uint32_t meter_policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error)
+{
+	struct pmd_internals *p = dev->data->dev_private;
+	struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
+	struct softnic_mtr_meter_policy *mp;
+	const struct rte_flow_action *act;
+	const struct rte_flow_action_meter_color *recolor;
+	uint32_t i;
+	bool valid_act_found;
+
+	if (policy == NULL)
+		return -rte_mtr_error_set(error,
+			EINVAL,
+			RTE_MTR_ERROR_TYPE_METER_POLICY,
+			NULL,
+			"Null meter policy invalid");
+
+	/* Meter policy must not 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 already exists");
+
+	for (i = 0; i < RTE_COLORS; i++) {
+		if (policy->actions[i] == NULL)
+			return -rte_mtr_error_set(error,
+				EINVAL,
+				RTE_MTR_ERROR_TYPE_METER_POLICY,
+				NULL,
+				"Null action list");
+		for (act = policy->actions[i], valid_act_found = false;
+		     act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
+			if (act->type == RTE_FLOW_ACTION_TYPE_VOID)
+				continue;
+			/*
+			 * Support one (and one only) of
+			 * METER_COLOR or DROP action.
+			 */
+			if ((act->type != RTE_FLOW_ACTION_TYPE_METER_COLOR &&
+				act->type != RTE_FLOW_ACTION_TYPE_DROP) ||
+				valid_act_found)
+				return -rte_mtr_error_set(error,
+					EINVAL,
+					RTE_MTR_ERROR_TYPE_METER_POLICY,
+					NULL,
+					"Action invalid");
+			valid_act_found = true;
+		}
+		if (!valid_act_found)
+			return -rte_mtr_error_set(error,
+				EINVAL,
+				RTE_MTR_ERROR_TYPE_METER_POLICY,
+				NULL,
+				"No valid action found");
+	}
+
+	/* Memory allocation */
+	mp = calloc(1, sizeof(struct softnic_mtr_meter_policy));
+	if (mp == NULL)
+		return -rte_mtr_error_set(error,
+			ENOMEM,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			"Memory alloc failed");
+
+	/* Fill in */
+	mp->meter_policy_id = meter_policy_id;
+	for (i = 0; i < RTE_COLORS; i++) {
+		mp->policer[i] = RTE_TABLE_ACTION_POLICER_DROP;
+		act = policy->actions[i];
+		if (!act)
+			continue;
+		if (act->type == RTE_FLOW_ACTION_TYPE_METER_COLOR) {
+			recolor = act->conf;
+			switch (recolor->color) {
+			case RTE_COLOR_GREEN:
+				mp->policer[i] =
+				RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
+				break;
+			case RTE_COLOR_YELLOW:
+				mp->policer[i] =
+				RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
+				break;
+			case RTE_COLOR_RED:
+				mp->policer[i] =
+				RTE_TABLE_ACTION_POLICER_COLOR_RED;
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+	/* Add to list */
+	TAILQ_INSERT_TAIL(mpl, mp, node);
+
+	return 0;
+}
+
+/* MTR meter policy delete */
+static int
+pmd_mtr_meter_policy_delete(struct rte_eth_dev *dev,
+	uint32_t meter_policy_id,
+	struct rte_mtr_error *error)
+{
+	struct pmd_internals *p = dev->data->dev_private;
+	struct softnic_mtr_meter_policy *mp;
+
+	/* Meter policy must exist */
+	mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
+	if (mp == NULL)
+		return -rte_mtr_error_set(error,
+			EINVAL,
+			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+			NULL,
+			"Meter policy id invalid");
+
+	/* Check unused */
+	if (mp->n_users)
+		return -rte_mtr_error_set(error,
+			EBUSY,
+			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
+			NULL,
+			"Meter policy in use");
+
+	/* Remove from list */
+	TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
+	free(mp);
+
+	return 0;
+}
+
 struct softnic_mtr *
 softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
 {
@@ -275,6 +408,7 @@ struct softnic_mtr *
 	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;
 
@@ -292,6 +426,16 @@ struct softnic_mtr *
 			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)
@@ -310,6 +454,7 @@ struct softnic_mtr *
 
 	/* Update dependencies */
 	mp->n_users++;
+	policy->n_users++;
 
 	return 0;
 }
@@ -324,6 +469,7 @@ struct softnic_mtr *
 	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);
@@ -351,8 +497,18 @@ struct softnic_mtr *
 			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);
@@ -514,18 +670,18 @@ struct softnic_mtr *
 	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);
@@ -536,28 +692,17 @@ struct softnic_mtr *
 			NULL,
 			"MTR object id not valid");
 
-	/* Valid policer actions */
-	if (actions == NULL)
+	if (m->params.meter_policy_id == meter_policy_id)
+		return 0;
+
+	/* 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) {
@@ -569,9 +714,7 @@ struct softnic_mtr *
 
 		/* 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,
@@ -595,10 +738,20 @@ struct softnic_mtr *
 			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;
 }
@@ -615,28 +768,40 @@ struct softnic_mtr *
 
 /* 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];
 		}
 
@@ -647,16 +812,20 @@ struct softnic_mtr *
 		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];
 		}
 
@@ -722,7 +891,8 @@ struct softnic_mtr *
 		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);
@@ -743,6 +913,9 @@ struct softnic_mtr *
 	.meter_profile_add = pmd_mtr_meter_profile_add,
 	.meter_profile_delete = pmd_mtr_meter_profile_delete,
 
+	.meter_policy_add = pmd_mtr_meter_policy_add,
+	.meter_policy_delete = pmd_mtr_meter_policy_delete,
+
 	.create = pmd_mtr_create,
 	.destroy = pmd_mtr_destroy,
 	.meter_enable = NULL,
@@ -750,7 +923,7 @@ struct softnic_mtr *
 
 	.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 c16f5ba..94c8c1c 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -33,6 +33,7 @@
 #include <rte_bitops.h>
 #include <rte_mbuf.h>
 #include <rte_mbuf_dyn.h>
+#include <rte_meter.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -2392,6 +2393,14 @@ enum rte_flow_action_type {
 	 * @see struct rte_flow_action_conntrack.
 	 */
 	RTE_FLOW_ACTION_TYPE_CONNTRACK,
+
+	/**
+	 * Color the packet to reflect the meter color result.
+	 * Set the meter color in the mbuf to the selected color.
+	 *
+	 * See struct rte_flow_action_meter_color.
+	 */
+	RTE_FLOW_ACTION_TYPE_METER_COLOR,
 };
 
 /**
@@ -3139,6 +3148,19 @@ struct rte_flow_modify_conntrack {
 };
 
 /**
+ * @warning
+ * @b EXPERIMENTAL: this structure may change without prior notice
+ *
+ * RTE_FLOW_ACTION_TYPE_METER_COLOR
+ *
+ * The meter color should be set in the packet meta-data
+ * (i.e. struct rte_mbuf::sched::color).
+ */
+struct rte_flow_action_meter_color {
+	enum rte_color color; /**< Packet color. */
+};
+
+/**
  * Field IDs for MODIFY_FIELD action.
  */
 enum rte_flow_field_id {
diff --git a/lib/librte_ethdev/rte_mtr.c b/lib/librte_ethdev/rte_mtr.c
index 3073ac0..e49fcf2 100644
--- a/lib/librte_ethdev/rte_mtr.c
+++ b/lib/librte_ethdev/rte_mtr.c
@@ -91,6 +91,40 @@
 		meter_profile_id, error);
 }
 
+/* MTR meter policy validate */
+int
+rte_mtr_meter_policy_validate(uint16_t port_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_policy_validate)(dev,
+		policy, error);
+}
+
+/* MTR meter policy add */
+int
+rte_mtr_meter_policy_add(uint16_t port_id,
+	uint32_t policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_policy_add)(dev,
+		policy_id, policy, error);
+}
+
+/** MTR meter policy delete */
+int
+rte_mtr_meter_policy_delete(uint16_t port_id,
+	uint32_t policy_id,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, meter_policy_delete)(dev,
+		policy_id, error);
+}
+
 /** MTR object create */
 int
 rte_mtr_create(uint16_t port_id,
@@ -149,29 +183,28 @@
 		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 ceb5dcb..dc246dd 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" {
@@ -200,20 +201,16 @@ struct rte_mtr_meter_profile {
 };
 
 /**
- * Policer actions
+ * Meter policy
  */
-enum rte_mtr_policer_action {
-	/** Recolor the packet as green. */
-	MTR_POLICER_ACTION_COLOR_GREEN = 0,
-
-	/** Recolor the packet as yellow. */
-	MTR_POLICER_ACTION_COLOR_YELLOW,
-
-	/** Recolor the packet as red. */
-	MTR_POLICER_ACTION_COLOR_RED,
-
-	/** Drop the packet. */
-	MTR_POLICER_ACTION_DROP,
+struct rte_mtr_meter_policy_params {
+	/**
+	 * Policy action list per color.
+	 * actions[i] potentially represents a chain of rte_flow actions
+	 * terminated by the END action, exactly as specified by the rte_flow
+	 * API for the flow definition, and not just a single action.
+	 */
+	const struct rte_flow_action *actions[RTE_COLORS];
 };
 
 /**
@@ -257,13 +254,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;
 };
 
 /**
@@ -350,6 +347,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.
 	 */
@@ -367,18 +371,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;
-
 	/**
 	 * srTCM rfc2697 byte mode supported.
 	 * When non-zero, it indicates that byte mode is supported for
@@ -447,6 +439,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,
 };
 
 /**
@@ -531,6 +525,144 @@ struct rte_mtr_error {
 	struct rte_mtr_error *error);
 
 /**
+ * Check whether a meter policy can be created on a given port.
+ *
+ * The meter policy is validated for correctness and
+ * whether it could be accepted by the device given sufficient resources.
+ * The policy is checked against the current capability information
+ * meter_policy_n_max configuration.
+ * The policy may also optionally be validated against existing
+ * device policy resources.
+ * This function has no effect on the target device.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] policy
+ *   Associated action list per color.
+ *   list NULL is legal and means no special action.
+ *   (list terminated by the END action).
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+__rte_experimental
+int
+rte_mtr_meter_policy_validate(uint16_t port_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+
+/**
+ * Meter policy add
+ *
+ * Create a new meter policy. The new policy
+ * is used to create single or multiple MTR objects.
+ * The same policy can be used to create 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] policy
+ *   Associated actions per color.
+ *   list NULL is legal and means no special action.
+ *   Non-NULL list must be terminated.
+ *   (list terminated by the END action).
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+__rte_experimental
+int
+rte_mtr_meter_policy_add(uint16_t port_id,
+	uint32_t policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+
+/**
+ * Define meter policy action list:
+ * GREEN - GREEN, YELLOW - YELLOW, RED - RED
+ */
+#define rte_mtr_policy_pass_color(policy) \
+struct rte_mtr_meter_policy_params policy = \
+{ \
+	.actions[RTE_COLOR_GREEN] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
+			.conf = &(struct rte_flow_action_meter_color) { \
+				.color = RTE_COLOR_GREEN, \
+			}, \
+		}, \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+	.actions[RTE_COLOR_YELLOW] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
+			.conf = &(struct rte_flow_action_meter_color) { \
+				.color = RTE_COLOR_YELLOW, \
+			}, \
+		}, \
+		{ \
+		.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+	.actions[RTE_COLOR_RED] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_METER_COLOR, \
+			.conf = &(struct rte_flow_action_meter_color) { \
+				.color = RTE_COLOR_RED, \
+			}, \
+		}, \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+}
+
+/**
+ * Define meter policy action list:
+ * GREEN - Do nothing, YELLOW - Do nothing, RED - DROP
+ */
+#define rte_mtr_policy_drop_red(policy) \
+struct rte_mtr_meter_policy_params policy = \
+{ \
+	.actions[RTE_COLOR_GREEN] = NULL, \
+	.actions[RTE_COLOR_YELLOW] = NULL, \
+	.actions[RTE_COLOR_RED] = (struct rte_flow_action[]) { \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_DROP, \
+		}, \
+		{ \
+			.type = RTE_FLOW_ACTION_TYPE_END, \
+		}, \
+	}, \
+}
+
+/**
+ * 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
  *
  * Create a new MTR object for the current port. This object is run as part of
@@ -655,18 +787,14 @@ struct rte_mtr_error {
 	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
@@ -674,26 +802,24 @@ struct rte_mtr_error {
  */
 __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
@@ -701,10 +827,9 @@ struct rte_mtr_error {
  */
 __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 a0ddc2b..62273ed 100644
--- a/lib/librte_ethdev/rte_mtr_driver.h
+++ b/lib/librte_ethdev/rte_mtr_driver.h
@@ -41,6 +41,22 @@ typedef int (*rte_mtr_meter_profile_delete_t)(struct rte_eth_dev *dev,
 	struct rte_mtr_error *error);
 /**< @internal MTR meter profile delete */
 
+typedef int (*rte_mtr_meter_policy_validate_t)(struct rte_eth_dev *dev,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+/**< @internal MTR meter policy validate */
+
+typedef int (*rte_mtr_meter_policy_add_t)(struct rte_eth_dev *dev,
+	uint32_t policy_id,
+	struct rte_mtr_meter_policy_params *policy,
+	struct rte_mtr_error *error);
+/**< @internal MTR meter policy add */
+
+typedef int (*rte_mtr_meter_policy_delete_t)(struct rte_eth_dev *dev,
+	uint32_t policy_id,
+	struct rte_mtr_error *error);
+/**< @internal MTR meter policy delete */
+
 typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
 	struct rte_mtr_params *params,
@@ -69,18 +85,17 @@ typedef int (*rte_mtr_meter_profile_update_t)(struct rte_eth_dev *dev,
 	struct rte_mtr_error *error);
 /**< @internal MTR object meter profile update */
 
-typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
+typedef int (*rte_mtr_meter_policy_update_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
-	enum rte_color *dscp_table,
+	uint32_t meter_policy_id,
 	struct rte_mtr_error *error);
-/**< @internal MTR object meter DSCP table update */
+/**< @internal MTR object meter policy update */
 
-typedef int (*rte_mtr_policer_actions_update_t)(struct rte_eth_dev *dev,
+typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
-	uint32_t action_mask,
-	enum rte_mtr_policer_action *actions,
+	enum rte_color *dscp_table,
 	struct rte_mtr_error *error);
-/**< @internal MTR object policer action update*/
+/**< @internal MTR object meter DSCP table update */
 
 typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
 	uint32_t mtr_id,
@@ -124,14 +139,23 @@ struct rte_mtr_ops {
 	/** MTR object meter DSCP table update */
 	rte_mtr_meter_dscp_table_update_t meter_dscp_table_update;
 
-	/** MTR object policer action update */
-	rte_mtr_policer_actions_update_t policer_actions_update;
-
 	/** MTR object enabled stats update */
 	rte_mtr_stats_update_t stats_update;
 
 	/** MTR object stats read */
 	rte_mtr_stats_read_t stats_read;
+
+	/** MTR meter policy validate */
+	rte_mtr_meter_policy_validate_t meter_policy_validate;
+
+	/** MTR meter policy add */
+	rte_mtr_meter_policy_add_t meter_policy_add;
+
+	/** 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 4eb561a..44d30b0 100644
--- a/lib/librte_ethdev/version.map
+++ b/lib/librte_ethdev/version.map
@@ -138,7 +138,6 @@ EXPERIMENTAL {
 	rte_mtr_meter_profile_add;
 	rte_mtr_meter_profile_delete;
 	rte_mtr_meter_profile_update;
-	rte_mtr_policer_actions_update;
 	rte_mtr_stats_read;
 	rte_mtr_stats_update;
 
@@ -246,6 +245,10 @@ EXPERIMENTAL {
 	rte_flow_action_handle_destroy;
 	rte_flow_action_handle_update;
 	rte_flow_action_handle_query;
+	rte_mtr_meter_policy_add;
+	rte_mtr_meter_policy_delete;
+	rte_mtr_meter_policy_update;
+	rte_mtr_meter_policy_validate;
 };
 
 INTERNAL {
-- 
1.8.3.1


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

* [dpdk-dev] [PATCH v10 2/2] app/testpmd: support policy actions per color
  2021-04-20 14:04     ` [dpdk-dev] [PATCH v10 " Jiawei Wang
  2021-04-20 14:04       ` [dpdk-dev] [PATCH v10 1/2] ethdev: add pre-defined " Jiawei Wang
@ 2021-04-20 14:04       ` Jiawei Wang
  2021-04-20 17:14         ` Ajit Khaparde
  2021-04-21 10:23       ` [dpdk-dev] [PATCH v10 0/2] Support meter policy API Ferruh Yigit
  2 siblings, 1 reply; 78+ messages in thread
From: Jiawei Wang @ 2021-04-20 14:04 UTC (permalink / raw)
  To: matan, orika, viacheslavo, shahafs, ferruh.yigit, Xiaoyun Li
  Cc: dev, thomas, rasland, roniba, asafp, Haifei Luo

From: Haifei Luo <haifeil@nvidia.com>

Add the create/del policy CLIs to support actions per color.
The CLIs are:
Create:  add port meter policy (port_id) (policy_id) g_actions (actions)
y_actions (actions) r_actions (actions)
Delete:  del port meter policy (port_id) (policy_id)

Examples:
testpmd> add port meter policy 0 1 g_actions rss / end y_actions end
r_actions drop / end
testpmd> del port meter policy 0 1

Signed-off-by: Haifei Luo <haifeil@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
---
 app/test-pmd/cmdline.c                      |  13 ++-
 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                       |  32 ++++++++
 app/test-pmd/testpmd.h                      |   2 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  30 ++++++-
 7 files changed, 269 insertions(+), 14 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index fd2834e..c300a40 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -708,9 +708,8 @@ 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"
-			"(g_action) (y_action) (r_action) (stats_mask) (shared)\n"
-			"(use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
+			"create port meter (port_id) (mtr_id) (profile_id) (policy_id) (meter_enable)\n"
+			"(stats_mask) (shared) (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
 			"(dscp_tbl_entry63)]\n"
 			"    meter create\n\n"
 
@@ -723,6 +722,13 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"del port meter (port_id) (mtr_id)\n"
 			"    meter delete\n\n"
 
+			"add port meter policy (port_id) (policy_id) g_actions (actions)\n"
+			"y_actions (actions) r_actions (actions)\n"
+			"    meter policy add\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"
 
@@ -17508,6 +17514,7 @@ struct cmd_showport_macs_result {
 	(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 3c4650b..5947341 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,
 	INDIRECT_ACTION_ID,
+	POLICY_ID,
+
+	/* TOP-level command. */
+	ADD,
 
 	/* Top-level command. */
 	SET,
@@ -299,6 +303,9 @@ enum index {
 	ITEM_INTEGRITY_LEVEL,
 	ITEM_INTEGRITY_VALUE,
 	ITEM_CONNTRACK,
+	ITEM_POL_PORT,
+	ITEM_POL_METER,
+	ITEM_POL_POLICY,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -441,6 +448,9 @@ enum index {
 	ACTION_CONNTRACK_UPDATE,
 	ACTION_CONNTRACK_UPDATE_DIR,
 	ACTION_CONNTRACK_UPDATE_CTX,
+	ACTION_POL_G,
+	ACTION_POL_Y,
+	ACTION_POL_R,
 };
 
 /** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -826,6 +836,9 @@ struct buffer {
 		struct {
 			int destroy;
 		} aged; /**< Aged arguments. */
+		struct {
+			uint32_t policy_id;
+		} policy;/**< Policy arguments. */
 	} args; /**< Command arguments. */
 };
 
@@ -1848,6 +1861,9 @@ static int parse_ia_destroy(struct context *ctx, const struct token *token,
 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
 			   const char *str, unsigned int len, void *buf,
 			   unsigned int size);
+static int parse_mp(struct context *, const struct token *,
+		    const char *, unsigned int,
+		    void *, unsigned int);
 static int comp_none(struct context *, const struct token *,
 		     unsigned int, char *, unsigned int);
 static int comp_boolean(struct context *, const struct token *,
@@ -1877,7 +1893,7 @@ static int comp_set_modify_field_id(struct context *, const struct token *,
 	[ZERO] = {
 		.name = "ZERO",
 		.help = "null entry, abused as the entry point",
-		.next = NEXT(NEXT_ENTRY(FLOW)),
+		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
 	},
 	[END] = {
 		.name = "",
@@ -1999,6 +2015,13 @@ static int comp_set_modify_field_id(struct context *, const struct token *,
 		.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",
@@ -4669,6 +4692,54 @@ static int comp_set_modify_field_id(struct context *, const struct token *,
 		.help = "specify action to create indirect handle",
 		.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. */
@@ -4947,6 +5018,47 @@ static int comp_set_modify_field_id(struct context *, const struct 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 validate/create commands. */
 static int
 parse_vc(struct context *ctx, const struct token *token,
@@ -7876,6 +7988,10 @@ static int comp_set_modify_field_id(struct context *, const struct token *,
 	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 aa454af..eff2473 100644
--- a/app/test-pmd/cmdline_mtr.c
+++ b/app/test-pmd/cmdline_mtr.c
@@ -37,6 +37,8 @@
 		[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 @@
 		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)
 {
@@ -705,6 +713,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;
@@ -732,6 +741,9 @@ struct cmd_create_port_meter_result {
 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");
@@ -775,7 +787,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) {
@@ -790,7 +802,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);
@@ -805,7 +816,6 @@ static void cmd_create_port_meter_parsed(void *parsed_result,
 	.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 = {
@@ -815,10 +825,8 @@ static void cmd_create_port_meter_parsed(void *parsed_result,
 		(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,
@@ -948,6 +956,71 @@ static void cmd_disable_port_meter_parsed(void *parsed_result,
 	},
 };
 
+/* *** 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 7e2713c..2415fc1 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_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 ccb9bd3..5789f6d 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
 
@@ -1798,6 +1800,36 @@ struct rte_flow_action_handle *
 	}
 }
 
+/** 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 *act = actions;
+	const struct rte_flow_action *start;
+	struct rte_mtr_meter_policy_params policy;
+	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)
+			policy.actions[i] = start;
+		else
+			policy.actions[i] = NULL;
+		act++;
+	}
+	ret = rte_mtr_meter_policy_add(port_id,
+			policy_id,
+			&policy, &error);
+	if (ret)
+		print_mtr_err_msg(&error);
+	return ret;
+}
+
 /** Validate flow rule. */
 int
 port_flow_validate(portid_t port_id,
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 9530ec5..6ca872d 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -840,6 +840,8 @@ struct port_flow_tunnel *
 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);
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index d9d6841..2141735 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2772,13 +2772,37 @@ Delete meter profile from the ethernet device::
 
    testpmd> del port meter profile (port_id) (profile_id)
 
+create port policy
+~~~~~~~~~~~~~~~~~~
+
+Create new policy object for the ethernet device::
+
+   testpmd> add port meter policy (port_id) (policy_id) g_actions \
+   {action} y_actions {action} r_actions {action}
+
+where:
+
+* ``policy_id``: policy ID.
+* ``action``: action lists for green/yellow/red colors.
+
+delete port policy
+~~~~~~~~~~~~~~~~~~
+
+Delete policy object for the ethernet device::
+
+   testpmd> del port meter policy (port_id) (policy_id)
+
+where:
+
+* ``policy_id``: policy ID.
+
 create port meter
 ~~~~~~~~~~~~~~~~~
 
 Create new meter object for the ethernet device::
 
    testpmd> create port meter (port_id) (mtr_id) (profile_id) \
-   (meter_enable) (g_action) (y_action) (r_action) (stats_mask) (shared) \
+   (policy_id) (meter_enable) (stats_mask) (shared) \
    (use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\
    (dscp_tbl_entry63)]
 
@@ -2786,11 +2810,9 @@ where:
 
 * ``mtr_id``: meter object ID.
 * ``profile_id``: ID for the meter profile.
+* ``policy_id``: ID for the policy.
 * ``meter_enable``: When this parameter has a non-zero value, the meter object
   gets enabled at the time of creation, otherwise remains disabled.
-* ``g_action``: Policer action for the packet with green color.
-* ``y_action``: Policer action for the packet with yellow color.
-* ``r_action``: Policer action for the packet with red color.
 * ``stats_mask``: Mask of statistics counter types to be enabled for the
   meter object.
 * ``shared``:  When this parameter has a non-zero value, the meter object is
-- 
1.8.3.1


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

* Re: [dpdk-dev] [PATCH v9 0/2] Support meter policy API
  2021-04-20 11:36     ` [dpdk-dev] [PATCH v9 0/2] Support meter policy API Ferruh Yigit
@ 2021-04-20 14:08       ` Jiawei(Jonny) Wang
  0 siblings, 0 replies; 78+ messages in thread
From: Jiawei(Jonny) Wang @ 2021-04-20 14:08 UTC (permalink / raw)
  To: Ferruh Yigit, Matan Azrad, Ori Kam, Slava Ovsiienko, Shahaf Shuler
  Cc: dev, NBU-Contact-Thomas Monjalon, Raslan Darawsheh, Roni Bar Yanai

Hi,

> -----Original Message-----
> From: Ferruh Yigit <ferruh.yigit@intel.com>
> Sent: Tuesday, April 20, 2021 7:37 PM
> To: Jiawei(Jonny) Wang <jiaweiw@nvidia.com>; Matan Azrad
> <matan@nvidia.com>; Ori Kam <orika@nvidia.com>; Slava Ovsiienko
> <viacheslavo@nvidia.com>; Shahaf Shuler <shahafs@nvidia.com>
> Cc: dev@dpdk.org; NBU-Contact-Thomas Monjalon
> <thomas@monjalon.net>; Raslan Darawsheh <rasland@nvidia.com>; Roni
> Bar Yanai <roniba@nvidia.com>
> Subject: Re: [dpdk-dev] [PATCH v9 0/2] Support meter policy API
> 
> On 4/19/2021 5:08 PM, Jiawei Wang wrote:
> > 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.
> >
> > Add two common policy template as macros in the header file,
> >
> > RFC ("ethdev: add pre-defined meter policy API")
> > https://patchwork.dpdk.org/project/dpdk/patch/20210318085815.804896-
> 1-
> > lizh@nvidia.com/
> >
> > Depends-on: series=16351  ("Add ASO meter support in MLX5 PMD ")
> > https://patchwork.dpdk.org/project/dpdk/list/?series=16351
> >
> > V2: Delete default policy and change relation doc files.
> > V3: Fix coding style issues.
> > V4: Fix comments about Depends-on
> > V5: Fix comments about rte_mtr_meter_policy_add.
> > V6: Delete policy example.
> > V7: Fix comments and place two common policy template as macros.
> > V8: Fix rebase conflict issues and CI warning
> > V9: Rebase and Fix the comments for softnic driver.
> >
> > Haifei Luo (1):
> >    app/testpmd: support policy actions per color
> >
> > Li Zhang (1):
> >    ethdev: add pre-defined meter policy API
> >
> 
> Hi Li, Haifei,
> 
> This patch conflicts with merged integrity check/conntrack features, also the
> dependent mlx5 ASO set send a new version.
> 
> Can you please send a new version rebasing on latest versions?
> 
> 

Thanks Ferruh point it, I had rebased and also update the new mlx5 ASO series link.
The latest v10 already been sent.

Thanks.


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

* Re: [dpdk-dev] [PATCH v10 1/2] ethdev: add pre-defined meter policy API
  2021-04-20 14:04       ` [dpdk-dev] [PATCH v10 1/2] ethdev: add pre-defined " Jiawei Wang
@ 2021-04-20 17:12         ` Ajit Khaparde
  2021-04-21 19:43         ` Thomas Monjalon
  1 sibling, 0 replies; 78+ messages in thread
From: Ajit Khaparde @ 2021-04-20 17:12 UTC (permalink / raw)
  To: Jiawei Wang
  Cc: Matan Azrad, Ori Kam, Slava Ovsiienko, Shahaf Shuler,
	Ferruh Yigit, Wisam Jaddo, Xiaoyun Li, Jasvinder Singh,
	Cristian Dumitrescu, Thomas Monjalon, Andrew Rybchenko,
	Ray Kinsella, Neil Horman, dpdk-dev, Raslan Darawsheh,
	Roni Bar Yanai, Asaf Penso, Li Zhang, Haifei Luo

[-- Attachment #1: Type: text/plain, Size: 2448 bytes --]

On Tue, Apr 20, 2021 at 7:05 AM Jiawei Wang <jiaweiw@nvidia.com> wrote:
>
> From: Li Zhang <lizh@nvidia.com>
>
> Currently, the flow meter policy does not support multiple actions
> per color; also the allowed action types per color are very limited.
> In addition, the policy cannot be pre-defined.
>
> Due to the growing in flow actions offload abilities there is a potential
> for the user to use variety of actions per color differently.
> This new meter policy API comes to allow this potential in the most ethdev
> common way using rte_flow action definition.
> A list of rte_flow actions will be provided by the user per color
> in order to create a meter policy.
> In addition, the API forces to pre-define the policy before
> the meters creation in order to allow sharing of single policy
> with multiple meters efficiently.
>
> meter_policy_id is added into struct rte_mtr_params.
> So that it can get the policy during the meters creation.
>
> Allow coloring the packet using a new rte_flow_action_color
> as could be done by the old policy API.
>
> Add two common policy template as macros in the head file.
>
> The next API function were added:
> - rte_mtr_meter_policy_add
> - 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. Supports policy API to get color action as policer action did.
>    The color action will be mapped into rte_table_action_policer.
>
> net/mlx5: clean meter creation management
> Cleans and breaks part of the current meter management
> in order to allow better design with policy API.
>
> Signed-off-by: Li Zhang <lizh@nvidia.com>
> Signed-off-by: Haifei Luo <haifeil@nvidia.com>
> Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
> Acked-by: Matan Azrad <matan@nvidia.com>
> Acked-by: Ray Kinsella <mdr@ashroe.eu>
> Acked-by: Ori Kam <orika@nvidia.com>
> Acked-by: Jasvinder Singh <jasvinder.singh@intel.com>
> Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com>


> --
> 1.8.3.1
>

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

* Re: [dpdk-dev] [PATCH v10 2/2] app/testpmd: support policy actions per color
  2021-04-20 14:04       ` [dpdk-dev] [PATCH v10 2/2] app/testpmd: support policy actions per color Jiawei Wang
@ 2021-04-20 17:14         ` Ajit Khaparde
  0 siblings, 0 replies; 78+ messages in thread
From: Ajit Khaparde @ 2021-04-20 17:14 UTC (permalink / raw)
  To: Jiawei Wang
  Cc: matan, orika, viacheslavo, shahafs, ferruh.yigit, Xiaoyun Li,
	dev, thomas, rasland, roniba, asafp, Haifei Luo

[-- Attachment #1: Type: text/plain, Size: 659 bytes --]

On Tue, Apr 20, 2021 at 7:05 AM Jiawei Wang <jiaweiw@nvidia.com> wrote:
>
> From: Haifei Luo <haifeil@nvidia.com>
>
> Add the create/del policy CLIs to support actions per color.
> The CLIs are:
> Create:  add port meter policy (port_id) (policy_id) g_actions (actions)
> y_actions (actions) r_actions (actions)
> Delete:  del port meter policy (port_id) (policy_id)
>
> Examples:
> testpmd> add port meter policy 0 1 g_actions rss / end y_actions end
> r_actions drop / end
> testpmd> del port meter policy 0 1
>
> Signed-off-by: Haifei Luo <haifeil@nvidia.com>
> Acked-by: Matan Azrad <matan@nvidia.com>
Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com>

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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-03-18  8:58 [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API Li Zhang
                   ` (8 preceding siblings ...)
  2021-04-15  9:20 ` [dpdk-dev] [PATCH v8 0/2] Support meter policy API Li Zhang
@ 2021-04-20 17:56 ` Stephen Hemminger
  2021-04-21  2:49   ` Li Zhang
  9 siblings, 1 reply; 78+ messages in thread
From: Stephen Hemminger @ 2021-04-20 17:56 UTC (permalink / raw)
  To: Li Zhang
  Cc: dekelp, orika, viacheslavo, matan, shahafs, lironh,
	jasvinder.singh, Thomas Monjalon, Ferruh Yigit, Andrew Rybchenko,
	Cristian Dumitrescu, dev, rasland, roniba

On Thu, 18 Mar 2021 10:58:14 +0200
Li Zhang <lizh@nvidia.com> wrote:

> +
> +	/**
> +	 * Color the packet to reflect the meter color result.
> +	 *
> +	 * See struct rte_flow_action_color.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_COlOR,

Why the odd use of lower case here? Shouldn't it be RTE_FLOW_ACTION_TYPE_COLOR

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

* Re: [dpdk-dev] [PATCH v9 1/2] ethdev: add pre-defined meter policy API
  2021-04-20 12:55         ` Asaf Penso
@ 2021-04-20 21:01           ` Dumitrescu, Cristian
  0 siblings, 0 replies; 78+ messages in thread
From: Dumitrescu, Cristian @ 2021-04-20 21:01 UTC (permalink / raw)
  To: Asaf Penso, Jiawei(Jonny) Wang, Matan Azrad, Ori Kam,
	Slava Ovsiienko, Shahaf Shuler, Wisam Monther, Li, Xiaoyun,
	Singh, Jasvinder, NBU-Contact-Thomas Monjalon, Yigit, Ferruh,
	Andrew Rybchenko, Ray Kinsella, Neil Horman
  Cc: dev, Raslan Darawsheh, Roni Bar Yanai, Li Zhang, Haifei Luo



> -----Original Message-----
> From: Asaf Penso <asafp@nvidia.com>
> Sent: Tuesday, April 20, 2021 1:55 PM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; Jiawei(Jonny)
> Wang <jiaweiw@nvidia.com>; Matan Azrad <matan@nvidia.com>; Ori Kam
> <orika@nvidia.com>; Slava Ovsiienko <viacheslavo@nvidia.com>; Shahaf
> Shuler <shahafs@nvidia.com>; Wisam Monther <wisamm@nvidia.com>; Li,
> Xiaoyun <xiaoyun.li@intel.com>; Singh, Jasvinder
> <jasvinder.singh@intel.com>; NBU-Contact-Thomas Monjalon
> <thomas@monjalon.net>; Yigit, Ferruh <ferruh.yigit@intel.com>; Andrew
> Rybchenko <andrew.rybchenko@oktetlabs.ru>; Ray Kinsella
> <mdr@ashroe.eu>; Neil Horman <nhorman@tuxdriver.com>
> Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar Yanai
> <roniba@nvidia.com>; Li Zhang <lizh@nvidia.com>; Haifei Luo
> <haifeil@nvidia.com>
> Subject: RE: [PATCH v9 1/2] ethdev: add pre-defined meter policy API
> 
> Thank you, Cristian, appreciate this extra effort!
> 
> Regards,
> Asaf Penso
> 

My pleasure, Asaf, thank you! :)

Regards,
Cristian

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

* Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter policy API
  2021-04-20 17:56 ` [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined " Stephen Hemminger
@ 2021-04-21  2:49   ` Li Zhang
  0 siblings, 0 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-21  2:49 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: dekelp, Ori Kam, Slava Ovsiienko, Matan Azrad, Shahaf Shuler,
	lironh, jasvinder.singh, NBU-Contact-Thomas Monjalon,
	Ferruh Yigit, Andrew Rybchenko, Cristian Dumitrescu, dev,
	Raslan Darawsheh, Roni Bar Yanai

Hi Stephen

Thanks your comments.
We already change it in the following series and please take a look:
https://patchwork.dpdk.org/project/dpdk/list/?series=16524
+	/**
+	 * Color the packet to reflect the meter color result.
+	 * Set the meter color in the mbuf to the selected color.
+	 *
+	 * See struct rte_flow_action_meter_color.
+	 */
+	RTE_FLOW_ACTION_TYPE_METER_COLOR,

Regards,
Li Zhang
> -----Original Message-----
> From: Stephen Hemminger <stephen@networkplumber.org>
> Sent: Wednesday, April 21, 2021 1:56 AM
> To: Li Zhang <lizh@nvidia.com>
> Cc: dekelp@nvidia.com; Ori Kam <orika@nvidia.com>; Slava Ovsiienko
> <viacheslavo@nvidia.com>; Matan Azrad <matan@nvidia.com>; Shahaf
> Shuler <shahafs@nvidia.com>; lironh@marvell.com;
> jasvinder.singh@intel.com; NBU-Contact-Thomas Monjalon
> <thomas@monjalon.net>; Ferruh Yigit <ferruh.yigit@intel.com>; Andrew
> Rybchenko <andrew.rybchenko@oktetlabs.ru>; Cristian Dumitrescu
> <cristian.dumitrescu@intel.com>; dev@dpdk.org; Raslan Darawsheh
> <rasland@nvidia.com>; Roni Bar Yanai <roniba@nvidia.com>
> Subject: Re: [dpdk-dev] [PATCH 1/2] [RFC]: ethdev: add pre-defined meter
> policy API
> 
> External email: Use caution opening links or attachments
> 
> 
> On Thu, 18 Mar 2021 10:58:14 +0200
> Li Zhang <lizh@nvidia.com> wrote:
> 
> > +
> > +     /**
> > +      * Color the packet to reflect the meter color result.
> > +      *
> > +      * See struct rte_flow_action_color.
> > +      */
> > +     RTE_FLOW_ACTION_TYPE_COlOR,
> 
> Why the odd use of lower case here? Shouldn't it be
> RTE_FLOW_ACTION_TYPE_COLOR

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

* Re: [dpdk-dev] [PATCH v10 0/2] Support meter policy API
  2021-04-20 14:04     ` [dpdk-dev] [PATCH v10 " Jiawei Wang
  2021-04-20 14:04       ` [dpdk-dev] [PATCH v10 1/2] ethdev: add pre-defined " Jiawei Wang
  2021-04-20 14:04       ` [dpdk-dev] [PATCH v10 2/2] app/testpmd: support policy actions per color Jiawei Wang
@ 2021-04-21 10:23       ` Ferruh Yigit
  2 siblings, 0 replies; 78+ messages in thread
From: Ferruh Yigit @ 2021-04-21 10:23 UTC (permalink / raw)
  To: Jiawei Wang, matan, orika, viacheslavo, shahafs
  Cc: dev, thomas, rasland, roniba, asafp

On 4/20/2021 3:04 PM, Jiawei Wang wrote:
> 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.
> 
> Add two common policy template as macros in the header file,
> 
> RFC ("ethdev: add pre-defined meter policy API")
> https://patchwork.dpdk.org/project/dpdk/patch/20210318085815.804896-1-lizh@nvidia.com/
> 
> Depends-on: series=16520  ("Add ASO meter support in MLX5 PMD ")
> https://patchwork.dpdk.org/project/dpdk/list/?series=16520
> 
> v10:
> * Rebase.
> 
> v9:
> * Rebase.
> * Fix the comments for softnic driver.
> 
> v8:
> * Fix rebase conflict issues and CI warning.
> 
> v7:
> * Fix comments and place two common policy template as macros.
> 
> v6:
> * Delete policy example.
> 
> v5:
> * Fix comments about rte_mtr_meter_policy_add.
> 
> v4:
> * Fix comments about Depends-on.
> 
> v3:
> * Fix coding style issues.
> 
> 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
> 

Series applied to dpdk-next-net/main, thanks.


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

* Re: [dpdk-dev] [PATCH v10 1/2] ethdev: add pre-defined meter policy API
  2021-04-20 14:04       ` [dpdk-dev] [PATCH v10 1/2] ethdev: add pre-defined " Jiawei Wang
  2021-04-20 17:12         ` Ajit Khaparde
@ 2021-04-21 19:43         ` Thomas Monjalon
  2021-04-22  1:29           ` Li Zhang
  1 sibling, 1 reply; 78+ messages in thread
From: Thomas Monjalon @ 2021-04-21 19:43 UTC (permalink / raw)
  To: Jiawei Wang
  Cc: matan, orika, viacheslavo, shahafs, ferruh.yigit, Wisam Jaddo,
	Xiaoyun Li, Jasvinder Singh, Cristian Dumitrescu,
	Andrew Rybchenko, Ray Kinsella, dev, rasland, roniba, asafp,
	Li Zhang, Haifei Luo

20/04/2021 16:04, Jiawei Wang:
> --- a/doc/guides/rel_notes/release_21_05.rst
> +++ b/doc/guides/rel_notes/release_21_05.rst
> @@ -244,6 +244,27 @@ New Features
>    * Added support for crypto adapter forward mode in octeontx2 event and crypto
>      device driver.
>  
> +  * 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_add()``, ``rte_mtr_meter_policy_delete()`` and
> +    ``rte_mtr_create_with_policy()``
> +  * ethdev: Removed rte_mtr_policer_action from rte_mtr_params structures.
> +  * ethdev: Added rte_mtr_meter_policy_params structures to support policy API.
> +  * ethdev: Added meter_policy_id into rte_mtr_params structures.
> +  * ethdev: Removed policer_action_recolor_supported and policer_action_drop_supported from rte_mtr_capabilities structures.
> +  * ethdev: Added meter_policy_n_max into rte_mtr_capabilities structures.
> +  * ethdev: Added RTE_FLOW_ACTION_TYPE_METER_COLOR in enum rte_flow_action_type.
> +  * ethdev: Added RTE_MTR_ERROR_TYPE_METER_POLICY_ID and RTE_MTR_ERROR_TYPE_METER_POLICY_ID into rte_mtr_error_type.

What is this garbage?
Wrong place, wrong format, wrong everything.

I would like to see a bit more attention to details,
especially in a rush to close the -rc1.



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

* Re: [dpdk-dev] [PATCH v10 1/2] ethdev: add pre-defined meter policy API
  2021-04-21 19:43         ` Thomas Monjalon
@ 2021-04-22  1:29           ` Li Zhang
  0 siblings, 0 replies; 78+ messages in thread
From: Li Zhang @ 2021-04-22  1:29 UTC (permalink / raw)
  To: NBU-Contact-Thomas Monjalon, Jiawei(Jonny) Wang
  Cc: Matan Azrad, Ori Kam, Slava Ovsiienko, Shahaf Shuler,
	ferruh.yigit, Wisam Monther, Xiaoyun Li, Jasvinder Singh,
	Cristian Dumitrescu, Andrew Rybchenko, Ray Kinsella, dev,
	Raslan Darawsheh, Roni Bar Yanai, Asaf Penso, Haifei Luo

Hi Thomas,

Thanks for your comments.
Since this patch already accepted, I will fix it in RC2.

Regards,
Li Zhang

> -----Original Message-----
> From: Thomas Monjalon <thomas@monjalon.net>
> Sent: Thursday, April 22, 2021 3:44 AM
> To: Jiawei(Jonny) Wang <jiaweiw@nvidia.com>
> Cc: Matan Azrad <matan@nvidia.com>; Ori Kam <orika@nvidia.com>; Slava
> Ovsiienko <viacheslavo@nvidia.com>; Shahaf Shuler <shahafs@nvidia.com>;
> ferruh.yigit@intel.com; Wisam Monther <wisamm@nvidia.com>; Xiaoyun Li
> <xiaoyun.li@intel.com>; Jasvinder Singh <jasvinder.singh@intel.com>; Cristian
> Dumitrescu <cristian.dumitrescu@intel.com>; Andrew Rybchenko
> <andrew.rybchenko@oktetlabs.ru>; Ray Kinsella <mdr@ashroe.eu>;
> dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>; Roni Bar Yanai
> <roniba@nvidia.com>; Asaf Penso <asafp@nvidia.com>; Li Zhang
> <lizh@nvidia.com>; Haifei Luo <haifeil@nvidia.com>
> Subject: Re: [dpdk-dev] [PATCH v10 1/2] ethdev: add pre-defined meter policy
> API
> 
> External email: Use caution opening links or attachments
> 
> 
> 20/04/2021 16:04, Jiawei Wang:
> > --- a/doc/guides/rel_notes/release_21_05.rst
> > +++ b/doc/guides/rel_notes/release_21_05.rst
> > @@ -244,6 +244,27 @@ New Features
> >    * Added support for crypto adapter forward mode in octeontx2 event and
> crypto
> >      device driver.
> >
> > +  * 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_add()``, ``rte_mtr_meter_policy_delete()`` and
> > +    ``rte_mtr_create_with_policy()``
> > +  * ethdev: Removed rte_mtr_policer_action from rte_mtr_params
> structures.
> > +  * ethdev: Added rte_mtr_meter_policy_params structures to support
> policy API.
> > +  * ethdev: Added meter_policy_id into rte_mtr_params structures.
> > +  * ethdev: Removed policer_action_recolor_supported and
> policer_action_drop_supported from rte_mtr_capabilities structures.
> > +  * ethdev: Added meter_policy_n_max into rte_mtr_capabilities structures.
> > +  * ethdev: Added RTE_FLOW_ACTION_TYPE_METER_COLOR in enum
> rte_flow_action_type.
> > +  * ethdev: Added RTE_MTR_ERROR_TYPE_METER_POLICY_ID and
> RTE_MTR_ERROR_TYPE_METER_POLICY_ID into rte_mtr_error_type.
> 
> What is this garbage?
> Wrong place, wrong format, wrong everything.
> 
> I would like to see a bit more attention to details, especially in a rush to close
> the -rc1.
> 


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

end of thread, other threads:[~2021-04-22  1:29 UTC | newest]

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.