All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/3] rte_mtr: generic ethdev API for metering and policing
@ 2017-05-30 16:44 Cristian Dumitrescu
  2017-05-30 16:44 ` [RFC 1/3] ethdev: add traffic metering and policing ops get API Cristian Dumitrescu
                   ` (2 more replies)
  0 siblings, 3 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-05-30 16:44 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jerin.jacob, hemant.agrawal,
	declan.doherty, keith.wiles

This patch set introduces an ethdev-based generic API for Traffic
Metering and Policing (MTR), which is yet another standard RX offload for
Ethernet devices.

Similar to rte_flow and rte_tm APIs, the configuration of MTR objects is
done in their own namespace (rte_mtr) within the librte_ether library.
Metering and policing action typically sits on top of flow classification,
which is why MTR objects are enabled through a newly introduced rte_flow
action, which is the only impact to rte_flow API.

Q1: Why introduce ethdev-based traffic metering ad policing API?
A1: Traffic metering and policing is a standard RX offload for Ethernet
devices present in NICs, SoCs and NPUs across the industry.

Q2: What's the connection between the new rte_mtr API and the existing
librte_meter library?
A2: The existing librte_meter library provides a SW implementation for a
subset of the features exposed by this API. The rte_mtr API is agnostic to
whether the implementation is HW, SW or mixed HW-SW.

Q3: What's the connection between the new rte_mtr API and the existing
rte_flow API?
A3: The MTR object is hooked into ethdev RX processing path using a newly
introduced rte_flow action, which is the only impact to the rte_flow API.
The configuration of MTR objects is done in separate namespace (rte_mtr)
outside of rte_flow API.

Q4: Can the new rte_flow meter action drop packets? Is this a terminating
action or not?
A4: Although packets can be dropped by the newly introduced rte_flow meter
action, this action is non-terminating, i.e. the action list typically
contains at least one more action, which is a terminating action.
Depending on the policer actions configured for the MTR object, some
packets might be dropped while some packets passed to the next flow action
with their color set in the packet mbuf. For example, a typical policer
configuration is to drop the red packets while passing the green packets,
therefore a subsequent rte_flow action needs to be configured to determine
the final destination of green packets.

Q5: Which are the main operations exposed for the MTR object?
A5: Traffic metering, policing and statistics update. Traffic metering
determines the color for the current packet (green, yellow, red) based on
the previous history for this flow as maintained by the MTR object.
The policer can do nothing, recolor or drop the packet. Stats are
maintained for MTR object, as configured.

Q6: Where is the output color stored for the current packet.
A6: struct rte_mbuf::sched::color.

Q7: Which are the supported metering algorithms?
A7: srTCM (RFC 2697), trTCM (RFC 2698).

Q8: Which are the supported policer actions?
A8: Recolor the packet (keep or change the color determined by metering)
or drop the packet.

Cristian Dumitrescu (3):
  ethdev: add traffic metering and policing ops get API
  ethdev: add new rte_mtr API for traffic metering and policing
  rte_flow: add new action for traffic metering and policing

 MAINTAINERS                            |   4 +
 lib/librte_ether/Makefile              |   7 +-
 lib/librte_ether/rte_ethdev.c          |  12 +
 lib/librte_ether/rte_ethdev.h          |  20 ++
 lib/librte_ether/rte_ether_version.map |  14 +
 lib/librte_ether/rte_flow.h            |  22 ++
 lib/librte_ether/rte_mtr.c             | 184 +++++++++++++
 lib/librte_ether/rte_mtr.h             | 465 +++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_mtr_driver.h      | 188 +++++++++++++
 9 files changed, 914 insertions(+), 2 deletions(-)
 create mode 100644 lib/librte_ether/rte_mtr.c
 create mode 100644 lib/librte_ether/rte_mtr.h
 create mode 100644 lib/librte_ether/rte_mtr_driver.h

-- 
2.7.4

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

* [RFC 1/3] ethdev: add traffic metering and policing ops get API
  2017-05-30 16:44 [RFC 0/3] rte_mtr: generic ethdev API for metering and policing Cristian Dumitrescu
@ 2017-05-30 16:44 ` Cristian Dumitrescu
  2017-05-30 16:44 ` [RFC 2/3] ethdev: add new rte_mtr API for traffic metering and policing Cristian Dumitrescu
  2017-05-30 16:44 ` [RFC 3/3] rte_flow: add new action for traffic " Cristian Dumitrescu
  2 siblings, 0 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-05-30 16:44 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jerin.jacob, hemant.agrawal,
	declan.doherty, keith.wiles

Following similar approach to rte_flow and rte_tm for modularity reasons.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 lib/librte_ether/rte_ethdev.c          | 12 ++++++++++++
 lib/librte_ether/rte_ethdev.h          | 20 ++++++++++++++++++++
 lib/librte_ether/rte_ether_version.map |  6 ++++++
 3 files changed, 38 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 83898a8..eb35ef0 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3021,6 +3021,18 @@ rte_eth_dev_filter_ctrl(uint8_t port_id, enum rte_filter_type filter_type,
 	return (*dev->dev_ops->filter_ctrl)(dev, filter_type, filter_op, arg);
 }
 
+int
+rte_eth_dev_mtr_ops_get(uint8_t port_id, void *ops)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->mtr_ops_get, -ENOTSUP);
+	return (*dev->dev_ops->mtr_ops_get)(dev, ops);
+}
+
 void *
 rte_eth_add_rx_callback(uint8_t port_id, uint16_t queue_id,
 		rte_rx_callback_fn fn, void *user_param)
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 0f38b45..e3a1169 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1441,6 +1441,9 @@ typedef int (*eth_filter_ctrl_t)(struct rte_eth_dev *dev,
 				 void *arg);
 /**< @internal Take operations to assigned filter type on an Ethernet device */
 
+typedef int (*eth_mtr_ops_get_t)(struct rte_eth_dev *dev, void *ops);
+/**< @internal Get Trafffic Metering and Policing (MTR) operations */
+
 typedef int (*eth_get_dcb_info)(struct rte_eth_dev *dev,
 				 struct rte_eth_dcb_info *dcb_info);
 /**< @internal Get dcb information on an Ethernet device */
@@ -1573,6 +1576,9 @@ struct eth_dev_ops {
 	/**< Get extended device statistic values by ID. */
 	eth_xstats_get_names_by_id_t xstats_get_names_by_id;
 	/**< Get name of extended device statistics by ID. */
+
+	eth_mtr_ops_get_t mtr_ops_get;
+	/**< Get Traffic Metering and Policing (MTR) operations. */
 };
 
 /**
@@ -4105,6 +4111,20 @@ int rte_eth_dev_filter_ctrl(uint8_t port_id, enum rte_filter_type filter_type,
 			enum rte_filter_op filter_op, void *arg);
 
 /**
+ * Take Traffic Metering and Policing (MTR) operations on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param arg
+ *   Pointer to MTR operations.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-ENODEV) if *port_id* invalid.
+ */
+int rte_eth_dev_mtr_ops_get(uint8_t port_id, void *ops);
+
+/**
  * Get DCB information on an Ethernet device.
  *
  * @param port_id
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index d6726bb..9783aa1 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -156,3 +156,9 @@ DPDK_17.05 {
 	rte_eth_xstats_get_names_by_id;
 
 } DPDK_17.02;
+
+DPDK_17.08 {
+    global:
+
+	rte_eth_dev_mtr_ops_get;
+} DPDK_17.05;
-- 
2.7.4

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

* [RFC 2/3] ethdev: add new rte_mtr API for traffic metering and policing
  2017-05-30 16:44 [RFC 0/3] rte_mtr: generic ethdev API for metering and policing Cristian Dumitrescu
  2017-05-30 16:44 ` [RFC 1/3] ethdev: add traffic metering and policing ops get API Cristian Dumitrescu
@ 2017-05-30 16:44 ` Cristian Dumitrescu
  2017-08-26  0:06   ` [PATCH 0/3] rte_mtr: generic ethdev API for " Cristian Dumitrescu
  2017-05-30 16:44 ` [RFC 3/3] rte_flow: add new action for traffic " Cristian Dumitrescu
  2 siblings, 1 reply; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-05-30 16:44 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jerin.jacob, hemant.agrawal,
	declan.doherty, keith.wiles

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 MAINTAINERS                            |   4 +
 lib/librte_ether/Makefile              |   7 +-
 lib/librte_ether/rte_ether_version.map |   8 +
 lib/librte_ether/rte_mtr.c             | 184 +++++++++++++
 lib/librte_ether/rte_mtr.h             | 465 +++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_mtr_driver.h      | 188 +++++++++++++
 6 files changed, 854 insertions(+), 2 deletions(-)
 create mode 100644 lib/librte_ether/rte_mtr.c
 create mode 100644 lib/librte_ether/rte_mtr.h
 create mode 100644 lib/librte_ether/rte_mtr_driver.h

diff --git a/MAINTAINERS b/MAINTAINERS
index afb4cab..b025a7b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -240,6 +240,10 @@ Flow API
 M: Adrien Mazarguil <adrien.mazarguil@6wind.com>
 F: lib/librte_ether/rte_flow*
 
+Traffic metering and policing API
+M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
+F: lib/librte_ether/rte_mtr*
+
 Crypto API
 M: Declan Doherty <declan.doherty@intel.com>
 F: lib/librte_cryptodev/
diff --git a/lib/librte_ether/Makefile b/lib/librte_ether/Makefile
index 93fdde1..48f1098 100644
--- a/lib/librte_ether/Makefile
+++ b/lib/librte_ether/Makefile
@@ -1,6 +1,6 @@
 #   BSD LICENSE
 #
-#   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+#   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
 #   All rights reserved.
 #
 #   Redistribution and use in source and binary forms, with or without
@@ -41,10 +41,11 @@ CFLAGS += $(WERROR_FLAGS)
 
 EXPORT_MAP := rte_ether_version.map
 
-LIBABIVER := 6
+LIBABIVER := 7
 
 SRCS-y += rte_ethdev.c
 SRCS-y += rte_flow.c
+SRCS-y += rte_mtr.c
 
 #
 # Export include files
@@ -56,5 +57,7 @@ SYMLINK-y-include += rte_eth_ctrl.h
 SYMLINK-y-include += rte_dev_info.h
 SYMLINK-y-include += rte_flow.h
 SYMLINK-y-include += rte_flow_driver.h
+SYMLINK-y-include += rte_mtr.h
+SYMLINK-y-include += rte_mtr_driver.h
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index 9783aa1..89ea2ed 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -161,4 +161,12 @@ DPDK_17.08 {
     global:
 
 	rte_eth_dev_mtr_ops_get;
+	rte_mtr_meter_profile_add;
+	rte_mtr_meter_profile_delete;
+	rte_mtr_create;
+	rte_mtr_destroy;
+	rte_mtr_meter_profile_update;
+	rte_mtr_policer_action_update;
+	rte_mtr_stats_update;
+	rte_mtr_stats_read;
 } DPDK_17.05;
diff --git a/lib/librte_ether/rte_mtr.c b/lib/librte_ether/rte_mtr.c
new file mode 100644
index 0000000..efbe7fb
--- /dev/null
+++ b/lib/librte_ether/rte_mtr.c
@@ -0,0 +1,184 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+
+#include <rte_errno.h>
+#include "rte_ethdev.h"
+#include "rte_mtr_driver.h"
+#include "rte_mtr.h"
+
+/* Get generic traffic metering and policing operations structure from a port. */
+const struct rte_mtr_ops *
+rte_mtr_ops_get(uint8_t port_id, struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	const struct rte_mtr_ops *ops;
+
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		rte_mtr_error_set(error,
+			ENODEV,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			rte_strerror(ENODEV));
+		return NULL;
+	}
+
+	if ((dev->dev_ops->mtr_ops_get == NULL) ||
+		(dev->dev_ops->mtr_ops_get(dev, &ops) != 0) ||
+		(ops == NULL)) {
+		rte_mtr_error_set(error,
+			ENOSYS,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			rte_strerror(ENOSYS));
+		return NULL;
+	}
+
+	return ops;
+}
+
+#define RTE_MTR_FUNC(port_id, func)			\
+({							\
+	const struct rte_mtr_ops *ops =			\
+		rte_mtr_ops_get(port_id, error);		\
+	if (ops == NULL)					\
+		return -rte_errno;			\
+							\
+	if (ops->func == NULL)				\
+		return -rte_mtr_error_set(error,		\
+			ENOSYS,				\
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,	\
+			NULL,				\
+			rte_strerror(ENOSYS));		\
+							\
+	ops->func;					\
+})
+
+/* MTR meter profile add */
+int
+rte_mtr_meter_profile_add(uint8_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);
+}
+
+/** MTR meter profile delete */
+int
+rte_mtr_meter_profile_delete(uint8_t port_id,
+	uint32_t meter_profile_id,
+	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);
+}
+
+/** MTR object create */
+int
+rte_mtr_create(uint8_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);
+}
+
+/** MTR object destroy */
+int
+rte_mtr_destroy(uint8_t port_id,
+	uint32_t mtr_id,
+	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 object meter profile update */
+int
+rte_mtr_meter_profile_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint32_t meter_profile_id,
+	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 object policer action update */
+int
+rte_mtr_policer_action_update(uint8_t port_id,
+	uint32_t mtr_id,
+	enum rte_mtr_color color,
+	enum rte_mtr_policer_action action,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, policer_action_update)(dev,
+		mtr_id, color, action, error);
+}
+
+/** MTR object enabled stats update */
+int
+rte_mtr_stats_update(uint8_t port_id,
+	uint32_t mtr_id,
+	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 object stats read */
+int
+rte_mtr_stats_read(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error)
+{
+	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);
+}
diff --git a/lib/librte_ether/rte_mtr.h b/lib/librte_ether/rte_mtr.h
new file mode 100644
index 0000000..63179d1
--- /dev/null
+++ b/lib/librte_ether/rte_mtr.h
@@ -0,0 +1,465 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __INCLUDE_RTE_MTR_H__
+#define __INCLUDE_RTE_MTR_H__
+
+/**
+ * @file
+ * RTE Generic Traffic Metering and Policing API
+ *
+ * This interface provides the ability to configure the traffic metering and
+ * policing (MTR) in a generic way.
+ *
+ * The processing done for each input packet hitting a MTR object is:
+ *    A) Traffic metering: The packet is assigned a color (the meter output
+ *       color), based on the previous history of the flow reflected in the
+ *       current state of the MTR object, according to the specific traffic
+ *       metering algorithm. The traffic metering algorithm can typically work
+ *       in color aware mode, in which case the input packet already has an
+ *       initial color (the input color), or in color blind mode, which is
+ *       equivalent to considering all input packets initially colored as green.
+ *    B) Policing: There is a separate policer action configured for each meter
+ *       output color, which can:
+ *          a) Drop the packet.
+ *          b) Keep the same packet color: the policer output color matches the
+ *             meter output color (essentially a no-op action).
+ *          c) Recolor the packet: the policer output color is different 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).
+ *    C) Statistics: The set of counters maintained for each MTR object is
+ *       configurable and subject to the implementation support. This set
+ *       includes the number of packets and bytes dropped or passed for each
+ *       output color.
+ *
+ * Once successfully created, an MTR object is linked to one or several flows
+ * through the meter action of the flow API.
+ *    A) Whether an MTR object is private to a flow or potentially shared by
+ *       several flows has to be specified at creation time.
+ *    B) Several meter actions can be potentially registered for the same flow.
+ */
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Color
+ */
+enum rte_mtr_color {
+	RTE_MTR_GREEN = 0, /**< Green */
+	RTE_MTR_YELLOW, /**< Yellow */
+	RTE_MTR_RED, /**< Red */
+	RTE_MTR_COLORS /**< Number of colors */
+};
+
+/**
+ * Statistics counter type
+ */
+enum rte_mtr_stats_type {
+	/**< Number of packets passed as green by the policer.  */
+	RTE_MTR_STATS_N_PKTS_GREEN = 1 << 0,
+
+	/**< Number of bytes passed as green by the policer.  */
+	RTE_MTR_STATS_N_BYTES_GREEN = 1 << 1,
+
+	/**< Number of packets passed as yellow by the policer.  */
+	RTE_MTR_STATS_N_PKTS_YELLOW = 1 << 2,
+
+	/**< Number of bytes passed as yellow by the policer.  */
+	RTE_MTR_STATS_N_BYTES_YELLOW = 1 << 3,
+
+	/**< Number of packets passed as red by the policer.  */
+	RTE_MTR_STATS_N_PKTS_RED = 1 << 4,
+
+	/**< Number of bytes passed as red by the policer.  */
+	RTE_MTR_STATS_N_BYTES_RED = 1 << 5,
+
+	/**< Number of packets dropped by the policer.  */
+	RTE_MTR_STATS_N_PKTS_DROPPED = 1 << 6,
+
+	/**< Number of bytes dropped by the policer.  */
+	RTE_MTR_STATS_N_BYTES_DROPPED = 1 << 7,
+};
+
+/**
+ * Statistics counters
+ */
+struct rte_mtr_stats {
+	/**< Number of packets passed by the policer (per color). */
+	uint64_t n_pkts[RTE_MTR_COLORS];
+
+	/**< Number of bytes passed by the policer (per color). */
+	uint64_t n_bytes[RTE_MTR_COLORS];
+
+	/**< Number of packets dropped by the policer. */
+	uint64_t n_pkts_dropped;
+
+	/**< Number of bytes passed by the policer. */
+	uint64_t n_bytes_dropped;
+};
+
+/**
+ * Traffic metering algorithms
+ */
+enum rte_mtr_algorithm {
+	/**< Single Rate Three Color Marker (srTCM) - IETF RFC 2697. */
+	RTE_MTR_SRTCM_RFC2697 = 0,
+
+	/**< Two Rate Three Color Marker (trTCM) - IETF RFC 2698. */
+	RTE_MTR_TRTCM_RFC2698,
+};
+
+/**
+ * Meter profile
+ */
+struct rte_mtr_meter_profile {
+	/**<  Traffic metering algorithm. */
+	enum rte_mtr_algorithm alg;
+
+	union {
+		/**< Items only valid when *alg* is set to srTCM - RFC2697. */
+		struct {
+			/**< Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/**< Committed Burst Size (CBS) (bytes). */
+			uint64_t cbs;
+
+			/**< Excess Burst Size (EBS) (bytes). */
+			uint64_t ebs;
+
+			/**< Non-zero for color aware mode, zero for color blind
+			 * mode. In color aware mode, the packet input color is
+			 * read from the IPv4/IPv6 DSCP field, as defined by
+			 * IETF RFC 2597 (low/medium/high drop precedence
+			 * translates to green/yellow/red color respectively).
+			 */
+			int color_aware;
+		} srtcm_rfc2697;
+
+		/**< Items only valid when *alg* is set to trTCM - RFC2698. */
+		struct {
+			/**< Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/**< Peak Information Rate (PIR) (bytes/second). */
+			uint64_t pir;
+
+			/**< Committed Burst Size (CBS) (byes). */
+			uint64_t cbs;
+
+			/**< Peak Burst Size (PBS) (bytes). */
+			uint64_t pbs;
+
+			/**< Non-zero for color aware mode, zero for color blind
+			 * mode. In color aware mode, the packet input color is
+			 * read from the IPv4/IPv6 DSCP field, as defined by
+			 * IETF RFC 2597 (low/medium/high drop precedence
+			 * translates to green/yellow/red color respectively).
+			 */
+			int color_aware;
+		} trtcm_rfc2698;
+	};
+};
+
+/**
+ * Policer actions
+ */
+enum rte_mtr_policer_action {
+	/**< Recolor the packet as green. */
+	e_MTR_POLICER_ACTION_COLOR_GREEN = 0,
+
+	/**< Recolor the packet as yellow. */
+	e_MTR_POLICER_ACTION_COLOR_YELLOW,
+
+	/**< Recolor the packet as red. */
+	e_MTR_POLICER_ACTION_COLOR_RED,
+
+	/**< Drop the packet. */
+	e_MTR_POLICER_ACTION_DROP,
+};
+
+/**
+ * Parameters for each traffic metering & policing object
+ *
+ * @see enum rte_mtr_stats_type
+ */
+struct rte_mtr_params {
+	/**< Meter profile ID. */
+	uint32_t meter_profile_id;
+
+	/**< Policer actions (per meter output color). */
+	enum rte_mtr_policer_action action[RTE_MTR_COLORS];
+
+	/**< Set of stats counters to be enabled. */
+	uint64_t stats_mask;
+};
+
+/**
+ * Verbose error types.
+ *
+ * Most of them provide the type of the object referenced by struct
+ * rte_mtr_error::cause.
+ */
+enum rte_mtr_error_type {
+	RTE_MTR_ERROR_TYPE_NONE, /**< No error. */
+	RTE_MTR_ERROR_TYPE_UNSPECIFIED, /**< Cause unspecified. */
+	RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+	RTE_MTR_ERROR_TYPE_METER_PROFILE,
+	RTE_MTR_ERROR_TYPE_MTR_ID,
+	RTE_MTR_ERROR_TYPE_MTR_PARAMS,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED,
+	RTE_MTR_ERROR_TYPE_STATS_MASK,
+	RTE_MTR_ERROR_TYPE_STATS,
+	RTE_MTR_ERROR_TYPE_SHARED,
+};
+
+/**
+ * Verbose error structure definition.
+ *
+ * This object is normally allocated by applications and set by PMDs, the
+ * message points to a constant string which does not need to be freed by
+ * the application, however its pointer can be considered valid only as long
+ * as its associated DPDK port remains configured. Closing the underlying
+ * device or unloading the PMD invalidates it.
+ *
+ * Both cause and message may be NULL regardless of the error type.
+ */
+struct rte_mtr_error {
+	enum rte_mtr_error_type type; /**< Cause field and error type. */
+	const void *cause; /**< Object responsible for the error. */
+	const char *message; /**< Human-readable error message. */
+};
+
+/**
+ * Meter profile add
+ *
+ * Create a new meter profile with ID set to *meter_profile_id*. 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.
+ */
+int
+rte_mtr_meter_profile_add(uint8_t port_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_meter_profile *profile,
+	struct rte_mtr_error *error);
+
+/**
+ * Meter profile delete
+ *
+ * Delete an existing meter profile. This operation fails when there is
+ * currently at least one user (i.e. MTR object) of this profile.
+ *
+ * @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[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_profile_delete(uint8_t port_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object create
+ *
+ * Create a new MTR object for the current port.
+ *
+ * @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
+ *   Non-zero when this MTR object can be shared by multiple flows, zero when
+ *   this MTR object can be used by a single flow.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_create(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_params *params,
+	int shared,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object destroy
+ *
+ * Delete an existing MTR object. This operation fails when there is currently
+ * at least one user (i.e. flow) of this MTR object.
+ *
+ * @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[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_destroy(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object meter profile 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] meter_profile_id
+ *   Meter profile ID for the current MTR object. Needs to be valid.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_profile_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object policer action update for given color
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be valid.
+ * @param[in] color
+ *   Color for which the policer action is updated.
+ * @param[in] action
+ *   Policer action for specified color.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_policer_action_update(uint8_t port_id,
+	uint32_t mtr_id,
+	enum rte_mtr_color color,
+	enum rte_mtr_policer_action action,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object enabled statistics counters 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] stats_mask
+ *   Mask of statistics counter types to be enabled for the current MTR object.
+ *   Any statistics counter type not included in this set is to be disabled for
+ *   the current MTR object.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_mtr_stats_type
+ */
+int
+rte_mtr_stats_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint64_t stats_mask,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object statistics counters read
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be valid.
+ * @param[out] stats
+ *   When non-NULL, it contains the current value for the statistics counters
+ *   enabled for the current MTR object.
+ * @param[out] stats_mask
+ *   When non-NULL, it contains the mask of statistics counter types that are
+ *   currently enabled for this MTR object, indicating which of the counters
+ *   retrieved with the *stats* structure are valid.
+ * @param[in] clear
+ *   When this parameter has a non-zero value, the statistics counters are
+ *   cleared (i.e. set to zero) immediately after they have been read,
+ *   otherwise the statistics counters are left untouched.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_mtr_stats_type
+ */
+int
+rte_mtr_stats_read(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_RTE_MTR_H__ */
diff --git a/lib/librte_ether/rte_mtr_driver.h b/lib/librte_ether/rte_mtr_driver.h
new file mode 100644
index 0000000..3798cf6
--- /dev/null
+++ b/lib/librte_ether/rte_mtr_driver.h
@@ -0,0 +1,188 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __INCLUDE_RTE_MTR_DRIVER_H__
+#define __INCLUDE_RTE_MTR_DRIVER_H__
+
+/**
+ * @file
+ * RTE Generic Traffic Metering and Policing API (Driver Side)
+ *
+ * This file provides implementation helpers for internal use by PMDs, they
+ * are not intended to be exposed to applications and are not subject to ABI
+ * versioning.
+ */
+
+#include <stdint.h>
+
+#include <rte_errno.h>
+#include "rte_ethdev.h"
+#include "rte_mtr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int (*rte_mtr_meter_profile_add_t)(struct rte_eth_dev *dev,
+	uint32_t meter_profile_id,
+	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_error *error);
+/**< @internal MTR meter profile delete */
+
+typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	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_error *error);
+/**< @internal MTR object destroy */
+
+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_error *error);
+/**< @internal MTR object meter profile update */
+
+typedef int (*rte_mtr_policer_action_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	enum rte_mtr_color color,
+	enum rte_mtr_policer_action action,
+	struct rte_mtr_error *error);
+/**< @internal MTR object policer action update*/
+
+typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	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_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error);
+/**< @internal MTR object stats read */
+
+struct rte_mtr_ops {
+	/** MTR meter profile add */
+	rte_mtr_meter_profile_add_t meter_profile_add;
+
+	/** MTR meter profile delete */
+	rte_mtr_meter_profile_delete_t meter_profile_delete;
+
+	/** MTR object create */
+	rte_mtr_create_t create;
+
+	/** MTR object destroy */
+	rte_mtr_destroy_t destroy;
+
+	/** MTR object meter profile update */
+	rte_mtr_meter_profile_update_t meter_profile_update;
+
+	/** MTR object policer action update */
+	rte_mtr_policer_action_update_t policer_action_update;
+
+	/** MTR object enabled stats update */
+	rte_mtr_stats_update_t stats_update;
+
+	/** MTR object stats read */
+	rte_mtr_stats_read_t stats_read;
+};
+
+/**
+ * Initialize generic error structure.
+ *
+ * This function also sets rte_errno to a given value.
+ *
+ * @param[out] error
+ *   Pointer to error structure (may be NULL).
+ * @param[in] code
+ *   Related error code (rte_errno).
+ * @param[in] type
+ *   Cause field and error type.
+ * @param[in] cause
+ *   Object responsible for the error.
+ * @param[in] message
+ *   Human-readable error message.
+ *
+ * @return
+ *   Error code.
+ */
+static inline int
+rte_mtr_error_set(struct rte_mtr_error *error,
+		   int code,
+		   enum rte_mtr_error_type type,
+		   const void *cause,
+		   const char *message)
+{
+	if (error) {
+		*error = (struct rte_mtr_error){
+			.type = type,
+			.cause = cause,
+			.message = message,
+		};
+	}
+	rte_errno = code;
+	return code;
+}
+
+/**
+ * Get generic traffic metering and policing operations structure from a port
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[out] error
+ *   Error details
+ *
+ * @return
+ *   The traffic metering and policing operations structure associated with
+ *   port_id on success, NULL otherwise.
+ */
+const struct rte_mtr_ops *
+rte_mtr_ops_get(uint8_t port_id, struct rte_mtr_error *error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_RTE_MTR_DRIVER_H__ */
-- 
2.7.4

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

* [RFC 3/3] rte_flow: add new action for traffic metering and policing
  2017-05-30 16:44 [RFC 0/3] rte_mtr: generic ethdev API for metering and policing Cristian Dumitrescu
  2017-05-30 16:44 ` [RFC 1/3] ethdev: add traffic metering and policing ops get API Cristian Dumitrescu
  2017-05-30 16:44 ` [RFC 2/3] ethdev: add new rte_mtr API for traffic metering and policing Cristian Dumitrescu
@ 2017-05-30 16:44 ` Cristian Dumitrescu
  2017-06-01 15:13   ` Adrien Mazarguil
  2 siblings, 1 reply; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-05-30 16:44 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jerin.jacob, hemant.agrawal,
	declan.doherty, keith.wiles

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 lib/librte_ether/rte_flow.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index c47edbc..2942ca7 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -881,6 +881,14 @@ enum rte_flow_action_type {
 	 * See struct rte_flow_action_vf.
 	 */
 	RTE_FLOW_ACTION_TYPE_VF,
+
+	/**
+	 * Traffic metering and policing (MTR).
+	 *
+	 * See struct rte_flow_action_meter.
+	 * See file rte_mtr.h for MTR object configuration.
+	 */
+	RTE_FLOW_ACTION_TYPE_METER,
 };
 
 /**
@@ -974,6 +982,20 @@ struct rte_flow_action_vf {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_METER
+ *
+ * Traffic metering and policing (MTR).
+ *
+ * Packets matched by items of this type can be either dropped or passed to the
+ * next item with their color set by the MTR object.
+ *
+ * Non-terminating by default.
+ */
+struct rte_flow_action_meter {
+	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create(). */
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.7.4

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

* Re: [RFC 3/3] rte_flow: add new action for traffic metering and policing
  2017-05-30 16:44 ` [RFC 3/3] rte_flow: add new action for traffic " Cristian Dumitrescu
@ 2017-06-01 15:13   ` Adrien Mazarguil
  2017-06-06 18:37     ` Dumitrescu, Cristian
  0 siblings, 1 reply; 64+ messages in thread
From: Adrien Mazarguil @ 2017-06-01 15:13 UTC (permalink / raw)
  To: Cristian Dumitrescu
  Cc: dev, thomas, jerin.jacob, hemant.agrawal, declan.doherty, keith.wiles

Hi Cristian,

On Tue, May 30, 2017 at 05:44:13PM +0100, Cristian Dumitrescu wrote:
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> ---
>  lib/librte_ether/rte_flow.h | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> index c47edbc..2942ca7 100644
> --- a/lib/librte_ether/rte_flow.h
> +++ b/lib/librte_ether/rte_flow.h
> @@ -881,6 +881,14 @@ enum rte_flow_action_type {
>  	 * See struct rte_flow_action_vf.
>  	 */
>  	RTE_FLOW_ACTION_TYPE_VF,
> +
> +	/**
> +	 * Traffic metering and policing (MTR).
> +	 *
> +	 * See struct rte_flow_action_meter.
> +	 * See file rte_mtr.h for MTR object configuration.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_METER,
>  };
>  
>  /**
> @@ -974,6 +982,20 @@ struct rte_flow_action_vf {
>  };
>  
>  /**
> + * RTE_FLOW_ACTION_TYPE_METER
> + *
> + * Traffic metering and policing (MTR).
> + *
> + * Packets matched by items of this type can be either dropped or passed to the
> + * next item with their color set by the MTR object.
> + *
> + * Non-terminating by default.
> + */
> +struct rte_flow_action_meter {
> +	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create(). */
> +};
> +
> +/**
>   * Definition of a single action.
>   *
>   * A list of actions is terminated by a END action.

Assuming this action is provided to the underlying PMD, can you describe
what happens next; what is a PMD supposed to do when creating the flow rule
and the impact on its data path?

It looks like mtr_id is arbitrarily set by the user calling
rte_mtr_create(), which means the PMD has to look up the associated MTR
context somehow.

How about making the rte_mtr_create() API return an opaque rte_mtr object
pointer provided back to all API functions as well as through this action
instead, and not leave it up to the user?

-- 
Adrien Mazarguil
6WIND

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

* Re: [RFC 3/3] rte_flow: add new action for traffic metering and policing
  2017-06-01 15:13   ` Adrien Mazarguil
@ 2017-06-06 18:37     ` Dumitrescu, Cristian
  2017-07-10 15:21       ` Adrien Mazarguil
  0 siblings, 1 reply; 64+ messages in thread
From: Dumitrescu, Cristian @ 2017-06-06 18:37 UTC (permalink / raw)
  To: Adrien Mazarguil
  Cc: dev, thomas, jerin.jacob, hemant.agrawal, Doherty, Declan, Wiles, Keith

Hi Adrien,

Thanks for reviewing this proposal.

> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Thursday, June 1, 2017 4:14 PM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Cc: dev@dpdk.org; thomas@monjalon.net;
> jerin.jacob@caviumnetworks.com; hemant.agrawal@nxp.com; Doherty,
> Declan <declan.doherty@intel.com>; Wiles, Keith <keith.wiles@intel.com>
> Subject: Re: [RFC 3/3] rte_flow: add new action for traffic metering and
> policing
> 
> Hi Cristian,
> 
> On Tue, May 30, 2017 at 05:44:13PM +0100, Cristian Dumitrescu wrote:
> > Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> > ---
> >  lib/librte_ether/rte_flow.h | 22 ++++++++++++++++++++++
> >  1 file changed, 22 insertions(+)
> >
> > diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> > index c47edbc..2942ca7 100644
> > --- a/lib/librte_ether/rte_flow.h
> > +++ b/lib/librte_ether/rte_flow.h
> > @@ -881,6 +881,14 @@ enum rte_flow_action_type {
> >  	 * See struct rte_flow_action_vf.
> >  	 */
> >  	RTE_FLOW_ACTION_TYPE_VF,
> > +
> > +	/**
> > +	 * Traffic metering and policing (MTR).
> > +	 *
> > +	 * See struct rte_flow_action_meter.
> > +	 * See file rte_mtr.h for MTR object configuration.
> > +	 */
> > +	RTE_FLOW_ACTION_TYPE_METER,
> >  };
> >
> >  /**
> > @@ -974,6 +982,20 @@ struct rte_flow_action_vf {
> >  };
> >
> >  /**
> > + * RTE_FLOW_ACTION_TYPE_METER
> > + *
> > + * Traffic metering and policing (MTR).
> > + *
> > + * Packets matched by items of this type can be either dropped or passed
> to the
> > + * next item with their color set by the MTR object.
> > + *
> > + * Non-terminating by default.
> > + */
> > +struct rte_flow_action_meter {
> > +	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create().
> */
> > +};
> > +
> > +/**
> >   * Definition of a single action.
> >   *
> >   * A list of actions is terminated by a END action.
> 
> Assuming this action is provided to the underlying PMD, can you describe
> what happens next; what is a PMD supposed to do when creating the flow
> rule
> and the impact on its data path?
> 

Metering is just another flow action that needs to be supported by rte_flow API.

Typically, NICs supporting this action have an array of metering & policing contexts on their data path, which are abstracted as MTR objects in our API.
- rte_mtr_create() configures an MTR object, with no association to any of the known flows yet.
	- On NIC side, the driver configures one of the available metering & policing contexts.
- rte_flow_create() defines the flow (match rule) and its set of actions, with metering & policing as one of the actions.
	- On NIC side, the driver configures a flow/filter for traffic classification/distribution/bifurcation, with the metering & policing context enabled for this flow.

At run-time, any packet matching this flow will execute this action, which involves metering (packet is assigned a color) and policing (packet may be recolored or dropped, as configured), with stats being updated as well.

> It looks like mtr_id is arbitrarily set by the user calling
> rte_mtr_create(), which means the PMD has to look up the associated MTR
> context somehow.
> 
> How about making the rte_mtr_create() API return an opaque rte_mtr
> object
> pointer provided back to all API functions as well as through this action
> instead, and not leave it up to the user?
> 

Of course, it can be done this way as well, but IMHO probably not the best idea from the application perspective. We had a similar discussion when we defined the ethdev traffic management API [1].

Object handles can be integers, void pointers or pointers to opaque structures, and each of these approaches are allowed and used by DPDK APIs. Here is an example why I think using integers for MTR object handle makes the life of the application easier:
- Let's assume we have several actions for a flow (a1, a2, a3, ...).
- When handles are pointers to opaque structures, app typically needs to save all of them in a per flow data structure: struct a1 *p1, struct a2 *p2, struct a3 *p3.
	-This results in increased complexity and size for the app tables, which can be avoided.
- When handles are integers generated by the app as opposed of driver, the app can simply use a single index - let's cal it flow_id - and register it as the handle to each of these flow actions.
	- No more fake tables.
	- No more worries about the pointer being valid in one address space and not valid in another.

There is some handle lookup to be done by the driver, but this is a trivial task,  and checking the validity of the handle (input parameter) is the first thing done by any API function, regardless of which handle style is used.

[1] http://www.dpdk.org/ml/archives/dev/2017-February/057368.html


> --
> Adrien Mazarguil
> 6WIND

Regards,
Cristian

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

* Re: [RFC 3/3] rte_flow: add new action for traffic metering and policing
  2017-06-06 18:37     ` Dumitrescu, Cristian
@ 2017-07-10 15:21       ` Adrien Mazarguil
  2017-07-12 18:06         ` Dumitrescu, Cristian
  0 siblings, 1 reply; 64+ messages in thread
From: Adrien Mazarguil @ 2017-07-10 15:21 UTC (permalink / raw)
  To: Dumitrescu, Cristian
  Cc: dev, thomas, jerin.jacob, hemant.agrawal, Doherty, Declan, Wiles, Keith

Hi Cristian,

Took me a while to reply and I didn't see any update in the meantime, is
this RFC still relevant?

More comments below.

On Tue, Jun 06, 2017 at 06:37:57PM +0000, Dumitrescu, Cristian wrote:
> Hi Adrien,
> 
> Thanks for reviewing this proposal.
> 
> > -----Original Message-----
> > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > Sent: Thursday, June 1, 2017 4:14 PM
> > To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> > Cc: dev@dpdk.org; thomas@monjalon.net;
> > jerin.jacob@caviumnetworks.com; hemant.agrawal@nxp.com; Doherty,
> > Declan <declan.doherty@intel.com>; Wiles, Keith <keith.wiles@intel.com>
> > Subject: Re: [RFC 3/3] rte_flow: add new action for traffic metering and
> > policing
> > 
> > Hi Cristian,
> > 
> > On Tue, May 30, 2017 at 05:44:13PM +0100, Cristian Dumitrescu wrote:
> > > Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> > > ---
> > >  lib/librte_ether/rte_flow.h | 22 ++++++++++++++++++++++
> > >  1 file changed, 22 insertions(+)
> > >
> > > diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> > > index c47edbc..2942ca7 100644
> > > --- a/lib/librte_ether/rte_flow.h
> > > +++ b/lib/librte_ether/rte_flow.h
> > > @@ -881,6 +881,14 @@ enum rte_flow_action_type {
> > >  	 * See struct rte_flow_action_vf.
> > >  	 */
> > >  	RTE_FLOW_ACTION_TYPE_VF,
> > > +
> > > +	/**
> > > +	 * Traffic metering and policing (MTR).
> > > +	 *
> > > +	 * See struct rte_flow_action_meter.
> > > +	 * See file rte_mtr.h for MTR object configuration.
> > > +	 */
> > > +	RTE_FLOW_ACTION_TYPE_METER,
> > >  };
> > >
> > >  /**
> > > @@ -974,6 +982,20 @@ struct rte_flow_action_vf {
> > >  };
> > >
> > >  /**
> > > + * RTE_FLOW_ACTION_TYPE_METER
> > > + *
> > > + * Traffic metering and policing (MTR).
> > > + *
> > > + * Packets matched by items of this type can be either dropped or passed
> > to the
> > > + * next item with their color set by the MTR object.
> > > + *
> > > + * Non-terminating by default.
> > > + */
> > > +struct rte_flow_action_meter {
> > > +	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create().
> > */
> > > +};
> > > +
> > > +/**
> > >   * Definition of a single action.
> > >   *
> > >   * A list of actions is terminated by a END action.
> > 
> > Assuming this action is provided to the underlying PMD, can you describe
> > what happens next; what is a PMD supposed to do when creating the flow
> > rule
> > and the impact on its data path?
> > 
> 
> Metering is just another flow action that needs to be supported by rte_flow API.
> 
> Typically, NICs supporting this action have an array of metering & policing contexts on their data path, which are abstracted as MTR objects in our API.
> - rte_mtr_create() configures an MTR object, with no association to any of the known flows yet.
> 	- On NIC side, the driver configures one of the available metering & policing contexts.
> - rte_flow_create() defines the flow (match rule) and its set of actions, with metering & policing as one of the actions.
> 	- On NIC side, the driver configures a flow/filter for traffic classification/distribution/bifurcation, with the metering & policing context enabled for this flow.
> 
> At run-time, any packet matching this flow will execute this action, which involves metering (packet is assigned a color) and policing (packet may be recolored or dropped, as configured), with stats being updated as well.

Thanks, this description should be part of the documentation in the final
patch. The relationship between rte_mtr and rte_flow objects must be
described as well, for instance making clear that one cannot remove a mtr
object if a flow rule depends on it.

> > It looks like mtr_id is arbitrarily set by the user calling
> > rte_mtr_create(), which means the PMD has to look up the associated MTR
> > context somehow.
> > 
> > How about making the rte_mtr_create() API return an opaque rte_mtr
> > object
> > pointer provided back to all API functions as well as through this action
> > instead, and not leave it up to the user?
> > 
> 
> Of course, it can be done this way as well, but IMHO probably not the best idea from the application perspective. We had a similar discussion when we defined the ethdev traffic management API [1].
> 
> Object handles can be integers, void pointers or pointers to opaque structures, and each of these approaches are allowed and used by DPDK APIs. Here is an example why I think using integers for MTR object handle makes the life of the application easier:
> - Let's assume we have several actions for a flow (a1, a2, a3, ...).
> - When handles are pointers to opaque structures, app typically needs to save all of them in a per flow data structure: struct a1 *p1, struct a2 *p2, struct a3 *p3.
> 	-This results in increased complexity and size for the app tables, which can be avoided.
> - When handles are integers generated by the app as opposed of driver, the app can simply use a single index - let's cal it flow_id - and register it as the handle to each of these flow actions.
> 	- No more fake tables.
> 	- No more worries about the pointer being valid in one address space and not valid in another.
> 
> There is some handle lookup to be done by the driver, but this is a trivial task,  and checking the validity of the handle (input parameter) is the first thing done by any API function, regardless of which handle style is used.

All this sounds reasonable from the control plane standpoint. My comment was
more generally besides the above rte_flow action, are we sure mtr_id will
never be used to perform actions from the data plane?

Otherwise driver lookup is perhaps a trivial task but is nonetheless
expensive. This step can be avoided if mtr_id contains enough information to
locate the related object as fast as possible inside the PMD without the
need for an intermediate lookup table.

In which case, making mtr_id a pointer-sized opaque value (e.g. uintptr_t)
provided by the PMD when calling rte_mtr_create() gives more flexibility to
the PMD. For some, a basic index value could be enough while for others, an
intermediate structure could be necessary.

Admittedly this is exactly the same as a pointer type to an opaque object,
address space-related issues would have to be managed by the PMD either
way. Applications are not supposed to dereference such objects.

> [1] http://www.dpdk.org/ml/archives/dev/2017-February/057368.html

-- 
Adrien Mazarguil
6WIND

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

* Re: [RFC 3/3] rte_flow: add new action for traffic metering and policing
  2017-07-10 15:21       ` Adrien Mazarguil
@ 2017-07-12 18:06         ` Dumitrescu, Cristian
  0 siblings, 0 replies; 64+ messages in thread
From: Dumitrescu, Cristian @ 2017-07-12 18:06 UTC (permalink / raw)
  To: Adrien Mazarguil
  Cc: dev, thomas, jerin.jacob, hemant.agrawal, Doherty, Declan, Wiles, Keith

Hi Adrien,

> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Monday, July 10, 2017 4:21 PM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Cc: dev@dpdk.org; thomas@monjalon.net;
> jerin.jacob@caviumnetworks.com; hemant.agrawal@nxp.com; Doherty,
> Declan <declan.doherty@intel.com>; Wiles, Keith <keith.wiles@intel.com>
> Subject: Re: [RFC 3/3] rte_flow: add new action for traffic metering and
> policing
> 
> Hi Cristian,
> 
> Took me a while to reply and I didn't see any update in the meantime, is
> this RFC still relevant?

Yes, absolutely!

> 
> More comments below.
> 

Thanks for continuing to look into this! I am actively looking for partners to evolve this API further and make it a good fit for DPDK devices. Now that Traffic Management API got merged, I can hopefully come back and spend more time on this.

> On Tue, Jun 06, 2017 at 06:37:57PM +0000, Dumitrescu, Cristian wrote:
> > Hi Adrien,
> >
> > Thanks for reviewing this proposal.
> >
> > > -----Original Message-----
> > > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > > Sent: Thursday, June 1, 2017 4:14 PM
> > > To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> > > Cc: dev@dpdk.org; thomas@monjalon.net;
> > > jerin.jacob@caviumnetworks.com; hemant.agrawal@nxp.com; Doherty,
> > > Declan <declan.doherty@intel.com>; Wiles, Keith
> <keith.wiles@intel.com>
> > > Subject: Re: [RFC 3/3] rte_flow: add new action for traffic metering and
> > > policing
> > >
> > > Hi Cristian,
> > >
> > > On Tue, May 30, 2017 at 05:44:13PM +0100, Cristian Dumitrescu wrote:
> > > > Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> > > > ---
> > > >  lib/librte_ether/rte_flow.h | 22 ++++++++++++++++++++++
> > > >  1 file changed, 22 insertions(+)
> > > >
> > > > diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> > > > index c47edbc..2942ca7 100644
> > > > --- a/lib/librte_ether/rte_flow.h
> > > > +++ b/lib/librte_ether/rte_flow.h
> > > > @@ -881,6 +881,14 @@ enum rte_flow_action_type {
> > > >  	 * See struct rte_flow_action_vf.
> > > >  	 */
> > > >  	RTE_FLOW_ACTION_TYPE_VF,
> > > > +
> > > > +	/**
> > > > +	 * Traffic metering and policing (MTR).
> > > > +	 *
> > > > +	 * See struct rte_flow_action_meter.
> > > > +	 * See file rte_mtr.h for MTR object configuration.
> > > > +	 */
> > > > +	RTE_FLOW_ACTION_TYPE_METER,
> > > >  };
> > > >
> > > >  /**
> > > > @@ -974,6 +982,20 @@ struct rte_flow_action_vf {
> > > >  };
> > > >
> > > >  /**
> > > > + * RTE_FLOW_ACTION_TYPE_METER
> > > > + *
> > > > + * Traffic metering and policing (MTR).
> > > > + *
> > > > + * Packets matched by items of this type can be either dropped or
> passed
> > > to the
> > > > + * next item with their color set by the MTR object.
> > > > + *
> > > > + * Non-terminating by default.
> > > > + */
> > > > +struct rte_flow_action_meter {
> > > > +	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create().
> > > */
> > > > +};
> > > > +
> > > > +/**
> > > >   * Definition of a single action.
> > > >   *
> > > >   * A list of actions is terminated by a END action.
> > >
> > > Assuming this action is provided to the underlying PMD, can you describe
> > > what happens next; what is a PMD supposed to do when creating the
> flow
> > > rule
> > > and the impact on its data path?
> > >
> >
> > Metering is just another flow action that needs to be supported by
> rte_flow API.
> >
> > Typically, NICs supporting this action have an array of metering & policing
> contexts on their data path, which are abstracted as MTR objects in our API.
> > - rte_mtr_create() configures an MTR object, with no association to any of
> the known flows yet.
> > 	- On NIC side, the driver configures one of the available metering &
> policing contexts.
> > - rte_flow_create() defines the flow (match rule) and its set of actions,
> with metering & policing as one of the actions.
> > 	- On NIC side, the driver configures a flow/filter for traffic
> classification/distribution/bifurcation, with the metering & policing context
> enabled for this flow.
> >
> > At run-time, any packet matching this flow will execute this action, which
> involves metering (packet is assigned a color) and policing (packet may be
> recolored or dropped, as configured), with stats being updated as well.
> 
> Thanks, this description should be part of the documentation in the final
> patch. The relationship between rte_mtr and rte_flow objects must be
> described as well, for instance making clear that one cannot remove a mtr
> object if a flow rule depends on it.
> 

Yes, took the note to document this. Will expand this is Doxygen as well.

> > > It looks like mtr_id is arbitrarily set by the user calling
> > > rte_mtr_create(), which means the PMD has to look up the associated
> MTR
> > > context somehow.
> > >
> > > How about making the rte_mtr_create() API return an opaque rte_mtr
> > > object
> > > pointer provided back to all API functions as well as through this action
> > > instead, and not leave it up to the user?
> > >
> >
> > Of course, it can be done this way as well, but IMHO probably not the best
> idea from the application perspective. We had a similar discussion when we
> defined the ethdev traffic management API [1].
> >
> > Object handles can be integers, void pointers or pointers to opaque
> structures, and each of these approaches are allowed and used by DPDK
> APIs. Here is an example why I think using integers for MTR object handle
> makes the life of the application easier:
> > - Let's assume we have several actions for a flow (a1, a2, a3, ...).
> > - When handles are pointers to opaque structures, app typically needs to
> save all of them in a per flow data structure: struct a1 *p1, struct a2 *p2,
> struct a3 *p3.
> > 	-This results in increased complexity and size for the app tables,
> which can be avoided.
> > - When handles are integers generated by the app as opposed of driver,
> the app can simply use a single index - let's cal it flow_id - and register it as
> the handle to each of these flow actions.
> > 	- No more fake tables.
> > 	- No more worries about the pointer being valid in one address space
> and not valid in another.
> >
> > There is some handle lookup to be done by the driver, but this is a trivial
> task,  and checking the validity of the handle (input parameter) is the first
> thing done by any API function, regardless of which handle style is used.
> 
> All this sounds reasonable from the control plane standpoint. My comment
> was
> more generally besides the above rte_flow action, are we sure mtr_id will
> never be used to perform actions from the data plane?
> 

Yes, we are sure. This object ID is just used for configuration.

Even for the SW fall-back case (see the librte_meter) this ID is not used on data path. When flow is added with this action, the meter context is simply initialized in the flow table entry and used directly from here, no lookup takes place on data path.

> Otherwise driver lookup is perhaps a trivial task but is nonetheless
> expensive. This step can be avoided if mtr_id contains enough information to
> locate the related object as fast as possible inside the PMD without the
> need for an intermediate lookup table.
> 

Yes, agreed, any ID lookup/translation on data path is expensive and has to be avoided. As stated above, there is no ID lookup/translation on the data path to be performed here.

> In which case, making mtr_id a pointer-sized opaque value (e.g. uintptr_t)
> provided by the PMD when calling rte_mtr_create() gives more flexibility to
> the PMD. For some, a basic index value could be enough while for others, an
> intermediate structure could be necessary.
> 
> Admittedly this is exactly the same as a pointer type to an opaque object,
> address space-related issues would have to be managed by the PMD either
> way. Applications are not supposed to dereference such objects.
> 

Yes, these are the typical methods to avoid any ID lookup/translation on data path, but not needed here.

> > [1] http://www.dpdk.org/ml/archives/dev/2017-February/057368.html
> 
> --
> Adrien Mazarguil
> 6WIND

Regards,
Cristian

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

* [PATCH 0/3] rte_mtr: generic ethdev API for metering and policing
  2017-05-30 16:44 ` [RFC 2/3] ethdev: add new rte_mtr API for traffic metering and policing Cristian Dumitrescu
@ 2017-08-26  0:06   ` Cristian Dumitrescu
  2017-08-26  0:06     ` [PATCH 1/3] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
                       ` (3 more replies)
  0 siblings, 4 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-08-26  0:06 UTC (permalink / raw)
  To: dev; +Cc: thomas, adrien.mazarguil, jerin.jacob, hemant.agrawal

This patch set introduces an ethdev-based generic API for Traffic
Metering and Policing (MTR), which is yet another standard RX offload for
Ethernet devices.

Similar to rte_flow and rte_tm APIs, the configuration of MTR objects is
done in their own namespace (rte_mtr) within the librte_ether library.
Metering and policing action typically sits on top of flow classification,
which is why MTR objects are enabled through a newly introduced rte_flow
action, which is the only impact to rte_flow API.

Q1: Why introduce ethdev-based traffic metering ad policing API?
A1: Traffic metering and policing is a standard RX offload for Ethernet
devices present in NICs, SoCs and NPUs across the industry.

Q2: What's the connection between the new rte_mtr API and the existing
librte_meter library?
A2: The existing librte_meter library provides a SW implementation for a
subset of the features exposed by this API. The rte_mtr API is agnostic to
whether the implementation is HW, SW or mixed HW-SW.

Q3: What's the connection between the new rte_mtr API and the existing
rte_flow API?
A3: The MTR object is hooked into ethdev RX processing path using a newly
introduced rte_flow action, which is the only impact to the rte_flow API.
The configuration of MTR objects is done in separate namespace (rte_mtr)
outside of rte_flow API.

Q4: Can the new rte_flow meter action drop packets? Is this a terminating
action or not?
A4: Although packets can be dropped by the newly introduced rte_flow meter
action, this action is non-terminating, i.e. the action list typically
contains at least one more action, which is a terminating action.
Depending on the policer actions configured for the MTR object, some
packets might be dropped while some packets passed to the next flow action
with their color set in the packet mbuf. For example, a typical policer
configuration is to drop the red packets while passing the green packets,
therefore a subsequent rte_flow action needs to be configured to determine
the final destination of green packets.

Q5: Which are the main operations exposed for the MTR object?
A5: Traffic metering, policing and statistics update. Traffic metering
determines the color for the current packet (green, yellow, red) based on
the previous history for this flow as maintained by the MTR object.
The policer can do nothing, recolor or drop the packet. Stats are
maintained for MTR object, as configured.

Q6: Where is the output color stored for the current packet.
A6: struct rte_mbuf::sched::color.

Q7: Which are the supported metering algorithms?
A7: srTCM (RFC 2697), trTCM (RFC 2698).

Q8: Which are the supported policer actions?
A8: Recolor the packet (keep or change the color determined by metering)
or drop the packet.

Cristian Dumitrescu (3):
  ethdev: add new eth_dev_ops function for mtr ops get
  ethdev: add new rte_mtr API for traffic metering and policing
  rte_flow: add new action for traffic metering and policing

 MAINTAINERS                            |   4 +
 doc/api/doxy-api-index.md              |   1 +
 lib/librte_ether/Makefile              |   5 +-
 lib/librte_ether/rte_ethdev.h          |   6 +
 lib/librte_ether/rte_ether_version.map |  15 ++
 lib/librte_ether/rte_flow.h            |  22 ++
 lib/librte_ether/rte_mtr.c             | 184 +++++++++++++
 lib/librte_ether/rte_mtr.h             | 471 +++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_mtr_driver.h      | 188 +++++++++++++
 9 files changed, 895 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_ether/rte_mtr.c
 create mode 100644 lib/librte_ether/rte_mtr.h
 create mode 100644 lib/librte_ether/rte_mtr_driver.h

-- 
2.7.4

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

* [PATCH 1/3] ethdev: add new eth_dev_ops function for mtr ops get
  2017-08-26  0:06   ` [PATCH 0/3] rte_mtr: generic ethdev API for " Cristian Dumitrescu
@ 2017-08-26  0:06     ` Cristian Dumitrescu
  2017-09-13  5:50       ` Jerin Jacob
  2017-10-05 13:09       ` [PATCH V2 0/5] rte_mtr: generic ethdev api for metering and policing Cristian Dumitrescu
  2017-08-26  0:06     ` [PATCH 2/3] ethdev: add new rte_mtr API " Cristian Dumitrescu
                       ` (2 subsequent siblings)
  3 siblings, 2 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-08-26  0:06 UTC (permalink / raw)
  To: dev; +Cc: thomas, adrien.mazarguil, jerin.jacob, hemant.agrawal

Following similar approach to rte_flow and rte_tm for modularity reasons.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
Changes in v1 (from RFC [1]):
- Removed ethdev API function to get the MTR ops, as it is not needed
  (input from Thomas)

[1] RFC: http://www.dpdk.org/ml/archives/dev/2017-May/066888.html

 lib/librte_ether/rte_ethdev.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 0adf327..361c9bd 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1421,6 +1421,9 @@ typedef int (*eth_filter_ctrl_t)(struct rte_eth_dev *dev,
 typedef int (*eth_tm_ops_get_t)(struct rte_eth_dev *dev, void *ops);
 /**< @internal Get Traffic Management (TM) operations on an Ethernet device */
 
+typedef int (*eth_mtr_ops_get_t)(struct rte_eth_dev *dev, void *ops);
+/**< @internal Get Trafffic Metering and Policing (MTR) operations */
+
 typedef int (*eth_get_dcb_info)(struct rte_eth_dev *dev,
 				 struct rte_eth_dcb_info *dcb_info);
 /**< @internal Get dcb information on an Ethernet device */
@@ -1544,6 +1547,9 @@ struct eth_dev_ops {
 
 	eth_tm_ops_get_t tm_ops_get;
 	/**< Get Traffic Management (TM) operations. */
+
+	eth_mtr_ops_get_t mtr_ops_get;
+	/**< Get Traffic Metering and Policing (MTR) operations. */
 };
 
 /**
-- 
2.7.4

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

* [PATCH 2/3] ethdev: add new rte_mtr API for traffic metering and policing
  2017-08-26  0:06   ` [PATCH 0/3] rte_mtr: generic ethdev API for " Cristian Dumitrescu
  2017-08-26  0:06     ` [PATCH 1/3] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
@ 2017-08-26  0:06     ` Cristian Dumitrescu
  2017-09-01  8:09       ` Hemant Agrawal
  2017-09-21 13:20       ` Thomas Monjalon
  2017-08-26  0:06     ` [PATCH 3/3] rte_flow: add new action " Cristian Dumitrescu
  2017-09-21 13:28     ` [PATCH 0/3] rte_mtr: generic ethdev API for " Thomas Monjalon
  3 siblings, 2 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-08-26  0:06 UTC (permalink / raw)
  To: dev; +Cc: thomas, adrien.mazarguil, jerin.jacob, hemant.agrawal

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
Changes in v1 (from RFC [1]):
- Added EXPERIMENTAL tag in rte_mtr.h and MANTAINERS for this new API
  (input from Thomas)
- Added more Doxygen comments to re-inforce relationship between MTR and
  flow (input from Adrien)
- Added Doxygen hook in doxy-api-index.md

[1] RFC: http://www.dpdk.org/ml/archives/dev/2017-May/066888.html

 MAINTAINERS                            |   4 +
 doc/api/doxy-api-index.md              |   1 +
 lib/librte_ether/Makefile              |   5 +-
 lib/librte_ether/rte_ether_version.map |  15 ++
 lib/librte_ether/rte_mtr.c             | 184 +++++++++++++
 lib/librte_ether/rte_mtr.h             | 471 +++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_mtr_driver.h      | 188 +++++++++++++
 7 files changed, 867 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_ether/rte_mtr.c
 create mode 100644 lib/librte_ether/rte_mtr.h
 create mode 100644 lib/librte_ether/rte_mtr_driver.h

diff --git a/MAINTAINERS b/MAINTAINERS
index a0cd75e..5491906 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -257,6 +257,10 @@ M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
 T: git://dpdk.org/next/dpdk-next-tm
 F: lib/librte_ether/rte_tm*
 
+Traffic Metering and Policing API - EXPERIMENTAL
+M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
+F: lib/librte_ether/rte_mtr*
+
 Crypto API
 M: Declan Doherty <declan.doherty@intel.com>
 F: lib/librte_cryptodev/
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 19e0d4f..b2342a9 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -41,6 +41,7 @@ The public API headers are grouped by topics:
   [ethctrl]            (@ref rte_eth_ctrl.h),
   [rte_flow]           (@ref rte_flow.h),
   [rte_tm]             (@ref rte_tm.h),
+  [rte_mtr]            (@ref rte_mtr.h),
   [cryptodev]          (@ref rte_cryptodev.h),
   [eventdev]           (@ref rte_eventdev.h),
   [metrics]            (@ref rte_metrics.h),
diff --git a/lib/librte_ether/Makefile b/lib/librte_ether/Makefile
index db692ae..e4e339d 100644
--- a/lib/librte_ether/Makefile
+++ b/lib/librte_ether/Makefile
@@ -41,11 +41,12 @@ CFLAGS += $(WERROR_FLAGS)
 
 EXPORT_MAP := rte_ether_version.map
 
-LIBABIVER := 6
+LIBABIVER := 7
 
 SRCS-y += rte_ethdev.c
 SRCS-y += rte_flow.c
 SRCS-y += rte_tm.c
+SRCS-y += rte_mtr.c
 
 #
 # Export include files
@@ -59,5 +60,7 @@ SYMLINK-y-include += rte_flow.h
 SYMLINK-y-include += rte_flow_driver.h
 SYMLINK-y-include += rte_tm.h
 SYMLINK-y-include += rte_tm_driver.h
+SYMLINK-y-include += rte_mtr.h
+SYMLINK-y-include += rte_mtr_driver.h
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index 4283728..7192664 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -187,3 +187,18 @@ DPDK_17.08 {
 	rte_tm_wred_profile_delete;
 
 } DPDK_17.05;
+
+DPDK_17.11 {
+	global:
+
+	rte_eth_dev_mtr_ops_get;
+	rte_mtr_meter_profile_add;
+	rte_mtr_meter_profile_delete;
+	rte_mtr_create;
+	rte_mtr_destroy;
+	rte_mtr_meter_profile_update;
+	rte_mtr_policer_action_update;
+	rte_mtr_stats_update;
+	rte_mtr_stats_read;
+
+} DPDK_17.08;
diff --git a/lib/librte_ether/rte_mtr.c b/lib/librte_ether/rte_mtr.c
new file mode 100644
index 0000000..efbe7fb
--- /dev/null
+++ b/lib/librte_ether/rte_mtr.c
@@ -0,0 +1,184 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+
+#include <rte_errno.h>
+#include "rte_ethdev.h"
+#include "rte_mtr_driver.h"
+#include "rte_mtr.h"
+
+/* Get generic traffic metering and policing operations structure from a port. */
+const struct rte_mtr_ops *
+rte_mtr_ops_get(uint8_t port_id, struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	const struct rte_mtr_ops *ops;
+
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		rte_mtr_error_set(error,
+			ENODEV,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			rte_strerror(ENODEV));
+		return NULL;
+	}
+
+	if ((dev->dev_ops->mtr_ops_get == NULL) ||
+		(dev->dev_ops->mtr_ops_get(dev, &ops) != 0) ||
+		(ops == NULL)) {
+		rte_mtr_error_set(error,
+			ENOSYS,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			rte_strerror(ENOSYS));
+		return NULL;
+	}
+
+	return ops;
+}
+
+#define RTE_MTR_FUNC(port_id, func)			\
+({							\
+	const struct rte_mtr_ops *ops =			\
+		rte_mtr_ops_get(port_id, error);		\
+	if (ops == NULL)					\
+		return -rte_errno;			\
+							\
+	if (ops->func == NULL)				\
+		return -rte_mtr_error_set(error,		\
+			ENOSYS,				\
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,	\
+			NULL,				\
+			rte_strerror(ENOSYS));		\
+							\
+	ops->func;					\
+})
+
+/* MTR meter profile add */
+int
+rte_mtr_meter_profile_add(uint8_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);
+}
+
+/** MTR meter profile delete */
+int
+rte_mtr_meter_profile_delete(uint8_t port_id,
+	uint32_t meter_profile_id,
+	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);
+}
+
+/** MTR object create */
+int
+rte_mtr_create(uint8_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);
+}
+
+/** MTR object destroy */
+int
+rte_mtr_destroy(uint8_t port_id,
+	uint32_t mtr_id,
+	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 object meter profile update */
+int
+rte_mtr_meter_profile_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint32_t meter_profile_id,
+	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 object policer action update */
+int
+rte_mtr_policer_action_update(uint8_t port_id,
+	uint32_t mtr_id,
+	enum rte_mtr_color color,
+	enum rte_mtr_policer_action action,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, policer_action_update)(dev,
+		mtr_id, color, action, error);
+}
+
+/** MTR object enabled stats update */
+int
+rte_mtr_stats_update(uint8_t port_id,
+	uint32_t mtr_id,
+	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 object stats read */
+int
+rte_mtr_stats_read(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error)
+{
+	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);
+}
diff --git a/lib/librte_ether/rte_mtr.h b/lib/librte_ether/rte_mtr.h
new file mode 100644
index 0000000..d15cb9f
--- /dev/null
+++ b/lib/librte_ether/rte_mtr.h
@@ -0,0 +1,471 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __INCLUDE_RTE_MTR_H__
+#define __INCLUDE_RTE_MTR_H__
+
+/**
+ * @file
+ * RTE Generic Traffic Metering and Policing API
+ *
+ * This interface provides the ability to configure the traffic metering and
+ * policing (MTR) in a generic way.
+ *
+ * The processing done for each input packet hitting a MTR object is:
+ *    A) Traffic metering: The packet is assigned a color (the meter output
+ *       color), based on the previous history of the flow reflected in the
+ *       current state of the MTR object, according to the specific traffic
+ *       metering algorithm. The traffic metering algorithm can typically work
+ *       in color aware mode, in which case the input packet already has an
+ *       initial color (the input color), or in color blind mode, which is
+ *       equivalent to considering all input packets initially colored as green.
+ *    B) Policing: There is a separate policer action configured for each meter
+ *       output color, which can:
+ *          a) Drop the packet.
+ *          b) Keep the same packet color: the policer output color matches the
+ *             meter output color (essentially a no-op action).
+ *          c) Recolor the packet: the policer output color is different 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).
+ *    C) Statistics: The set of counters maintained for each MTR object is
+ *       configurable and subject to the implementation support. This set
+ *       includes the number of packets and bytes dropped or passed for each
+ *       output color.
+ *
+ * Once successfully created, an MTR object is linked to one or several flows
+ * through the meter action of the flow API.
+ *    A) Whether an MTR object is private to a flow or potentially shared by
+ *       several flows has to be specified at creation time.
+ *    B) Several meter actions can be potentially registered for the same flow.
+ *
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ */
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Color
+ */
+enum rte_mtr_color {
+	RTE_MTR_GREEN = 0, /**< Green */
+	RTE_MTR_YELLOW, /**< Yellow */
+	RTE_MTR_RED, /**< Red */
+	RTE_MTR_COLORS /**< Number of colors */
+};
+
+/**
+ * Statistics counter type
+ */
+enum rte_mtr_stats_type {
+	/**< Number of packets passed as green by the policer.  */
+	RTE_MTR_STATS_N_PKTS_GREEN = 1 << 0,
+
+	/**< Number of bytes passed as green by the policer.  */
+	RTE_MTR_STATS_N_BYTES_GREEN = 1 << 1,
+
+	/**< Number of packets passed as yellow by the policer.  */
+	RTE_MTR_STATS_N_PKTS_YELLOW = 1 << 2,
+
+	/**< Number of bytes passed as yellow by the policer.  */
+	RTE_MTR_STATS_N_BYTES_YELLOW = 1 << 3,
+
+	/**< Number of packets passed as red by the policer.  */
+	RTE_MTR_STATS_N_PKTS_RED = 1 << 4,
+
+	/**< Number of bytes passed as red by the policer.  */
+	RTE_MTR_STATS_N_BYTES_RED = 1 << 5,
+
+	/**< Number of packets dropped by the policer.  */
+	RTE_MTR_STATS_N_PKTS_DROPPED = 1 << 6,
+
+	/**< Number of bytes dropped by the policer.  */
+	RTE_MTR_STATS_N_BYTES_DROPPED = 1 << 7,
+};
+
+/**
+ * Statistics counters
+ */
+struct rte_mtr_stats {
+	/**< Number of packets passed by the policer (per color). */
+	uint64_t n_pkts[RTE_MTR_COLORS];
+
+	/**< Number of bytes passed by the policer (per color). */
+	uint64_t n_bytes[RTE_MTR_COLORS];
+
+	/**< Number of packets dropped by the policer. */
+	uint64_t n_pkts_dropped;
+
+	/**< Number of bytes passed by the policer. */
+	uint64_t n_bytes_dropped;
+};
+
+/**
+ * Traffic metering algorithms
+ */
+enum rte_mtr_algorithm {
+	/**< Single Rate Three Color Marker (srTCM) - IETF RFC 2697. */
+	RTE_MTR_SRTCM_RFC2697 = 0,
+
+	/**< Two Rate Three Color Marker (trTCM) - IETF RFC 2698. */
+	RTE_MTR_TRTCM_RFC2698,
+};
+
+/**
+ * Meter profile
+ */
+struct rte_mtr_meter_profile {
+	/**<  Traffic metering algorithm. */
+	enum rte_mtr_algorithm alg;
+
+	union {
+		/**< Items only valid when *alg* is set to srTCM - RFC2697. */
+		struct {
+			/**< Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/**< Committed Burst Size (CBS) (bytes). */
+			uint64_t cbs;
+
+			/**< Excess Burst Size (EBS) (bytes). */
+			uint64_t ebs;
+
+			/**< Non-zero for color aware mode, zero for color blind
+			 * mode. In color aware mode, the packet input color is
+			 * read from the IPv4/IPv6 DSCP field, as defined by
+			 * IETF RFC 2597 (low/medium/high drop precedence
+			 * translates to green/yellow/red color respectively).
+			 */
+			int color_aware;
+		} srtcm_rfc2697;
+
+		/**< Items only valid when *alg* is set to trTCM - RFC2698. */
+		struct {
+			/**< Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/**< Peak Information Rate (PIR) (bytes/second). */
+			uint64_t pir;
+
+			/**< Committed Burst Size (CBS) (byes). */
+			uint64_t cbs;
+
+			/**< Peak Burst Size (PBS) (bytes). */
+			uint64_t pbs;
+
+			/**< Non-zero for color aware mode, zero for color blind
+			 * mode. In color aware mode, the packet input color is
+			 * read from the IPv4/IPv6 DSCP field, as defined by
+			 * IETF RFC 2597 (low/medium/high drop precedence
+			 * translates to green/yellow/red color respectively).
+			 */
+			int color_aware;
+		} trtcm_rfc2698;
+	};
+};
+
+/**
+ * Policer actions
+ */
+enum rte_mtr_policer_action {
+	/**< Recolor the packet as green. */
+	e_MTR_POLICER_ACTION_COLOR_GREEN = 0,
+
+	/**< Recolor the packet as yellow. */
+	e_MTR_POLICER_ACTION_COLOR_YELLOW,
+
+	/**< Recolor the packet as red. */
+	e_MTR_POLICER_ACTION_COLOR_RED,
+
+	/**< Drop the packet. */
+	e_MTR_POLICER_ACTION_DROP,
+};
+
+/**
+ * Parameters for each traffic metering & policing object
+ *
+ * @see enum rte_mtr_stats_type
+ */
+struct rte_mtr_params {
+	/**< Meter profile ID. */
+	uint32_t meter_profile_id;
+
+	/**< Policer actions (per meter output color). */
+	enum rte_mtr_policer_action action[RTE_MTR_COLORS];
+
+	/**< Set of stats counters to be enabled. */
+	uint64_t stats_mask;
+};
+
+/**
+ * Verbose error types.
+ *
+ * Most of them provide the type of the object referenced by struct
+ * rte_mtr_error::cause.
+ */
+enum rte_mtr_error_type {
+	RTE_MTR_ERROR_TYPE_NONE, /**< No error. */
+	RTE_MTR_ERROR_TYPE_UNSPECIFIED, /**< Cause unspecified. */
+	RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+	RTE_MTR_ERROR_TYPE_METER_PROFILE,
+	RTE_MTR_ERROR_TYPE_MTR_ID,
+	RTE_MTR_ERROR_TYPE_MTR_PARAMS,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED,
+	RTE_MTR_ERROR_TYPE_STATS_MASK,
+	RTE_MTR_ERROR_TYPE_STATS,
+	RTE_MTR_ERROR_TYPE_SHARED,
+};
+
+/**
+ * Verbose error structure definition.
+ *
+ * This object is normally allocated by applications and set by PMDs, the
+ * message points to a constant string which does not need to be freed by
+ * the application, however its pointer can be considered valid only as long
+ * as its associated DPDK port remains configured. Closing the underlying
+ * device or unloading the PMD invalidates it.
+ *
+ * Both cause and message may be NULL regardless of the error type.
+ */
+struct rte_mtr_error {
+	enum rte_mtr_error_type type; /**< Cause field and error type. */
+	const void *cause; /**< Object responsible for the error. */
+	const char *message; /**< Human-readable error message. */
+};
+
+/**
+ * Meter profile add
+ *
+ * Create a new meter profile with ID set to *meter_profile_id*. 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.
+ */
+int
+rte_mtr_meter_profile_add(uint8_t port_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_meter_profile *profile,
+	struct rte_mtr_error *error);
+
+/**
+ * Meter profile delete
+ *
+ * Delete an existing meter profile. This operation fails when there is
+ * currently at least one user (i.e. MTR object) of this profile.
+ *
+ * @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[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_profile_delete(uint8_t port_id,
+	uint32_t meter_profile_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
+ * associated flow action for traffic metering and policing.
+ *
+ * @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
+ *   Non-zero when this MTR object can be shared by multiple flows, zero when
+ *   this MTR object can be used by a single flow.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_flow_action_type::RTE_FLOW_ACTION_TYPE_METER
+ */
+int
+rte_mtr_create(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_params *params,
+	int shared,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object destroy
+ *
+ * Delete an existing MTR object. This operation fails when there is currently
+ * at least one user (i.e. flow) of this MTR object.
+ *
+ * @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[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_destroy(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object meter profile 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] meter_profile_id
+ *   Meter profile ID for the current MTR object. Needs to be valid.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_profile_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object policer action update for given color
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be valid.
+ * @param[in] color
+ *   Color for which the policer action is updated.
+ * @param[in] action
+ *   Policer action for specified color.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_policer_action_update(uint8_t port_id,
+	uint32_t mtr_id,
+	enum rte_mtr_color color,
+	enum rte_mtr_policer_action action,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object enabled statistics counters 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] stats_mask
+ *   Mask of statistics counter types to be enabled for the current MTR object.
+ *   Any statistics counter type not included in this set is to be disabled for
+ *   the current MTR object.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_mtr_stats_type
+ */
+int
+rte_mtr_stats_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint64_t stats_mask,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object statistics counters read
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be valid.
+ * @param[out] stats
+ *   When non-NULL, it contains the current value for the statistics counters
+ *   enabled for the current MTR object.
+ * @param[out] stats_mask
+ *   When non-NULL, it contains the mask of statistics counter types that are
+ *   currently enabled for this MTR object, indicating which of the counters
+ *   retrieved with the *stats* structure are valid.
+ * @param[in] clear
+ *   When this parameter has a non-zero value, the statistics counters are
+ *   cleared (i.e. set to zero) immediately after they have been read,
+ *   otherwise the statistics counters are left untouched.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_mtr_stats_type
+ */
+int
+rte_mtr_stats_read(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_RTE_MTR_H__ */
diff --git a/lib/librte_ether/rte_mtr_driver.h b/lib/librte_ether/rte_mtr_driver.h
new file mode 100644
index 0000000..3798cf6
--- /dev/null
+++ b/lib/librte_ether/rte_mtr_driver.h
@@ -0,0 +1,188 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __INCLUDE_RTE_MTR_DRIVER_H__
+#define __INCLUDE_RTE_MTR_DRIVER_H__
+
+/**
+ * @file
+ * RTE Generic Traffic Metering and Policing API (Driver Side)
+ *
+ * This file provides implementation helpers for internal use by PMDs, they
+ * are not intended to be exposed to applications and are not subject to ABI
+ * versioning.
+ */
+
+#include <stdint.h>
+
+#include <rte_errno.h>
+#include "rte_ethdev.h"
+#include "rte_mtr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int (*rte_mtr_meter_profile_add_t)(struct rte_eth_dev *dev,
+	uint32_t meter_profile_id,
+	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_error *error);
+/**< @internal MTR meter profile delete */
+
+typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	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_error *error);
+/**< @internal MTR object destroy */
+
+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_error *error);
+/**< @internal MTR object meter profile update */
+
+typedef int (*rte_mtr_policer_action_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	enum rte_mtr_color color,
+	enum rte_mtr_policer_action action,
+	struct rte_mtr_error *error);
+/**< @internal MTR object policer action update*/
+
+typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	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_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error);
+/**< @internal MTR object stats read */
+
+struct rte_mtr_ops {
+	/** MTR meter profile add */
+	rte_mtr_meter_profile_add_t meter_profile_add;
+
+	/** MTR meter profile delete */
+	rte_mtr_meter_profile_delete_t meter_profile_delete;
+
+	/** MTR object create */
+	rte_mtr_create_t create;
+
+	/** MTR object destroy */
+	rte_mtr_destroy_t destroy;
+
+	/** MTR object meter profile update */
+	rte_mtr_meter_profile_update_t meter_profile_update;
+
+	/** MTR object policer action update */
+	rte_mtr_policer_action_update_t policer_action_update;
+
+	/** MTR object enabled stats update */
+	rte_mtr_stats_update_t stats_update;
+
+	/** MTR object stats read */
+	rte_mtr_stats_read_t stats_read;
+};
+
+/**
+ * Initialize generic error structure.
+ *
+ * This function also sets rte_errno to a given value.
+ *
+ * @param[out] error
+ *   Pointer to error structure (may be NULL).
+ * @param[in] code
+ *   Related error code (rte_errno).
+ * @param[in] type
+ *   Cause field and error type.
+ * @param[in] cause
+ *   Object responsible for the error.
+ * @param[in] message
+ *   Human-readable error message.
+ *
+ * @return
+ *   Error code.
+ */
+static inline int
+rte_mtr_error_set(struct rte_mtr_error *error,
+		   int code,
+		   enum rte_mtr_error_type type,
+		   const void *cause,
+		   const char *message)
+{
+	if (error) {
+		*error = (struct rte_mtr_error){
+			.type = type,
+			.cause = cause,
+			.message = message,
+		};
+	}
+	rte_errno = code;
+	return code;
+}
+
+/**
+ * Get generic traffic metering and policing operations structure from a port
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[out] error
+ *   Error details
+ *
+ * @return
+ *   The traffic metering and policing operations structure associated with
+ *   port_id on success, NULL otherwise.
+ */
+const struct rte_mtr_ops *
+rte_mtr_ops_get(uint8_t port_id, struct rte_mtr_error *error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_RTE_MTR_DRIVER_H__ */
-- 
2.7.4

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

* [PATCH 3/3] rte_flow: add new action for traffic metering and policing
  2017-08-26  0:06   ` [PATCH 0/3] rte_mtr: generic ethdev API for " Cristian Dumitrescu
  2017-08-26  0:06     ` [PATCH 1/3] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
  2017-08-26  0:06     ` [PATCH 2/3] ethdev: add new rte_mtr API " Cristian Dumitrescu
@ 2017-08-26  0:06     ` Cristian Dumitrescu
  2017-09-06 16:23       ` Adrien Mazarguil
  2017-09-21 13:28     ` [PATCH 0/3] rte_mtr: generic ethdev API for " Thomas Monjalon
  3 siblings, 1 reply; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-08-26  0:06 UTC (permalink / raw)
  To: dev; +Cc: thomas, adrien.mazarguil, jerin.jacob, hemant.agrawal

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 lib/librte_ether/rte_flow.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index bba6169..5569a87 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -915,6 +915,14 @@ enum rte_flow_action_type {
 	 * See struct rte_flow_action_vf.
 	 */
 	RTE_FLOW_ACTION_TYPE_VF,
+
+	/**
+	 * Traffic metering and policing (MTR).
+	 *
+	 * See struct rte_flow_action_meter.
+	 * See file rte_mtr.h for MTR object configuration.
+	 */
+	RTE_FLOW_ACTION_TYPE_METER,
 };
 
 /**
@@ -1008,6 +1016,20 @@ struct rte_flow_action_vf {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_METER
+ *
+ * Traffic metering and policing (MTR).
+ *
+ * Packets matched by items of this type can be either dropped or passed to the
+ * next item with their color set by the MTR object.
+ *
+ * Non-terminating by default.
+ */
+struct rte_flow_action_meter {
+	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create(). */
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.7.4

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

* Re: [PATCH 2/3] ethdev: add new rte_mtr API for traffic metering and policing
  2017-08-26  0:06     ` [PATCH 2/3] ethdev: add new rte_mtr API " Cristian Dumitrescu
@ 2017-09-01  8:09       ` Hemant Agrawal
  2017-09-04 14:32         ` Dumitrescu, Cristian
  2017-09-21 13:20       ` Thomas Monjalon
  1 sibling, 1 reply; 64+ messages in thread
From: Hemant Agrawal @ 2017-09-01  8:09 UTC (permalink / raw)
  To: Cristian Dumitrescu, dev; +Cc: thomas, adrien.mazarguil, jerin.jacob

On 8/26/2017 5:36 AM, Cristian Dumitrescu wrote:
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> ---
> Changes in v1 (from RFC [1]):
> - Added EXPERIMENTAL tag in rte_mtr.h and MANTAINERS for this new API
>   (input from Thomas)
> - Added more Doxygen comments to re-inforce relationship between MTR and
>   flow (input from Adrien)
> - Added Doxygen hook in doxy-api-index.md
>
> [1] RFC: http://www.dpdk.org/ml/archives/dev/2017-May/066888.html
>
>  MAINTAINERS                            |   4 +
>  doc/api/doxy-api-index.md              |   1 +
>  lib/librte_ether/Makefile              |   5 +-
>  lib/librte_ether/rte_ether_version.map |  15 ++
>  lib/librte_ether/rte_mtr.c             | 184 +++++++++++++
>  lib/librte_ether/rte_mtr.h             | 471 +++++++++++++++++++++++++++++++++
>  lib/librte_ether/rte_mtr_driver.h      | 188 +++++++++++++
>  7 files changed, 867 insertions(+), 1 deletion(-)
>  create mode 100644 lib/librte_ether/rte_mtr.c
>  create mode 100644 lib/librte_ether/rte_mtr.h
>  create mode 100644 lib/librte_ether/rte_mtr_driver.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a0cd75e..5491906 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -257,6 +257,10 @@ M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
>  T: git://dpdk.org/next/dpdk-next-tm
>  F: lib/librte_ether/rte_tm*
>
> +Traffic Metering and Policing API - EXPERIMENTAL
> +M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> +F: lib/librte_ether/rte_mtr*
> +
>  Crypto API
>  M: Declan Doherty <declan.doherty@intel.com>
>  F: lib/librte_cryptodev/
> diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
> index 19e0d4f..b2342a9 100644
> --- a/doc/api/doxy-api-index.md
> +++ b/doc/api/doxy-api-index.md
> @@ -41,6 +41,7 @@ The public API headers are grouped by topics:
>    [ethctrl]            (@ref rte_eth_ctrl.h),
>    [rte_flow]           (@ref rte_flow.h),
>    [rte_tm]             (@ref rte_tm.h),
> +  [rte_mtr]            (@ref rte_mtr.h),
>    [cryptodev]          (@ref rte_cryptodev.h),
>    [eventdev]           (@ref rte_eventdev.h),
>    [metrics]            (@ref rte_metrics.h),
> diff --git a/lib/librte_ether/Makefile b/lib/librte_ether/Makefile
> index db692ae..e4e339d 100644
> --- a/lib/librte_ether/Makefile
> +++ b/lib/librte_ether/Makefile
> @@ -41,11 +41,12 @@ CFLAGS += $(WERROR_FLAGS)
>
>  EXPORT_MAP := rte_ether_version.map
>
> -LIBABIVER := 6
> +LIBABIVER := 7
>
>  SRCS-y += rte_ethdev.c
>  SRCS-y += rte_flow.c
>  SRCS-y += rte_tm.c
> +SRCS-y += rte_mtr.c
>
>  #
>  # Export include files
> @@ -59,5 +60,7 @@ SYMLINK-y-include += rte_flow.h
>  SYMLINK-y-include += rte_flow_driver.h
>  SYMLINK-y-include += rte_tm.h
>  SYMLINK-y-include += rte_tm_driver.h
> +SYMLINK-y-include += rte_mtr.h
> +SYMLINK-y-include += rte_mtr_driver.h
>
>  include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
> index 4283728..7192664 100644
> --- a/lib/librte_ether/rte_ether_version.map
> +++ b/lib/librte_ether/rte_ether_version.map
> @@ -187,3 +187,18 @@ DPDK_17.08 {
>  	rte_tm_wred_profile_delete;
>
>  } DPDK_17.05;
> +
> +DPDK_17.11 {
> +	global:
> +
> +	rte_eth_dev_mtr_ops_get;
> +	rte_mtr_meter_profile_add;
> +	rte_mtr_meter_profile_delete;
> +	rte_mtr_create;
> +	rte_mtr_destroy;
> +	rte_mtr_meter_profile_update;
> +	rte_mtr_policer_action_update;
> +	rte_mtr_stats_update;
> +	rte_mtr_stats_read;
> +
> +} DPDK_17.08;
> diff --git a/lib/librte_ether/rte_mtr.c b/lib/librte_ether/rte_mtr.c
> new file mode 100644
> index 0000000..efbe7fb
> --- /dev/null
> +++ b/lib/librte_ether/rte_mtr.c
> @@ -0,0 +1,184 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2017 Intel Corporation. All rights reserved.
> + *   All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of Intel Corporation nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <stdint.h>
> +
> +#include <rte_errno.h>
> +#include "rte_ethdev.h"
> +#include "rte_mtr_driver.h"
> +#include "rte_mtr.h"
> +
> +/* Get generic traffic metering and policing operations structure from a port. */
> +const struct rte_mtr_ops *
> +rte_mtr_ops_get(uint8_t port_id, struct rte_mtr_error *error)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> +	const struct rte_mtr_ops *ops;
> +
> +	if (!rte_eth_dev_is_valid_port(port_id)) {
> +		rte_mtr_error_set(error,
> +			ENODEV,
> +			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
> +			NULL,
> +			rte_strerror(ENODEV));
> +		return NULL;
> +	}
> +
> +	if ((dev->dev_ops->mtr_ops_get == NULL) ||
> +		(dev->dev_ops->mtr_ops_get(dev, &ops) != 0) ||
> +		(ops == NULL)) {
> +		rte_mtr_error_set(error,
> +			ENOSYS,
> +			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
> +			NULL,
> +			rte_strerror(ENOSYS));
> +		return NULL;
> +	}
> +
> +	return ops;
> +}
> +
> +#define RTE_MTR_FUNC(port_id, func)			\
> +({							\
> +	const struct rte_mtr_ops *ops =			\
> +		rte_mtr_ops_get(port_id, error);		\
> +	if (ops == NULL)					\
> +		return -rte_errno;			\
> +							\
> +	if (ops->func == NULL)				\
> +		return -rte_mtr_error_set(error,		\
> +			ENOSYS,				\
> +			RTE_MTR_ERROR_TYPE_UNSPECIFIED,	\
> +			NULL,				\
> +			rte_strerror(ENOSYS));		\
> +							\
> +	ops->func;					\
> +})
> +
> +/* MTR meter profile add */
> +int
> +rte_mtr_meter_profile_add(uint8_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);
> +}
> +
> +/** MTR meter profile delete */
> +int
> +rte_mtr_meter_profile_delete(uint8_t port_id,
> +	uint32_t meter_profile_id,
> +	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);
> +}
> +
> +/** MTR object create */
> +int
> +rte_mtr_create(uint8_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);
> +}
> +
> +/** MTR object destroy */
> +int
> +rte_mtr_destroy(uint8_t port_id,
> +	uint32_t mtr_id,
> +	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 object meter profile update */
> +int
> +rte_mtr_meter_profile_update(uint8_t port_id,
> +	uint32_t mtr_id,
> +	uint32_t meter_profile_id,
> +	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 object policer action update */
> +int
> +rte_mtr_policer_action_update(uint8_t port_id,
> +	uint32_t mtr_id,
> +	enum rte_mtr_color color,
> +	enum rte_mtr_policer_action action,
> +	struct rte_mtr_error *error)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> +	return RTE_MTR_FUNC(port_id, policer_action_update)(dev,
> +		mtr_id, color, action, error);
> +}
> +
> +/** MTR object enabled stats update */
> +int
> +rte_mtr_stats_update(uint8_t port_id,
> +	uint32_t mtr_id,
> +	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 object stats read */
> +int
> +rte_mtr_stats_read(uint8_t port_id,
> +	uint32_t mtr_id,
> +	struct rte_mtr_stats *stats,
> +	uint64_t *stats_mask,
> +	int clear,
> +	struct rte_mtr_error *error)
> +{
> +	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);
> +}
> diff --git a/lib/librte_ether/rte_mtr.h b/lib/librte_ether/rte_mtr.h
> new file mode 100644
> index 0000000..d15cb9f
> --- /dev/null
> +++ b/lib/librte_ether/rte_mtr.h
> @@ -0,0 +1,471 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2017 Intel Corporation. All rights reserved.
> + *   All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of Intel Corporation nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifndef __INCLUDE_RTE_MTR_H__
> +#define __INCLUDE_RTE_MTR_H__
> +
> +/**
> + * @file
> + * RTE Generic Traffic Metering and Policing API
> + *
> + * This interface provides the ability to configure the traffic metering and
> + * policing (MTR) in a generic way.
> + *
> + * The processing done for each input packet hitting a MTR object is:
> + *    A) Traffic metering: The packet is assigned a color (the meter output
> + *       color), based on the previous history of the flow reflected in the
> + *       current state of the MTR object, according to the specific traffic
> + *       metering algorithm. The traffic metering algorithm can typically work
> + *       in color aware mode, in which case the input packet already has an
> + *       initial color (the input color), or in color blind mode, which is
> + *       equivalent to considering all input packets initially colored as green.
> + *    B) Policing: There is a separate policer action configured for each meter
> + *       output color, which can:
> + *          a) Drop the packet.
> + *          b) Keep the same packet color: the policer output color matches the
> + *             meter output color (essentially a no-op action).
> + *          c) Recolor the packet: the policer output color is different 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).
> + *    C) Statistics: The set of counters maintained for each MTR object is
> + *       configurable and subject to the implementation support. This set
> + *       includes the number of packets and bytes dropped or passed for each
> + *       output color.
> + *
> + * Once successfully created, an MTR object is linked to one or several flows
> + * through the meter action of the flow API.
> + *    A) Whether an MTR object is private to a flow or potentially shared by
> + *       several flows has to be specified at creation time.
> + *    B) Several meter actions can be potentially registered for the same flow.
> + *
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + */
> +#include <stdint.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**
> + * Color
> + */
> +enum rte_mtr_color {
> +	RTE_MTR_GREEN = 0, /**< Green */
> +	RTE_MTR_YELLOW, /**< Yellow */
> +	RTE_MTR_RED, /**< Red */
> +	RTE_MTR_COLORS /**< Number of colors */
> +};
> +
> +/**
> + * Statistics counter type
> + */
> +enum rte_mtr_stats_type {
> +	/**< Number of packets passed as green by the policer.  */
> +	RTE_MTR_STATS_N_PKTS_GREEN = 1 << 0,
> +
> +	/**< Number of bytes passed as green by the policer.  */
> +	RTE_MTR_STATS_N_BYTES_GREEN = 1 << 1,
> +
> +	/**< Number of packets passed as yellow by the policer.  */
> +	RTE_MTR_STATS_N_PKTS_YELLOW = 1 << 2,
> +
> +	/**< Number of bytes passed as yellow by the policer.  */
> +	RTE_MTR_STATS_N_BYTES_YELLOW = 1 << 3,
> +
> +	/**< Number of packets passed as red by the policer.  */
> +	RTE_MTR_STATS_N_PKTS_RED = 1 << 4,
> +
> +	/**< Number of bytes passed as red by the policer.  */
> +	RTE_MTR_STATS_N_BYTES_RED = 1 << 5,
> +
> +	/**< Number of packets dropped by the policer.  */
> +	RTE_MTR_STATS_N_PKTS_DROPPED = 1 << 6,
> +
> +	/**< Number of bytes dropped by the policer.  */
> +	RTE_MTR_STATS_N_BYTES_DROPPED = 1 << 7,
> +};
> +
> +/**
> + * Statistics counters
> + */
> +struct rte_mtr_stats {
> +	/**< Number of packets passed by the policer (per color). */
> +	uint64_t n_pkts[RTE_MTR_COLORS];
> +
> +	/**< Number of bytes passed by the policer (per color). */
> +	uint64_t n_bytes[RTE_MTR_COLORS];
> +
> +	/**< Number of packets dropped by the policer. */
> +	uint64_t n_pkts_dropped;
> +
> +	/**< Number of bytes passed by the policer. */
> +	uint64_t n_bytes_dropped;
> +};
> +
> +/**
> + * Traffic metering algorithms
> + */
> +enum rte_mtr_algorithm {
> +	/**< Single Rate Three Color Marker (srTCM) - IETF RFC 2697. */
> +	RTE_MTR_SRTCM_RFC2697 = 0,
> +
> +	/**< Two Rate Three Color Marker (trTCM) - IETF RFC 2698. */
> +	RTE_MTR_TRTCM_RFC2698,

will you please also add following here
1. RFC-4115—A differentiated service two-rate three-color marker with 
efficient handling of in-profile traffic
2. Pass Through Mode- This mode does not implement differentiated 
services. It can be used for some applications to block/pass selected 
flows and set a constant color for these flows. The default (disabled) 
mode is color-aware pass-through with no dropping of packets.
- In color-aware mode, packet pre-color is copied to the packet color
– In color-blind mode, the default color is programmable per profile
– Configurable next module and command per packet color. Each color 
action can be programmed to pass or drop the packet.


> +};
> +
> +/**
> + * Meter profile
> + */
> +struct rte_mtr_meter_profile {
> +	/**<  Traffic metering algorithm. */
> +	enum rte_mtr_algorithm alg;
> +
> +	union {
> +		/**< Items only valid when *alg* is set to srTCM - RFC2697. */
> +		struct {
> +			/**< Committed Information Rate (CIR) (bytes/second). */
> +			uint64_t cir;
> +
> +			/**< Committed Burst Size (CBS) (bytes). */
> +			uint64_t cbs;
> +
> +			/**< Excess Burst Size (EBS) (bytes). */
> +			uint64_t ebs;
> +
> +			/**< Non-zero for color aware mode, zero for color blind
> +			 * mode. In color aware mode, the packet input color is
> +			 * read from the IPv4/IPv6 DSCP field, as defined by
> +			 * IETF RFC 2597 (low/medium/high drop precedence
> +			 * translates to green/yellow/red color respectively).
> +			 */
> +			int color_aware;
> +		} srtcm_rfc2697;
> +
> +		/**< Items only valid when *alg* is set to trTCM - RFC2698. */
> +		struct {
> +			/**< Committed Information Rate (CIR) (bytes/second). */
> +			uint64_t cir;
> +
> +			/**< Peak Information Rate (PIR) (bytes/second). */
> +			uint64_t pir;
> +
> +			/**< Committed Burst Size (CBS) (byes). */
> +			uint64_t cbs;
> +
> +			/**< Peak Burst Size (PBS) (bytes). */
> +			uint64_t pbs;
> +
> +			/**< Non-zero for color aware mode, zero for color blind
> +			 * mode. In color aware mode, the packet input color is
> +			 * read from the IPv4/IPv6 DSCP field, as defined by
> +			 * IETF RFC 2597 (low/medium/high drop precedence
> +			 * translates to green/yellow/red color respectively).
> +			 */
> +			int color_aware;
> +		} trtcm_rfc2698;
> +	};
> +};
> +
> +/**
> + * Policer actions
> + */
> +enum rte_mtr_policer_action {
> +	/**< Recolor the packet as green. */
> +	e_MTR_POLICER_ACTION_COLOR_GREEN = 0,
> +
> +	/**< Recolor the packet as yellow. */
> +	e_MTR_POLICER_ACTION_COLOR_YELLOW,
> +
> +	/**< Recolor the packet as red. */
> +	e_MTR_POLICER_ACTION_COLOR_RED,
> +
> +	/**< Drop the packet. */
> +	e_MTR_POLICER_ACTION_DROP,
> +};
> +
> +/**
> + * Parameters for each traffic metering & policing object
> + *
> + * @see enum rte_mtr_stats_type
> + */
> +struct rte_mtr_params {
> +	/**< Meter profile ID. */
> +	uint32_t meter_profile_id;
> +
> +	/**< Policer actions (per meter output color). */
> +	enum rte_mtr_policer_action action[RTE_MTR_COLORS];
> +
> +	/**< Set of stats counters to be enabled. */
> +	uint64_t stats_mask;
> +};
> +
> +/**
> + * Verbose error types.
> + *
> + * Most of them provide the type of the object referenced by struct
> + * rte_mtr_error::cause.
> + */
> +enum rte_mtr_error_type {
> +	RTE_MTR_ERROR_TYPE_NONE, /**< No error. */
> +	RTE_MTR_ERROR_TYPE_UNSPECIFIED, /**< Cause unspecified. */
> +	RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
> +	RTE_MTR_ERROR_TYPE_METER_PROFILE,
> +	RTE_MTR_ERROR_TYPE_MTR_ID,
> +	RTE_MTR_ERROR_TYPE_MTR_PARAMS,
> +	RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN,
> +	RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW,
> +	RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED,
> +	RTE_MTR_ERROR_TYPE_STATS_MASK,
> +	RTE_MTR_ERROR_TYPE_STATS,
> +	RTE_MTR_ERROR_TYPE_SHARED,
> +};
> +
> +/**
> + * Verbose error structure definition.
> + *
> + * This object is normally allocated by applications and set by PMDs, the
> + * message points to a constant string which does not need to be freed by
> + * the application, however its pointer can be considered valid only as long
> + * as its associated DPDK port remains configured. Closing the underlying
> + * device or unloading the PMD invalidates it.
> + *
> + * Both cause and message may be NULL regardless of the error type.
> + */
> +struct rte_mtr_error {
> +	enum rte_mtr_error_type type; /**< Cause field and error type. */
> +	const void *cause; /**< Object responsible for the error. */
> +	const char *message; /**< Human-readable error message. */
> +};
> +
> +/**
> + * Meter profile add
> + *
> + * Create a new meter profile with ID set to *meter_profile_id*. 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.
> + */
> +int
> +rte_mtr_meter_profile_add(uint8_t port_id,
> +	uint32_t meter_profile_id,
> +	struct rte_mtr_meter_profile *profile,
> +	struct rte_mtr_error *error);
> +
> +/**
> + * Meter profile delete
> + *
> + * Delete an existing meter profile. This operation fails when there is
> + * currently at least one user (i.e. MTR object) of this profile.
> + *

Do you want to do this checking at library level or at driver level?
Same profile can be used by two distinct drivers!

This is applicable for other APIs as well. Your current API 
implementation is mostly pass-through. A stateful will be better.

> + * @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[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_mtr_meter_profile_delete(uint8_t port_id,
> +	uint32_t meter_profile_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
> + * associated flow action for traffic metering and policing.
> + *
> + * @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
> + *   Non-zero when this MTR object can be shared by multiple flows, zero when
> + *   this MTR object can be used by a single flow.
> + * @param[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + *
> + * @see enum rte_flow_action_type::RTE_FLOW_ACTION_TYPE_METER
> + */
> +int
> +rte_mtr_create(uint8_t port_id,
> +	uint32_t mtr_id,
> +	struct rte_mtr_params *params,
> +	int shared,
> +	struct rte_mtr_error *error);
> +
> +/**
> + * MTR object destroy
> + *
> + * Delete an existing MTR object. This operation fails when there is currently
> + * at least one user (i.e. flow) of this MTR object.
> + *
> + * @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[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_mtr_destroy(uint8_t port_id,
> +	uint32_t mtr_id,
> +	struct rte_mtr_error *error);
> +
> +/**
> + * MTR object meter profile 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] meter_profile_id
> + *   Meter profile ID for the current MTR object. Needs to be valid.
> + * @param[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_mtr_meter_profile_update(uint8_t port_id,
> +	uint32_t mtr_id,
> +	uint32_t meter_profile_id,
> +	struct rte_mtr_error *error);
> +
> +/**
> + * MTR object policer action update for given color
> + *
> + * @param[in] port_id
> + *   The port identifier of the Ethernet device.
> + * @param[in] mtr_id
> + *   MTR object ID. Needs to be valid.
> + * @param[in] color
> + *   Color for which the policer action is updated.
> + * @param[in] action
> + *   Policer action for specified color.
> + * @param[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + */
> +int
> +rte_mtr_policer_action_update(uint8_t port_id,
> +	uint32_t mtr_id,
> +	enum rte_mtr_color color,
> +	enum rte_mtr_policer_action action,
> +	struct rte_mtr_error *error);
> +
> +/**
> + * MTR object enabled statistics counters 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] stats_mask
> + *   Mask of statistics counter types to be enabled for the current MTR object.
> + *   Any statistics counter type not included in this set is to be disabled for
> + *   the current MTR object.
> + * @param[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + *
> + * @see enum rte_mtr_stats_type
> + */
> +int
> +rte_mtr_stats_update(uint8_t port_id,
> +	uint32_t mtr_id,
> +	uint64_t stats_mask,
> +	struct rte_mtr_error *error);
> +
> +/**
> + * MTR object statistics counters read
> + *
> + * @param[in] port_id
> + *   The port identifier of the Ethernet device.
> + * @param[in] mtr_id
> + *   MTR object ID. Needs to be valid.
> + * @param[out] stats
> + *   When non-NULL, it contains the current value for the statistics counters
> + *   enabled for the current MTR object.
> + * @param[out] stats_mask
> + *   When non-NULL, it contains the mask of statistics counter types that are
> + *   currently enabled for this MTR object, indicating which of the counters
> + *   retrieved with the *stats* structure are valid.
> + * @param[in] clear
> + *   When this parameter has a non-zero value, the statistics counters are
> + *   cleared (i.e. set to zero) immediately after they have been read,
> + *   otherwise the statistics counters are left untouched.
> + * @param[out] error
> + *   Error details. Filled in only on error, when not NULL.
> + * @return
> + *   0 on success, non-zero error code otherwise.
> + *
> + * @see enum rte_mtr_stats_type
> + */
> +int
> +rte_mtr_stats_read(uint8_t port_id,
> +	uint32_t mtr_id,
> +	struct rte_mtr_stats *stats,
> +	uint64_t *stats_mask,
> +	int clear,
> +	struct rte_mtr_error *error);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* __INCLUDE_RTE_MTR_H__ */
> diff --git a/lib/librte_ether/rte_mtr_driver.h b/lib/librte_ether/rte_mtr_driver.h
> new file mode 100644
> index 0000000..3798cf6
> --- /dev/null
> +++ b/lib/librte_ether/rte_mtr_driver.h
> @@ -0,0 +1,188 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2017 Intel Corporation. All rights reserved.
> + *   All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of Intel Corporation nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifndef __INCLUDE_RTE_MTR_DRIVER_H__
> +#define __INCLUDE_RTE_MTR_DRIVER_H__
> +
> +/**
> + * @file
> + * RTE Generic Traffic Metering and Policing API (Driver Side)
> + *
> + * This file provides implementation helpers for internal use by PMDs, they
> + * are not intended to be exposed to applications and are not subject to ABI
> + * versioning.
> + */
> +
> +#include <stdint.h>
> +
> +#include <rte_errno.h>
> +#include "rte_ethdev.h"
> +#include "rte_mtr.h"
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +typedef int (*rte_mtr_meter_profile_add_t)(struct rte_eth_dev *dev,
> +	uint32_t meter_profile_id,
> +	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_error *error);
> +/**< @internal MTR meter profile delete */
> +
> +typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,
> +	uint32_t mtr_id,
> +	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_error *error);
> +/**< @internal MTR object destroy */
> +
> +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_error *error);
> +/**< @internal MTR object meter profile update */
> +
> +typedef int (*rte_mtr_policer_action_update_t)(struct rte_eth_dev *dev,
> +	uint32_t mtr_id,
> +	enum rte_mtr_color color,
> +	enum rte_mtr_policer_action action,
> +	struct rte_mtr_error *error);
> +/**< @internal MTR object policer action update*/
> +
> +typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
> +	uint32_t mtr_id,
> +	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_stats *stats,
> +	uint64_t *stats_mask,
> +	int clear,
> +	struct rte_mtr_error *error);
> +/**< @internal MTR object stats read */
> +
> +struct rte_mtr_ops {
> +	/** MTR meter profile add */
> +	rte_mtr_meter_profile_add_t meter_profile_add;
> +
> +	/** MTR meter profile delete */
> +	rte_mtr_meter_profile_delete_t meter_profile_delete;
> +
> +	/** MTR object create */
> +	rte_mtr_create_t create;
> +
> +	/** MTR object destroy */
> +	rte_mtr_destroy_t destroy;
> +
> +	/** MTR object meter profile update */
> +	rte_mtr_meter_profile_update_t meter_profile_update;
> +
> +	/** MTR object policer action update */
> +	rte_mtr_policer_action_update_t policer_action_update;
> +
> +	/** MTR object enabled stats update */
> +	rte_mtr_stats_update_t stats_update;
> +
> +	/** MTR object stats read */
> +	rte_mtr_stats_read_t stats_read;
> +};
> +
> +/**
> + * Initialize generic error structure.
> + *
> + * This function also sets rte_errno to a given value.
> + *
> + * @param[out] error
> + *   Pointer to error structure (may be NULL).
> + * @param[in] code
> + *   Related error code (rte_errno).
> + * @param[in] type
> + *   Cause field and error type.
> + * @param[in] cause
> + *   Object responsible for the error.
> + * @param[in] message
> + *   Human-readable error message.
> + *
> + * @return
> + *   Error code.
> + */
> +static inline int
> +rte_mtr_error_set(struct rte_mtr_error *error,
> +		   int code,
> +		   enum rte_mtr_error_type type,
> +		   const void *cause,
> +		   const char *message)
> +{
> +	if (error) {
> +		*error = (struct rte_mtr_error){
> +			.type = type,
> +			.cause = cause,
> +			.message = message,
> +		};
> +	}
> +	rte_errno = code;
> +	return code;
> +}
> +
> +/**
> + * Get generic traffic metering and policing operations structure from a port
> + *
> + * @param[in] port_id
> + *   The port identifier of the Ethernet device.
> + * @param[out] error
> + *   Error details
> + *
> + * @return
> + *   The traffic metering and policing operations structure associated with
> + *   port_id on success, NULL otherwise.
> + */
> +const struct rte_mtr_ops *
> +rte_mtr_ops_get(uint8_t port_id, struct rte_mtr_error *error);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* __INCLUDE_RTE_MTR_DRIVER_H__ */
>

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

* Re: [PATCH 2/3] ethdev: add new rte_mtr API for traffic metering and policing
  2017-09-01  8:09       ` Hemant Agrawal
@ 2017-09-04 14:32         ` Dumitrescu, Cristian
  2017-09-06  9:15           ` Hemant Agrawal
  0 siblings, 1 reply; 64+ messages in thread
From: Dumitrescu, Cristian @ 2017-09-04 14:32 UTC (permalink / raw)
  To: Hemant Agrawal, dev; +Cc: thomas, adrien.mazarguil, jerin.jacob

Hi Hemant,

Thanks very much for your input!

<snip>...

> > +
> > +/**
> > + * Traffic metering algorithms
> > + */
> > +enum rte_mtr_algorithm {
> > +	/**< Single Rate Three Color Marker (srTCM) - IETF RFC 2697. */
> > +	RTE_MTR_SRTCM_RFC2697 = 0,
> > +
> > +	/**< Two Rate Three Color Marker (trTCM) - IETF RFC 2698. */
> > +	RTE_MTR_TRTCM_RFC2698,
> 
> will you please also add following here
> 1. RFC-4115-A differentiated service two-rate three-color marker with
> efficient handling of in-profile traffic
> 2. Pass Through Mode- This mode does not implement differentiated
> services. It can be used for some applications to block/pass selected
> flows and set a constant color for these flows. The default (disabled)
> mode is color-aware pass-through with no dropping of packets.
> - In color-aware mode, packet pre-color is copied to the packet color
> - In color-blind mode, the default color is programmable per profile
> - Configurable next module and command per packet color. Each color
> action can be programmed to pass or drop the packet.
> 

Yes, will add both. The trTCM from RFC 4115 was already on my list, adding the pass-through mode makes sense to me as well.

<snip>...

> > +/**
> > + * Meter profile delete
> > + *
> > + * Delete an existing meter profile. This operation fails when there is
> > + * currently at least one user (i.e. MTR object) of this profile.
> > + *
> 
> Do you want to do this checking at library level or at driver level?
> Same profile can be used by two distinct drivers!
> 
> This is applicable for other APIs as well. Your current API
> implementation is mostly pass-through. A stateful will be better.
> 

Yes, the same meter profiles can potentially be shared for a group of ethdev ports, but unfortunately we cannot do this with the current ethdev API, which is per port with no sharing ability between groups of ports.

Here we are lucky to have just a read-only configuration template that needs to be shared amongst ports, so the quick workaround is to define the same profile for each port at the expense of some (small) work duplication. Hopefully this is OK with you?

<snip>...

Regards,
Cristian

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

* Re: [PATCH 2/3] ethdev: add new rte_mtr API for traffic metering and policing
  2017-09-04 14:32         ` Dumitrescu, Cristian
@ 2017-09-06  9:15           ` Hemant Agrawal
  2017-09-19 16:14             ` Dumitrescu, Cristian
  0 siblings, 1 reply; 64+ messages in thread
From: Hemant Agrawal @ 2017-09-06  9:15 UTC (permalink / raw)
  To: Dumitrescu, Cristian, dev; +Cc: thomas, adrien.mazarguil, jerin.jacob

Hi Cristian,

On 9/4/2017 8:02 PM, Dumitrescu, Cristian wrote:
> <snip>...
>
>>> +
>>> +/**
>>> + * Traffic metering algorithms
>>> + */
>>> +enum rte_mtr_algorithm {
>>> +	/**< Single Rate Three Color Marker (srTCM) - IETF RFC 2697. */
>>> +	RTE_MTR_SRTCM_RFC2697 = 0,
>>> +
>>> +	/**< Two Rate Three Color Marker (trTCM) - IETF RFC 2698. */
>>> +	RTE_MTR_TRTCM_RFC2698,
>>
>> will you please also add following here
>> 1. RFC-4115-A differentiated service two-rate three-color marker with
>> efficient handling of in-profile traffic
>> 2. Pass Through Mode- This mode does not implement differentiated
>> services. It can be used for some applications to block/pass selected
>> flows and set a constant color for these flows. The default (disabled)
>> mode is color-aware pass-through with no dropping of packets.
>> - In color-aware mode, packet pre-color is copied to the packet color
>> - In color-blind mode, the default color is programmable per profile
>> - Configurable next module and command per packet color. Each color
>> action can be programmed to pass or drop the packet.
>>
>
> Yes, will add both. The trTCM from RFC 4115 was already on my list, adding the pass-through mode makes sense to me as well.
>
> <snip>...
>
>>> +/**
>>> + * Meter profile delete
>>> + *
>>> + * Delete an existing meter profile. This operation fails when there is
>>> + * currently at least one user (i.e. MTR object) of this profile.
>>> + *
>>
>> Do you want to do this checking at library level or at driver level?
>> Same profile can be used by two distinct drivers!
>>
>> This is applicable for other APIs as well. Your current API
>> implementation is mostly pass-through. A stateful will be better.
>>
>
> Yes, the same meter profiles can potentially be shared for a group of ethdev ports, but unfortunately we cannot do this with the current ethdev API, which is per port with no sharing ability between groups of ports.
>
> Here we are lucky to have just a read-only configuration template that needs to be shared amongst ports, so the quick workaround is to define the same profile for each port at the expense of some (small) work duplication. Hopefully this is OK with you?
>
Is that mean you will create the meter profile template first and then 
apply/remove that on a port?

how about adding a use-count to the profile?

On a different lines, can we do following
1. Metering profile is not applied to a port.  Metering object maintain 
the use-count.
2. metering object is applied to the port, which in turn contains 
metering profile.

Regards,
Hemant

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

* Re: [PATCH 3/3] rte_flow: add new action for traffic metering and policing
  2017-08-26  0:06     ` [PATCH 3/3] rte_flow: add new action " Cristian Dumitrescu
@ 2017-09-06 16:23       ` Adrien Mazarguil
  2017-09-19 16:36         ` Dumitrescu, Cristian
  0 siblings, 1 reply; 64+ messages in thread
From: Adrien Mazarguil @ 2017-09-06 16:23 UTC (permalink / raw)
  To: Cristian Dumitrescu; +Cc: dev, thomas, jerin.jacob, hemant.agrawal

Hi Cristian,

This commit should probably come first in the series since the rest relies
on it, right?

Subject line does not conform past commits, it should start with "ethdev:"
and not mention "rte_flow" (use "flow API").

On Sat, Aug 26, 2017 at 01:06:13AM +0100, Cristian Dumitrescu wrote:
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>

A short description of what this new item does and why it's added is
necessary. Context provided by the rest of the series will not always be
available.

More comments below.

> ---
>  lib/librte_ether/rte_flow.h | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> index bba6169..5569a87 100644
> --- a/lib/librte_ether/rte_flow.h
> +++ b/lib/librte_ether/rte_flow.h
> @@ -915,6 +915,14 @@ enum rte_flow_action_type {
>  	 * See struct rte_flow_action_vf.
>  	 */
>  	RTE_FLOW_ACTION_TYPE_VF,
> +
> +	/**
> +	 * Traffic metering and policing (MTR).
> +	 *
> +	 * See struct rte_flow_action_meter.
> +	 * See file rte_mtr.h for MTR object configuration.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_METER,
>  };
>  
>  /**
> @@ -1008,6 +1016,20 @@ struct rte_flow_action_vf {
>  };
>  
>  /**
> + * RTE_FLOW_ACTION_TYPE_METER
> + *
> + * Traffic metering and policing (MTR).
> + *
> + * Packets matched by items of this type can be either dropped or passed to the
> + * next item with their color set by the MTR object.
> + *
> + * Non-terminating by default.
> + */
> +struct rte_flow_action_meter {
> +	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create(). */
> +};
> +

Default mask definition is missing.

> +/**
>   * Definition of a single action.
>   *
>   * A list of actions is terminated by a END action.
> -- 
> 2.7.4
> 

Even if MTR is a separate API, please add to this commit:

- Documentation update: guides/prog_guide/rte_flow.rst
- Testpmd update: app/test-pmd/cmdline_flow.c
- Testpmd documentation update: doc/guides/testpmd_app_ug/testpmd_funcs.rst

You can find examples in previous commits related to rte_flow.

-- 
Adrien Mazarguil
6WIND

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

* Re: [PATCH 1/3] ethdev: add new eth_dev_ops function for mtr ops get
  2017-08-26  0:06     ` [PATCH 1/3] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
@ 2017-09-13  5:50       ` Jerin Jacob
  2017-09-19 15:52         ` Dumitrescu, Cristian
  2017-10-05 13:09       ` [PATCH V2 0/5] rte_mtr: generic ethdev api for metering and policing Cristian Dumitrescu
  1 sibling, 1 reply; 64+ messages in thread
From: Jerin Jacob @ 2017-09-13  5:50 UTC (permalink / raw)
  To: Cristian Dumitrescu; +Cc: dev, thomas, adrien.mazarguil, hemant.agrawal

-----Original Message-----
> Date: Sat, 26 Aug 2017 01:06:11 +0100
> From: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> To: dev@dpdk.org
> CC: thomas@monjalon.net, adrien.mazarguil@6wind.com,
>  jerin.jacob@caviumnetworks.com, hemant.agrawal@nxp.com
> Subject: [PATCH 1/3] ethdev: add new eth_dev_ops function for mtr ops get
> X-Mailer: git-send-email 2.7.4
> 
> Following similar approach to rte_flow and rte_tm for modularity reasons.
> 
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> ---
> Changes in v1 (from RFC [1]):
> - Removed ethdev API function to get the MTR ops, as it is not needed
>   (input from Thomas)
> 
> [1] RFC: http://www.dpdk.org/ml/archives/dev/2017-May/066888.html
> 
>  lib/librte_ether/rte_ethdev.h | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> index 0adf327..361c9bd 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -1421,6 +1421,9 @@ typedef int (*eth_filter_ctrl_t)(struct rte_eth_dev *dev,
>  typedef int (*eth_tm_ops_get_t)(struct rte_eth_dev *dev, void *ops);
>  /**< @internal Get Traffic Management (TM) operations on an Ethernet device */
>  
> +typedef int (*eth_mtr_ops_get_t)(struct rte_eth_dev *dev, void *ops);
> +/**< @internal Get Trafffic Metering and Policing (MTR) operations */
> +
>  typedef int (*eth_get_dcb_info)(struct rte_eth_dev *dev,
>  				 struct rte_eth_dcb_info *dcb_info);
>  /**< @internal Get dcb information on an Ethernet device */
> @@ -1544,6 +1547,9 @@ struct eth_dev_ops {
>  
>  	eth_tm_ops_get_t tm_ops_get;
>  	/**< Get Traffic Management (TM) operations. */
> +
> +	eth_mtr_ops_get_t mtr_ops_get;
> +	/**< Get Traffic Metering and Policing (MTR) operations. */

It will useful to have capability info here. In Cavium hardwares,
all input pkts are considered as green when they enqueue to ethdev tx
queue.

On the congestion control on Rx side, We support tail drop and RED per
mempool(not per RX queue)

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

* Re: [PATCH 1/3] ethdev: add new eth_dev_ops function for mtr ops get
  2017-09-13  5:50       ` Jerin Jacob
@ 2017-09-19 15:52         ` Dumitrescu, Cristian
  0 siblings, 0 replies; 64+ messages in thread
From: Dumitrescu, Cristian @ 2017-09-19 15:52 UTC (permalink / raw)
  To: Jerin Jacob; +Cc: dev, thomas, adrien.mazarguil, hemant.agrawal

Thanks for your input, Jerin!

<snip>...

> 
> It will useful to have capability info here. In Cavium hardwares,
> all input pkts are considered as green when they enqueue to ethdev tx
> queue.
> 

OK, will add capability API in V2.

> On the congestion control on Rx side, We support tail drop and RED per
> mempool(not per RX queue)

Regards,
Cristian

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

* Re: [PATCH 2/3] ethdev: add new rte_mtr API for traffic metering and policing
  2017-09-06  9:15           ` Hemant Agrawal
@ 2017-09-19 16:14             ` Dumitrescu, Cristian
  0 siblings, 0 replies; 64+ messages in thread
From: Dumitrescu, Cristian @ 2017-09-19 16:14 UTC (permalink / raw)
  To: Hemant Agrawal, dev; +Cc: thomas, adrien.mazarguil, jerin.jacob

Hi Hemant,

<snip>...

> >>> +/**
> >>> + * Meter profile delete
> >>> + *
> >>> + * Delete an existing meter profile. This operation fails when there is
> >>> + * currently at least one user (i.e. MTR object) of this profile.
> >>> + *
> >>
> >> Do you want to do this checking at library level or at driver level?
> >> Same profile can be used by two distinct drivers!
> >>
> >> This is applicable for other APIs as well. Your current API
> >> implementation is mostly pass-through. A stateful will be better.
> >>
> >
> > Yes, the same meter profiles can potentially be shared for a group of
> ethdev ports, but unfortunately we cannot do this with the current ethdev
> API, which is per port with no sharing ability between groups of ports.
> >
> > Here we are lucky to have just a read-only configuration template that
> needs to be shared amongst ports, so the quick workaround is to define the
> same profile for each port at the expense of some (small) work duplication.
> Hopefully this is OK with you?
> >
> Is that mean you will create the meter profile template first and then
> apply/remove that on a port?
> 

Meter profile is just the configuration params (configuration template) that can be applied to many meter objects.

Approach A (my proposal): Keep all API functions per port, including meter profile create, including meter create. So in the likely case that meters on different ports use the same configuration, the same profile needs to be registered once for each port.

Approach B (your suggestion, if I got it right): Have a global list of profiles maintained internally by the library. This allows using the same profile on different ports, so no need to register the same profile explicitly for each port.

The reason I don't favour approach B  is it requires maintaining static global data in the library, but I don't see any tricky implications with either A or B.

Do you have strong preference towards B?


> how about adding a use-count to the profile?
> 

Yes, this is already part of the current proposal: the number of meter objects that share the same profile (i.e. configuration template) is counted, so the profile can be deleted only when it does not have any users (i.e. meter objects).

> On a different lines, can we do following
> 1. Metering profile is not applied to a port.  Metering object maintain
> the use-count.

Not sure I understand your statement on: "metering object maintain the use-count". Maybe we have a terminology misalignment on meter profile and meter object and I am not fully getting your point?

In my mind this is approach B from above. Also the above statement should be corrected to: metering _profile_ maintain the use-count (of how many metering objects are currently using it, i.e. use the same configuration template)?

> 2. metering object is applied to the port, which in turn contains
> metering profile.
> 

Yes, this is approach A from above :)


> Regards,
> Hemant

Regards,
Cristian

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

* Re: [PATCH 3/3] rte_flow: add new action for traffic metering and policing
  2017-09-06 16:23       ` Adrien Mazarguil
@ 2017-09-19 16:36         ` Dumitrescu, Cristian
  2017-09-19 17:00           ` Adrien Mazarguil
  0 siblings, 1 reply; 64+ messages in thread
From: Dumitrescu, Cristian @ 2017-09-19 16:36 UTC (permalink / raw)
  To: Adrien Mazarguil; +Cc: dev, thomas, jerin.jacob, hemant.agrawal

Hi Adrien,

> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Wednesday, September 6, 2017 5:23 PM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Cc: dev@dpdk.org; thomas@monjalon.net;
> jerin.jacob@caviumnetworks.com; hemant.agrawal@nxp.com
> Subject: Re: [PATCH 3/3] rte_flow: add new action for traffic metering and
> policing
> 
> Hi Cristian,
> 
> This commit should probably come first in the series since the rest relies
> on it, right?
> 

Yes, will do in V2.

> Subject line does not conform past commits, it should start with "ethdev:"
> and not mention "rte_flow" (use "flow API").
> 

Yes, sir!

> On Sat, Aug 26, 2017 at 01:06:13AM +0100, Cristian Dumitrescu wrote:
> > Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> 
> A short description of what this new item does and why it's added is
> necessary. Context provided by the rest of the series will not always be
> available.
> 

Yes, will add here the relevant description, which is currently only in the cover letter.

> More comments below.
> 
> > ---
> >  lib/librte_ether/rte_flow.h | 22 ++++++++++++++++++++++
> >  1 file changed, 22 insertions(+)
> >
> > diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> > index bba6169..5569a87 100644
> > --- a/lib/librte_ether/rte_flow.h
> > +++ b/lib/librte_ether/rte_flow.h
> > @@ -915,6 +915,14 @@ enum rte_flow_action_type {
> >  	 * See struct rte_flow_action_vf.
> >  	 */
> >  	RTE_FLOW_ACTION_TYPE_VF,
> > +
> > +	/**
> > +	 * Traffic metering and policing (MTR).
> > +	 *
> > +	 * See struct rte_flow_action_meter.
> > +	 * See file rte_mtr.h for MTR object configuration.
> > +	 */
> > +	RTE_FLOW_ACTION_TYPE_METER,
> >  };
> >
> >  /**
> > @@ -1008,6 +1016,20 @@ struct rte_flow_action_vf {
> >  };
> >
> >  /**
> > + * RTE_FLOW_ACTION_TYPE_METER
> > + *
> > + * Traffic metering and policing (MTR).
> > + *
> > + * Packets matched by items of this type can be either dropped or passed
> to the
> > + * next item with their color set by the MTR object.
> > + *
> > + * Non-terminating by default.
> > + */
> > +struct rte_flow_action_meter {
> > +	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create().
> */
> > +};
> > +
> 
> Default mask definition is missing.
> 

I do not understand this comment. This is a flow action, not a flow item (that might be a packet field with an associated mask); this mtr_id is similar to queue ID/index/VF ID from other flow actions, none having any mask attached. Adrien, can you please clarify?

> > +/**
> >   * Definition of a single action.
> >   *
> >   * A list of actions is terminated by a END action.
> > --
> > 2.7.4
> >
> 
> Even if MTR is a separate API, please add to this commit:
> 
> - Documentation update: guides/prog_guide/rte_flow.rst
> - Testpmd update: app/test-pmd/cmdline_flow.c
> - Testpmd documentation update:
> doc/guides/testpmd_app_ug/testpmd_funcs.rst
> 
> You can find examples in previous commits related to rte_flow.
> 

All of these items are a must and will get done, but do they have to be done in the same patch set?

My plan was to introduce test-pmd updates through separate patch sets after the API is accepted. I know you had these items done in the same patch set for rte_flow, but there are other APIs such as eventdev and ethdev traffic management which introduced sample app one release later.

> --
> Adrien Mazarguil
> 6WIND

Regards,
Cristian

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

* Re: [PATCH 3/3] rte_flow: add new action for traffic metering and policing
  2017-09-19 16:36         ` Dumitrescu, Cristian
@ 2017-09-19 17:00           ` Adrien Mazarguil
  2017-10-06 10:02             ` Dumitrescu, Cristian
  0 siblings, 1 reply; 64+ messages in thread
From: Adrien Mazarguil @ 2017-09-19 17:00 UTC (permalink / raw)
  To: Dumitrescu, Cristian; +Cc: dev, thomas, jerin.jacob, hemant.agrawal

Hi Cristian,

On Tue, Sep 19, 2017 at 04:36:50PM +0000, Dumitrescu, Cristian wrote:
<snip>
> > >  /**
> > > + * RTE_FLOW_ACTION_TYPE_METER
> > > + *
> > > + * Traffic metering and policing (MTR).
> > > + *
> > > + * Packets matched by items of this type can be either dropped or passed
> > to the
> > > + * next item with their color set by the MTR object.
> > > + *
> > > + * Non-terminating by default.
> > > + */
> > > +struct rte_flow_action_meter {
> > > +	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create().
> > */
> > > +};
> > > +
> > 
> > Default mask definition is missing.
> > 
> 
> I do not understand this comment. This is a flow action, not a flow item (that might be a packet field with an associated mask); this mtr_id is similar to queue ID/index/VF ID from other flow actions, none having any mask attached. Adrien, can you please clarify?

Yes, I actually misread it as a pattern item definition for some
reason. Nothing to see here, move along!

> 
> > > +/**
> > >   * Definition of a single action.
> > >   *
> > >   * A list of actions is terminated by a END action.
> > > --
> > > 2.7.4
> > >
> > 
> > Even if MTR is a separate API, please add to this commit:
> > 
> > - Documentation update: guides/prog_guide/rte_flow.rst
> > - Testpmd update: app/test-pmd/cmdline_flow.c
> > - Testpmd documentation update:
> > doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > 
> > You can find examples in previous commits related to rte_flow.
> > 
> 
> All of these items are a must and will get done, but do they have to be done in the same patch set?

That'd be much better as far as I'm involved in this review (rte_flow
changes). You should put them in the same patch as the above.

> My plan was to introduce test-pmd updates through separate patch sets after the API is accepted. I know you had these items done in the same patch set for rte_flow, but there are other APIs such as eventdev and ethdev traffic management which introduced sample app one release later.

In that case, could you split these changes in two parts?

This patch could bring the basic MTR action support in testpmd, by this I
mean the ability to type a flow command with such an action and not get
rejected with a "bad arguments" error since it is actually part of the API,
even if nothing is connected to that action at this point. The rule should
however get rejected by its lack of support in the underlying PMD.

Same idea for rte_flow and testpmd documentation update, this patch only
needs the minimum amount describing what this action is without a link to
the actual MTR documentation, which is not present at this point.

Subsequent commits shall update these as they complete the MTR API.

-- 
Adrien Mazarguil
6WIND

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

* Re: [PATCH 2/3] ethdev: add new rte_mtr API for traffic metering and policing
  2017-08-26  0:06     ` [PATCH 2/3] ethdev: add new rte_mtr API " Cristian Dumitrescu
  2017-09-01  8:09       ` Hemant Agrawal
@ 2017-09-21 13:20       ` Thomas Monjalon
  2017-10-06 10:03         ` Dumitrescu, Cristian
  1 sibling, 1 reply; 64+ messages in thread
From: Thomas Monjalon @ 2017-09-21 13:20 UTC (permalink / raw)
  To: Cristian Dumitrescu; +Cc: dev, adrien.mazarguil, jerin.jacob, hemant.agrawal

26/08/2017 02:06, Cristian Dumitrescu:
> +DPDK_17.11 {
> +       global:
> +
> +       rte_eth_dev_mtr_ops_get;
> +       rte_mtr_meter_profile_add;
> +       rte_mtr_meter_profile_delete;
> +       rte_mtr_create;
> +       rte_mtr_destroy;
> +       rte_mtr_meter_profile_update;
> +       rte_mtr_policer_action_update;
> +       rte_mtr_stats_update;
> +       rte_mtr_stats_read;
> +
> +} DPDK_17.08;

This API is experimental. So you should not version it in 17.11.
You can look how it was done for EAL:

EXPERIMENTAL {
    global:
...
} DPDK_17.11;

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

* Re: [PATCH 0/3] rte_mtr: generic ethdev API for metering and policing
  2017-08-26  0:06   ` [PATCH 0/3] rte_mtr: generic ethdev API for " Cristian Dumitrescu
                       ` (2 preceding siblings ...)
  2017-08-26  0:06     ` [PATCH 3/3] rte_flow: add new action " Cristian Dumitrescu
@ 2017-09-21 13:28     ` Thomas Monjalon
  3 siblings, 0 replies; 64+ messages in thread
From: Thomas Monjalon @ 2017-09-21 13:28 UTC (permalink / raw)
  To: Cristian Dumitrescu
  Cc: dev, adrien.mazarguil, jerin.jacob, hemant.agrawal, alexr,
	alejandro.lucero, ferruh.yigit, rahul.lakkireddy, ajit.khaparde,
	arybchenko

26/08/2017 02:06, Cristian Dumitrescu:
> This patch set introduces an ethdev-based generic API for Traffic
> Metering and Policing (MTR), which is yet another standard RX offload for
> Ethernet devices.

Thanks for bringing yet another offload API.

What are the expected devices to implement this API?

It would be nice to have reviews and acks from other vendors.

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

* [PATCH V2 0/5] rte_mtr: generic ethdev api for metering and policing
  2017-08-26  0:06     ` [PATCH 1/3] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
  2017-09-13  5:50       ` Jerin Jacob
@ 2017-10-05 13:09       ` Cristian Dumitrescu
  2017-10-05 13:09         ` [PATCH V2 1/5] ethdev: add new flow action " Cristian Dumitrescu
                           ` (4 more replies)
  1 sibling, 5 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-05 13:09 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, hemant.agrawal,
	jerin.jacob, jasvinder.singh

This patch set introduces an ethdev-based generic API for Traffic
Metering and Policing (MTR), which is yet another standard RX offload for
Ethernet devices.

Similar to rte_flow and rte_tm APIs, the configuration of MTR objects is
done in their own namespace (rte_mtr) within the librte_ether library.
Metering and policing action typically sits on top of flow classification,
which is why MTR objects are enabled through a newly introduced flow
action, which is the only impact to flow API.

Q1: Why introduce ethdev-based traffic metering ad policing API?
A1: Traffic metering and policing is a standard RX offload for Ethernet
devices present in NICs, SoCs and NPUs across the industry.

Q2: What's the connection between the new rte_mtr API and the existing
librte_meter library?
A2: The existing librte_meter library provides a SW implementation for a
subset of the features exposed by this API. The rte_mtr API is agnostic to
whether the implementation is HW, SW or mixed HW-SW.

Q3: What's the connection between the new rte_mtr API and the existing
flow API?
A3: The MTR object is hooked into ethdev RX processing path using a newly
introduced flow action, which is the only impact to the flow API.
The configuration of MTR objects is done in separate namespace (rte_mtr)
outside of flow API.

Q4: Can the new flow API meter action drop packets? Is this a terminating
action or not?
A4: Although packets can be dropped by the newly introduced flow API meter
action, this action is non-terminating, i.e. the action list typically
contains at least one more action, which is a terminating action.
Depending on the policer actions configured for the MTR object, some
packets might be dropped while some packets passed to the next flow action
with their color set in the packet mbuf. For example, a typical policer
configuration is to drop the red packets while passing the green packets,
therefore a subsequent flow action needs to be configured to determine the
final destination of green packets.

Q5: Which are the main operations exposed for the MTR object?
A5: Traffic metering, policing and statistics update. Traffic metering
determines the color for the current packet (green, yellow, red) based on
the previous history for this flow as maintained by the MTR object.
The policer can do nothing, recolor or drop the packet. Stats are
maintained for MTR object, as configured.

Q6: Where is the output color stored for the current packet.
A6: struct rte_mbuf::sched::color.

Q7: Which are the supported metering algorithms?
A7: srTCM (RFC 2697), trTCM (RFC 2698 and RFC 4115).

Q8: Which are the supported policer actions?
A8: Recolor the packet (keep or change the color determined by metering)
or drop the packet.

Cristian Dumitrescu (5):
  ethdev: add new flow action for metering and policing
  ethdev: add new eth_dev_ops function for mtr ops get
  ethdev: add new API for traffic metering and policing
  doc: ethdev traffic metering and policing api
  app/testpmd: cli for traffic metering and policing

 MAINTAINERS                                        |    4 +
 app/test-pmd/Makefile                              |    1 +
 app/test-pmd/cmdline.c                             |   10 +
 app/test-pmd/cmdline_flow.c                        |   24 +
 app/test-pmd/cmdline_mtr.c                         | 1013 ++++++++++++++++++++
 app/test-pmd/cmdline_mtr.h                         |   49 +
 doc/api/doxy-api-index.md                          |    1 +
 doc/guides/prog_guide/index.rst                    |    1 +
 doc/guides/prog_guide/rte_flow.rst                 |   24 +
 .../prog_guide/traffic_metering_and_policing.rst   |   97 ++
 lib/librte_ether/Makefile                          |    3 +
 lib/librte_ether/rte_ethdev.h                      |    6 +
 lib/librte_ether/rte_ethdev_version.map            |   18 +
 lib/librte_ether/rte_flow.h                        |   22 +
 lib/librte_ether/rte_mtr.c                         |  229 +++++
 lib/librte_ether/rte_mtr.h                         |  723 ++++++++++++++
 lib/librte_ether/rte_mtr_driver.h                  |  221 +++++
 17 files changed, 2446 insertions(+)
 create mode 100644 app/test-pmd/cmdline_mtr.c
 create mode 100644 app/test-pmd/cmdline_mtr.h
 create mode 100644 doc/guides/prog_guide/traffic_metering_and_policing.rst
 create mode 100644 lib/librte_ether/rte_mtr.c
 create mode 100644 lib/librte_ether/rte_mtr.h
 create mode 100644 lib/librte_ether/rte_mtr_driver.h

-- 
2.7.4

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

* [PATCH V2 1/5] ethdev: add new flow action for metering and policing
  2017-10-05 13:09       ` [PATCH V2 0/5] rte_mtr: generic ethdev api for metering and policing Cristian Dumitrescu
@ 2017-10-05 13:09         ` Cristian Dumitrescu
  2017-10-06 13:57           ` Adrien Mazarguil
  2017-10-06 14:45           ` [PATCH V3 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
  2017-10-05 13:09         ` [PATCH V2 2/5] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
                           ` (3 subsequent siblings)
  4 siblings, 2 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-05 13:09 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, hemant.agrawal,
	jerin.jacob, jasvinder.singh

Metering and policing action typically sits on top of flow classification,
which is why MTR objects are enabled through a newly introduced flow
action.

The configuration of MTR objects is done in their own namespace (rte_mtr)
within the librte_ether library. The MTR object is hooked into ethdev RX
processing path using the "meter" flow action.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 doc/guides/prog_guide/rte_flow.rst | 24 ++++++++++++++++++++++++
 lib/librte_ether/rte_flow.h        | 22 ++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 662a912..6b9cdc2 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1354,6 +1354,30 @@ rule or if packets are not addressed to a VF in the first place.
    | ``vf``       | VF ID to redirect packets to   |
    +--------------+--------------------------------+
 
+Action: ``METER``
+^^^^^^^^^^^^^^^^^
+
+Applies a stage of metering and policing.
+
+The metering and policing (MTR) object has to be first created using the
+rte_mtr_create() API function. The ID of the MTR object is specified as
+action parameter. One or several meter actions can be added to the same
+flow. More than one flow can use the same MTR object through the meter
+action. The MTR object can be further updated or queried using the
+rte_mtr* API.
+
+- Non-terminating by default.
+
+.. _table_rte_flow_action_meter:
+
+.. table:: METER
+
+   +--------------+---------------+
+   | Field        | Value         |
+   +==============+===============+
+   | ``mtr_id``   | MTR object ID |
+   +--------------+---------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index bba6169..5569a87 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -915,6 +915,14 @@ enum rte_flow_action_type {
 	 * See struct rte_flow_action_vf.
 	 */
 	RTE_FLOW_ACTION_TYPE_VF,
+
+	/**
+	 * Traffic metering and policing (MTR).
+	 *
+	 * See struct rte_flow_action_meter.
+	 * See file rte_mtr.h for MTR object configuration.
+	 */
+	RTE_FLOW_ACTION_TYPE_METER,
 };
 
 /**
@@ -1008,6 +1016,20 @@ struct rte_flow_action_vf {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_METER
+ *
+ * Traffic metering and policing (MTR).
+ *
+ * Packets matched by items of this type can be either dropped or passed to the
+ * next item with their color set by the MTR object.
+ *
+ * Non-terminating by default.
+ */
+struct rte_flow_action_meter {
+	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create(). */
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.7.4

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

* [PATCH V2 2/5] ethdev: add new eth_dev_ops function for mtr ops get
  2017-10-05 13:09       ` [PATCH V2 0/5] rte_mtr: generic ethdev api for metering and policing Cristian Dumitrescu
  2017-10-05 13:09         ` [PATCH V2 1/5] ethdev: add new flow action " Cristian Dumitrescu
@ 2017-10-05 13:09         ` Cristian Dumitrescu
  2017-10-05 13:09         ` [PATCH V2 3/5] ethdev: add new api for traffic metering and policing Cristian Dumitrescu
                           ` (2 subsequent siblings)
  4 siblings, 0 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-05 13:09 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, hemant.agrawal,
	jerin.jacob, jasvinder.singh

Following similar approach as rte_flow and rte_tm for modularity reasons,
the ops for the new rte_mtr API are retrieved through a new eth_dev_ops
function.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
Changes in v2:
-None

Changes in v1 (from RFC [1]):
- Removed ethdev API function to get the MTR ops, as it is not needed
  (input from Thomas)

[1] RFC: http://www.dpdk.org/ml/archives/dev/2017-May/066888.html

 lib/librte_ether/rte_ethdev.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 99cdd54..a5802b0 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1424,6 +1424,9 @@ typedef int (*eth_filter_ctrl_t)(struct rte_eth_dev *dev,
 typedef int (*eth_tm_ops_get_t)(struct rte_eth_dev *dev, void *ops);
 /**< @internal Get Traffic Management (TM) operations on an Ethernet device */
 
+typedef int (*eth_mtr_ops_get_t)(struct rte_eth_dev *dev, void *ops);
+/**< @internal Get Trafffic Metering and Policing (MTR) operations */
+
 typedef int (*eth_get_dcb_info)(struct rte_eth_dev *dev,
 				 struct rte_eth_dcb_info *dcb_info);
 /**< @internal Get dcb information on an Ethernet device */
@@ -1548,6 +1551,9 @@ struct eth_dev_ops {
 
 	eth_tm_ops_get_t tm_ops_get;
 	/**< Get Traffic Management (TM) operations. */
+
+	eth_mtr_ops_get_t mtr_ops_get;
+	/**< Get Traffic Metering and Policing (MTR) operations. */
 };
 
 /**
-- 
2.7.4

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

* [PATCH V2 3/5] ethdev: add new api for traffic metering and policing
  2017-10-05 13:09       ` [PATCH V2 0/5] rte_mtr: generic ethdev api for metering and policing Cristian Dumitrescu
  2017-10-05 13:09         ` [PATCH V2 1/5] ethdev: add new flow action " Cristian Dumitrescu
  2017-10-05 13:09         ` [PATCH V2 2/5] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
@ 2017-10-05 13:09         ` Cristian Dumitrescu
  2017-10-05 13:09         ` [PATCH V2 4/5] doc: ethdev traffic metering and policing api Cristian Dumitrescu
  2017-10-05 13:09         ` [PATCH V2 5/5] app/testpmd: cli for traffic metering and policing Cristian Dumitrescu
  4 siblings, 0 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-05 13:09 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, hemant.agrawal,
	jerin.jacob, jasvinder.singh

This patch introduces new ethdev generic API for Traffic Metering and
Policing (MTR), which is yet another standard RX offload for Ethernet
devices.

Similar to rte_flow and rte_tm APIs, the configuration of MTR objects is
done in their own namespace (rte_mtr) within the librte_ether library.

Main features:
1. Traffic metering: determine the color for the current packet (green,
   yellow, red) based on history maintained by the MTR object. Supported
   algorithms: srTCM (RFC 2697), trTCM (RFC 2698 and RFC 4115).
2. Policing (per meter output color actions): re-color the packet (keep
   or change the meter output color) or drop the packet.
3. Statistics
4. Capability API

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
Changes in v2:
- Implemented input from Hemant:
     - Added support for RFC 4115 trTCM algorithm
     - Added support for meter pass-through mode: see API functions
       rte_mtr_meter_enable() and rte_mtr_meter_disable()
- Implemented input from Jerin:
     - Added capability API
- Implemented input from Thomas:
     - Added new API functions under the EXPERIMENTAL section in map file
- Improved the mechanism for MTR object chaining: each MTR object can be
  configured whther to read input color from a previous MTR object in the
  same flow (if any) of from DSCP traslation table
- Improved run-time update functions
- Doxygen: added more descriptions, small fixes

Changes in v1 (from RFC [1]):
- Implemented input from Thomas:
     - Added EXPERIMENTAL tag in rte_mtr.h and MANTAINERS for this new API
- Implemented input from Adrien:
     - Added more Doxygen comments to re-inforce relationship between MTR and
       flow
- Doxygen: added hook in doxy-api-index.md

[1] RFC: http://www.dpdk.org/ml/archives/dev/2017-May/066888.html

 MAINTAINERS                             |   4 +
 doc/api/doxy-api-index.md               |   1 +
 lib/librte_ether/Makefile               |   3 +
 lib/librte_ether/rte_ethdev_version.map |  18 +
 lib/librte_ether/rte_mtr.c              | 229 ++++++++++
 lib/librte_ether/rte_mtr.h              | 723 ++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_mtr_driver.h       | 221 ++++++++++
 7 files changed, 1199 insertions(+)
 create mode 100644 lib/librte_ether/rte_mtr.c
 create mode 100644 lib/librte_ether/rte_mtr.h
 create mode 100644 lib/librte_ether/rte_mtr_driver.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 8df2a7f..f9aa787 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -260,6 +260,10 @@ M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
 T: git://dpdk.org/next/dpdk-next-tm
 F: lib/librte_ether/rte_tm*
 
+Traffic Metering and Policing API - EXPERIMENTAL
+M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
+F: lib/librte_ether/rte_mtr*
+
 Crypto API
 M: Declan Doherty <declan.doherty@intel.com>
 F: lib/librte_cryptodev/
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 19e0d4f..b2342a9 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -41,6 +41,7 @@ The public API headers are grouped by topics:
   [ethctrl]            (@ref rte_eth_ctrl.h),
   [rte_flow]           (@ref rte_flow.h),
   [rte_tm]             (@ref rte_tm.h),
+  [rte_mtr]            (@ref rte_mtr.h),
   [cryptodev]          (@ref rte_cryptodev.h),
   [eventdev]           (@ref rte_eventdev.h),
   [metrics]            (@ref rte_metrics.h),
diff --git a/lib/librte_ether/Makefile b/lib/librte_ether/Makefile
index 201cb96..35ba5d9 100644
--- a/lib/librte_ether/Makefile
+++ b/lib/librte_ether/Makefile
@@ -46,6 +46,7 @@ LIBABIVER := 7
 SRCS-y += rte_ethdev.c
 SRCS-y += rte_flow.c
 SRCS-y += rte_tm.c
+SRCS-y += rte_mtr.c
 SRCS-y += ethdev_profile.c
 
 #
@@ -60,5 +61,7 @@ SYMLINK-y-include += rte_flow.h
 SYMLINK-y-include += rte_flow_driver.h
 SYMLINK-y-include += rte_tm.h
 SYMLINK-y-include += rte_tm_driver.h
+SYMLINK-y-include += rte_mtr.h
+SYMLINK-y-include += rte_mtr_driver.h
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_ether/rte_ethdev_version.map b/lib/librte_ether/rte_ethdev_version.map
index 07f9e17..c8f59a0 100644
--- a/lib/librte_ether/rte_ethdev_version.map
+++ b/lib/librte_ether/rte_ethdev_version.map
@@ -194,3 +194,21 @@ DPDK_17.11 {
 	rte_eth_dev_reset;
 
 } DPDK_17.08;
+
+EXPERIMENTAL {
+	global:
+
+	rte_mtr_capabilities_get;
+	rte_mtr_meter_profile_add;
+	rte_mtr_meter_profile_delete;
+	rte_mtr_create;
+	rte_mtr_destroy;
+	rte_mtr_meter_enable;
+	rte_mtr_meter_disable;
+	rte_mtr_meter_profile_update;
+	rte_mtr_meter_dscp_table_update;
+	rte_mtr_policer_actions_update;
+	rte_mtr_stats_update;
+	rte_mtr_stats_read;
+
+} DPDK_17.11;
diff --git a/lib/librte_ether/rte_mtr.c b/lib/librte_ether/rte_mtr.c
new file mode 100644
index 0000000..6526a97
--- /dev/null
+++ b/lib/librte_ether/rte_mtr.c
@@ -0,0 +1,229 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+
+#include <rte_errno.h>
+#include "rte_ethdev.h"
+#include "rte_mtr_driver.h"
+#include "rte_mtr.h"
+
+/* Get generic traffic metering & policing operations structure from a port. */
+const struct rte_mtr_ops *
+rte_mtr_ops_get(uint8_t port_id, struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	const struct rte_mtr_ops *ops;
+
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		rte_mtr_error_set(error,
+			ENODEV,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			rte_strerror(ENODEV));
+		return NULL;
+	}
+
+	if ((dev->dev_ops->mtr_ops_get == NULL) ||
+		(dev->dev_ops->mtr_ops_get(dev, &ops) != 0) ||
+		(ops == NULL)) {
+		rte_mtr_error_set(error,
+			ENOSYS,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			rte_strerror(ENOSYS));
+		return NULL;
+	}
+
+	return ops;
+}
+
+#define RTE_MTR_FUNC(port_id, func)			\
+({							\
+	const struct rte_mtr_ops *ops =			\
+		rte_mtr_ops_get(port_id, error);		\
+	if (ops == NULL)					\
+		return -rte_errno;			\
+							\
+	if (ops->func == NULL)				\
+		return -rte_mtr_error_set(error,		\
+			ENOSYS,				\
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,	\
+			NULL,				\
+			rte_strerror(ENOSYS));		\
+							\
+	ops->func;					\
+})
+
+/* MTR capabilities get */
+int
+rte_mtr_capabilities_get(uint8_t port_id,
+	struct rte_mtr_capabilities *cap,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, capabilities_get)(dev,
+		cap, error);
+}
+
+/* MTR meter profile add */
+int
+rte_mtr_meter_profile_add(uint8_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);
+}
+
+/** MTR meter profile delete */
+int
+rte_mtr_meter_profile_delete(uint8_t port_id,
+	uint32_t meter_profile_id,
+	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);
+}
+
+/** MTR object create */
+int
+rte_mtr_create(uint8_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);
+}
+
+/** MTR object destroy */
+int
+rte_mtr_destroy(uint8_t port_id,
+	uint32_t mtr_id,
+	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 object meter enable */
+int
+rte_mtr_meter_enable(uint8_t port_id,
+	uint32_t mtr_id,
+	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 object meter disable */
+int
+rte_mtr_meter_disable(uint8_t port_id,
+	uint32_t mtr_id,
+	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 object meter profile update */
+int
+rte_mtr_meter_profile_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint32_t meter_profile_id,
+	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 object meter DSCP table update */
+int
+rte_mtr_meter_dscp_table_update(uint8_t port_id,
+	uint32_t mtr_id,
+	enum rte_mtr_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 object policer action update */
+int
+rte_mtr_policer_actions_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint32_t action_mask,
+	enum rte_mtr_policer_action *actions,
+	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);
+}
+
+/** MTR object enabled stats update */
+int
+rte_mtr_stats_update(uint8_t port_id,
+	uint32_t mtr_id,
+	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 object stats read */
+int
+rte_mtr_stats_read(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error)
+{
+	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);
+}
diff --git a/lib/librte_ether/rte_mtr.h b/lib/librte_ether/rte_mtr.h
new file mode 100644
index 0000000..f0f897f
--- /dev/null
+++ b/lib/librte_ether/rte_mtr.h
@@ -0,0 +1,723 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation.
+ *   Copyright(c) 2017 NXP.
+ *   Copyright(c) 2017 Cavium.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __INCLUDE_RTE_MTR_H__
+#define __INCLUDE_RTE_MTR_H__
+
+/**
+ * @file
+ * RTE Generic Traffic Metering and Policing API
+ *
+ * This interface provides the ability to configure the traffic metering and
+ * policing (MTR) in a generic way.
+ *
+ * The processing done for each input packet hitting a MTR object is:
+ *    A) Traffic metering: The packet is assigned a color (the meter output
+ *       color), based on the previous history of the flow reflected in the
+ *       current state of the MTR object, according to the specific traffic
+ *       metering algorithm. The traffic metering algorithm can typically work
+ *       in color aware mode, in which case the input packet already has an
+ *       initial color (the input color), or in color blind mode, which is
+ *       equivalent to considering all input packets initially colored as green.
+ *    B) Policing: There is a separate policer action configured for each meter
+ *       output color, which can:
+ *          a) Drop the packet.
+ *          b) Keep the same packet color: the policer output color matches the
+ *             meter output color (essentially a no-op action).
+ *          c) Recolor the packet: the policer output color is different 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).
+ *    C) Statistics: The set of counters maintained for each MTR object is
+ *       configurable and subject to the implementation support. This set
+ *       includes the number of packets and bytes dropped or passed for each
+ *       output color.
+ *
+ * Once successfully created, an MTR object is linked to one or several flows
+ * through the meter action of the flow API.
+ *    A) Whether an MTR object is private to a flow or potentially shared by
+ *       several flows has to be specified at creation time.
+ *    B) Several meter actions can be potentially registered for the same flow.
+ *
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ */
+#include <stdint.h>
+
+#include <rte_common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Color
+ */
+enum rte_mtr_color {
+	RTE_MTR_GREEN = 0, /**< Green */
+	RTE_MTR_YELLOW, /**< Yellow */
+	RTE_MTR_RED, /**< Red */
+	RTE_MTR_COLORS /**< Number of colors. */
+};
+
+/**
+ * Statistics counter type
+ */
+enum rte_mtr_stats_type {
+	/** Number of packets passed as green by the policer. */
+	RTE_MTR_STATS_N_PKTS_GREEN = 1 << 0,
+
+	/** Number of bytes passed as green by the policer. */
+	RTE_MTR_STATS_N_BYTES_GREEN = 1 << 1,
+
+	/** Number of packets passed as yellow by the policer. */
+	RTE_MTR_STATS_N_PKTS_YELLOW = 1 << 2,
+
+	/** Number of bytes passed as yellow by the policer. */
+	RTE_MTR_STATS_N_BYTES_YELLOW = 1 << 3,
+
+	/** Number of packets passed as red by the policer. */
+	RTE_MTR_STATS_N_PKTS_RED = 1 << 4,
+
+	/** Number of bytes passed as red by the policer. */
+	RTE_MTR_STATS_N_BYTES_RED = 1 << 5,
+
+	/** Number of packets dropped by the policer. */
+	RTE_MTR_STATS_N_PKTS_DROPPED = 1 << 6,
+
+	/** Number of bytes dropped by the policer. */
+	RTE_MTR_STATS_N_BYTES_DROPPED = 1 << 7,
+};
+
+/**
+ * Statistics counters
+ */
+struct rte_mtr_stats {
+	/** Number of packets passed by the policer (per color). */
+	uint64_t n_pkts[RTE_MTR_COLORS];
+
+	/** Number of bytes passed by the policer (per color). */
+	uint64_t n_bytes[RTE_MTR_COLORS];
+
+	/** Number of packets dropped by the policer. */
+	uint64_t n_pkts_dropped;
+
+	/** Number of bytes passed by the policer. */
+	uint64_t n_bytes_dropped;
+};
+
+/**
+ * Traffic metering algorithms
+ */
+enum rte_mtr_algorithm {
+	/** Single Rate Three Color Marker (srTCM) - IETF RFC 2697. */
+	RTE_MTR_SRTCM_RFC2697,
+
+	/** Two Rate Three Color Marker (trTCM) - IETF RFC 2698. */
+	RTE_MTR_TRTCM_RFC2698,
+
+	/** Two Rate Three Color Marker (trTCM) - IETF RFC 4115. */
+	RTE_MTR_TRTCM_RFC4115,
+};
+
+/**
+ * Meter profile
+ */
+struct rte_mtr_meter_profile {
+	/** Traffic metering algorithm. */
+	enum rte_mtr_algorithm alg;
+
+	RTE_STD_C11
+	union {
+		/** Items only valid when *alg* is set to srTCM - RFC 2697. */
+		struct {
+			/** Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/** Committed Burst Size (CBS) (bytes). */
+			uint64_t cbs;
+
+			/** Excess Burst Size (EBS) (bytes). */
+			uint64_t ebs;
+		} srtcm_rfc2697;
+
+		/** Items only valid when *alg* is set to trTCM - RFC 2698. */
+		struct {
+			/** Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/** Peak Information Rate (PIR) (bytes/second). */
+			uint64_t pir;
+
+			/** Committed Burst Size (CBS) (byes). */
+			uint64_t cbs;
+
+			/** Peak Burst Size (PBS) (bytes). */
+			uint64_t pbs;
+		} trtcm_rfc2698;
+
+		/** Items only valid when *alg* is set to trTCM - RFC 4115. */
+		struct {
+			/** Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/** Excess Information Rate (EIR) (bytes/second). */
+			uint64_t eir;
+
+			/** Committed Burst Size (CBS) (byes). */
+			uint64_t cbs;
+
+			/** Excess Burst Size (EBS) (bytes). */
+			uint64_t ebs;
+		} trtcm_rfc4115;
+	};
+};
+
+/**
+ * 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
+ *
+ * @see enum rte_mtr_stats_type
+ */
+struct rte_mtr_params {
+	/** Meter profile ID. */
+	uint32_t meter_profile_id;
+
+	/** 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
+	 * determined by the latest MTR object in the same flow is used as the
+	 * input color by the current MTR object, otherwise the current MTR
+	 * object uses the *dscp_table* to determine the input color. When zero:
+	 * the color determined by any previous MTR object in same flow is
+	 * ignored by the current MTR object, which uses the *dscp_table* to
+	 * determine the input color.
+	 */
+	int use_prev_mtr_color;
+
+	/** Meter input color. 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). The color blind mode
+	 * is configured by setting *use_prev_mtr_color* to 0 and *dscp_table*
+	 * to either NULL or to an all-green populated table. When
+	 * *use_prev_mtr_color* is non-zero value or when *dscp_table* contains
+	 * at least one yellow or red color element, then the color aware mode
+	 * is configured.
+	 */
+	enum rte_mtr_color *dscp_table;
+
+	/** Non-zero to enable the meter, zero to disable the meter at the time
+	 * of MTR object creation.
+	 * @see rte_mtr_meter_disable()
+	 */
+	int meter_enable;
+
+	/** Policer actions (per meter output color). */
+	enum rte_mtr_policer_action action[RTE_MTR_COLORS];
+
+	/** Set of stats counters to be enabled.
+	 * @see enum rte_mtr_stats_type
+	 */
+	uint64_t stats_mask;
+};
+
+/**
+ * MTR capabilities
+ */
+struct rte_mtr_capabilities {
+	/** Maximum number of MTR objects. */
+	uint32_t n_max;
+
+	/** Maximum number of MTR objects that can be shared by multiple flows.
+	 * The value of zero indicates that shared MTR objects are not
+	 * supported. The maximum value is *n_max*.
+	 */
+	uint32_t n_shared_max;
+
+	/** When non-zero, this flag indicates that all the MTR objects that
+	 * cannot be shared by multiple flows have identical capability set.
+	 */
+	int identical;
+
+	/** When non-zero, this flag indicates that all the MTR objects that
+	 * can be shared by multiple flows have identical capability set.
+	 */
+	int shared_identical;
+
+	/** Maximum number of flows that can share the same MTR object. The
+	 * value of zero is invalid. The value of 1 means that shared MTR
+	 * objects not supported.
+	 */
+	uint32_t shared_n_flows_per_mtr_max;
+
+	/** Maximum number of MTR objects that can be part of the same flow. The
+	 * value of zero is invalid. The value of 1 indicates that MTR object
+	 * chaining is not supported. The maximum value is *n_max*.
+	 */
+	uint32_t chaining_n_mtrs_per_flow_max;
+
+	/**
+	 * When non-zero, it indicates that the packet color identified by one
+	 * MTR object can be used as the packet input color by any subsequent
+	 * MTR object from the same flow. When zero, it indicates that the color
+	 * determined by one MTR object is always ignored by any subsequent MTR
+	 * object from the same flow. Only valid when MTR chaining is supported,
+	 * i.e. *chaining_n_mtrs_per_flow_max* is greater than 1. When non-zero,
+	 * it also means that the color aware mode is supported by at least one
+	 * metering algorithm.
+	 */
+	int chaining_use_prev_mtr_color_supported;
+
+	/**
+	 * When non-zero, it indicates that the packet color identified by one
+	 * MTR object is always used as the packet input color by any subsequent
+	 * MTR object that is part of the same flow. When zero, it indicates
+	 * that whether the color determined by one MTR object is either ignored
+	 * or used as the packet input color by any subsequent MTR object from
+	 * the same flow is individually configurable for each MTR object. Only
+	 * valid when *chaining_use_prev_mtr_color_supported* is non-zero.
+	 */
+	int chaining_use_prev_mtr_color_enforced;
+
+	/** Maximum number of MTR objects that can have their meter configured
+	 * to run the srTCM RFC 2697 algorithm. The value of 0 indicates this
+	 * metering algorithm is not supported. The maximum value is *n_max*.
+	 */
+	uint32_t meter_srtcm_rfc2697_n_max;
+
+	/** Maximum number of MTR objects that can have their meter configured
+	 * to run the trTCM RFC 2698 algorithm. The value of 0 indicates this
+	 * metering algorithm is not supported. The maximum value is *n_max*.
+	 */
+	uint32_t meter_trtcm_rfc2698_n_max;
+
+	/** Maximum number of MTR objects that can have their meter configured
+	 * to run the trTCM RFC 4115 algorithm. The value of 0 indicates this
+	 * metering algorithm is not supported. The maximum value is *n_max*.
+	 */
+	uint32_t meter_trtcm_rfc4115_n_max;
+
+	/** Maximum traffic rate that can be metered by a single MTR object. For
+	 * srTCM RFC 2697, this is the maximum CIR rate. For trTCM RFC 2698,
+	 * this is the maximum PIR rate. For trTCM RFC 4115, this is the maximum
+	 * value for the sum of PIR and EIR rates.
+	 */
+	uint64_t meter_rate_max;
+
+	/**
+	 * When non-zero, it indicates that color aware mode is supported for
+	 * the srTCM RFC 2697 metering algorithm.
+	 */
+	int color_aware_srtcm_rfc2697_supported;
+
+	/**
+	 * When non-zero, it indicates that color aware mode is supported for
+	 * the trTCM RFC 2698 metering algorithm.
+	 */
+	int color_aware_trtcm_rfc2698_supported;
+
+	/**
+	 * When non-zero, it indicates that color aware mode is supported for
+	 * the trTCM RFC 4115 metering algorithm.
+	 */
+	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
+	 */
+	uint64_t stats_mask;
+};
+
+/**
+ * Verbose error types.
+ *
+ * Most of them provide the type of the object referenced by struct
+ * rte_mtr_error::cause.
+ */
+enum rte_mtr_error_type {
+	RTE_MTR_ERROR_TYPE_NONE, /**< No error. */
+	RTE_MTR_ERROR_TYPE_UNSPECIFIED, /**< Cause unspecified. */
+	RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+	RTE_MTR_ERROR_TYPE_METER_PROFILE,
+	RTE_MTR_ERROR_TYPE_MTR_ID,
+	RTE_MTR_ERROR_TYPE_MTR_PARAMS,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED,
+	RTE_MTR_ERROR_TYPE_STATS_MASK,
+	RTE_MTR_ERROR_TYPE_STATS,
+	RTE_MTR_ERROR_TYPE_SHARED,
+};
+
+/**
+ * Verbose error structure definition.
+ *
+ * This object is normally allocated by applications and set by PMDs, the
+ * message points to a constant string which does not need to be freed by
+ * the application, however its pointer can be considered valid only as long
+ * as its associated DPDK port remains configured. Closing the underlying
+ * device or unloading the PMD invalidates it.
+ *
+ * Both cause and message may be NULL regardless of the error type.
+ */
+struct rte_mtr_error {
+	enum rte_mtr_error_type type; /**< Cause field and error type. */
+	const void *cause; /**< Object responsible for the error. */
+	const char *message; /**< Human-readable error message. */
+};
+
+/**
+ * MTR capabilities get
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[out] cap
+ *   MTR capabilities. 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.
+ */
+int
+rte_mtr_capabilities_get(uint8_t port_id,
+	struct rte_mtr_capabilities *cap,
+	struct rte_mtr_error *error);
+
+/**
+ * Meter profile add
+ *
+ * Create a new meter profile with ID set to *meter_profile_id*. 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.
+ */
+int
+rte_mtr_meter_profile_add(uint8_t port_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_meter_profile *profile,
+	struct rte_mtr_error *error);
+
+/**
+ * Meter profile delete
+ *
+ * Delete an existing meter profile. This operation fails when there is
+ * currently at least one user (i.e. MTR object) of this profile.
+ *
+ * @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[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_profile_delete(uint8_t port_id,
+	uint32_t meter_profile_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
+ * associated flow action for traffic metering and policing.
+ *
+ * @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
+ *   Non-zero when this MTR object can be shared by multiple flows, zero when
+ *   this MTR object can be used by a single flow.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_flow_action_type::RTE_FLOW_ACTION_TYPE_METER
+ */
+int
+rte_mtr_create(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_params *params,
+	int shared,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object destroy
+ *
+ * Delete an existing MTR object. This operation fails when there is currently
+ * at least one user (i.e. flow) of this MTR object.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be valid.
+ *   created for the current port.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_destroy(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object meter disable
+ *
+ * Disable the meter of an existing MTR object. In disabled state, the meter of
+ * the current MTR object works in pass-through mode, meaning that for each
+ * input packet the meter output color is always the same as the input color. In
+ * particular, when the meter of the current MTR object is configured in color
+ * blind mode, the input color is always green, so the meter output color is
+ * also always green. Note that the policer and the statistics of the current
+ * MTR object are working as usual while the meter is disabled. No action is
+ * taken and this function returns successfully when the meter of the current
+ * MTR object is already disabled.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_disable(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object meter enable
+ *
+ * Enable the meter of an existing MTR object. If the MTR object has its meter
+ * already enabled, then no action is taken and this function returns
+ * successfully.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_enable(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object meter profile 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] meter_profile_id
+ *   Meter profile ID for the current MTR object. Needs to be valid.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_profile_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_error *error);
+
+/**
+ * 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] 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
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_dscp_table_update(uint8_t port_id,
+	uint32_t mtr_id,
+	enum rte_mtr_color *dscp_table,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object policer actions 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[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_policer_actions_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint32_t action_mask,
+	enum rte_mtr_policer_action *actions,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object enabled statistics counters 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] stats_mask
+ *   Mask of statistics counter types to be enabled for the current MTR object.
+ *   Any statistics counter type not included in this set is to be disabled for
+ *   the current MTR object.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_mtr_stats_type
+ */
+int
+rte_mtr_stats_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint64_t stats_mask,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object statistics counters read
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be valid.
+ * @param[out] stats
+ *   When non-NULL, it contains the current value for the statistics counters
+ *   enabled for the current MTR object.
+ * @param[out] stats_mask
+ *   When non-NULL, it contains the mask of statistics counter types that are
+ *   currently enabled for this MTR object, indicating which of the counters
+ *   retrieved with the *stats* structure are valid.
+ * @param[in] clear
+ *   When this parameter has a non-zero value, the statistics counters are
+ *   cleared (i.e. set to zero) immediately after they have been read,
+ *   otherwise the statistics counters are left untouched.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_mtr_stats_type
+ */
+int
+rte_mtr_stats_read(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_RTE_MTR_H__ */
diff --git a/lib/librte_ether/rte_mtr_driver.h b/lib/librte_ether/rte_mtr_driver.h
new file mode 100644
index 0000000..bb7deed
--- /dev/null
+++ b/lib/librte_ether/rte_mtr_driver.h
@@ -0,0 +1,221 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __INCLUDE_RTE_MTR_DRIVER_H__
+#define __INCLUDE_RTE_MTR_DRIVER_H__
+
+/**
+ * @file
+ * RTE Generic Traffic Metering and Policing API (Driver Side)
+ *
+ * This file provides implementation helpers for internal use by PMDs, they
+ * are not intended to be exposed to applications and are not subject to ABI
+ * versioning.
+ */
+
+#include <stdint.h>
+
+#include <rte_errno.h>
+#include "rte_ethdev.h"
+#include "rte_mtr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int (*rte_mtr_capabilities_get_t)(struct rte_eth_dev *dev,
+	struct rte_mtr_capabilities *cap,
+	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,
+	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_error *error);
+/**< @internal MTR meter profile delete */
+
+typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	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_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_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_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_error *error);
+/**< @internal MTR object meter profile update */
+
+typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	enum rte_mtr_color *dscp_table,
+	struct rte_mtr_error *error);
+/**< @internal MTR object meter DSCP table update */
+
+typedef int (*rte_mtr_policer_actions_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	uint32_t action_mask,
+	enum rte_mtr_policer_action *actions,
+	struct rte_mtr_error *error);
+/**< @internal MTR object policer action update*/
+
+typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	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_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error);
+/**< @internal MTR object stats read */
+
+struct rte_mtr_ops {
+	/** MTR capabilities get */
+	rte_mtr_capabilities_get_t capabilities_get;
+
+	/** MTR meter profile add */
+	rte_mtr_meter_profile_add_t meter_profile_add;
+
+	/** MTR meter profile delete */
+	rte_mtr_meter_profile_delete_t meter_profile_delete;
+
+	/** MTR object create */
+	rte_mtr_create_t create;
+
+	/** MTR object destroy */
+	rte_mtr_destroy_t destroy;
+
+	/** MTR object meter enable */
+	rte_mtr_meter_enable_t meter_enable;
+
+	/** MTR object meter disable */
+	rte_mtr_meter_disable_t meter_disable;
+
+	/** MTR object meter profile update */
+	rte_mtr_meter_profile_update_t meter_profile_update;
+
+	/** 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;
+};
+
+/**
+ * Initialize generic error structure.
+ *
+ * This function also sets rte_errno to a given value.
+ *
+ * @param[out] error
+ *   Pointer to error structure (may be NULL).
+ * @param[in] code
+ *   Related error code (rte_errno).
+ * @param[in] type
+ *   Cause field and error type.
+ * @param[in] cause
+ *   Object responsible for the error.
+ * @param[in] message
+ *   Human-readable error message.
+ *
+ * @return
+ *   Error code.
+ */
+static inline int
+rte_mtr_error_set(struct rte_mtr_error *error,
+		   int code,
+		   enum rte_mtr_error_type type,
+		   const void *cause,
+		   const char *message)
+{
+	if (error) {
+		*error = (struct rte_mtr_error){
+			.type = type,
+			.cause = cause,
+			.message = message,
+		};
+	}
+	rte_errno = code;
+	return code;
+}
+
+/**
+ * Get generic traffic metering and policing operations structure from a port
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[out] error
+ *   Error details
+ *
+ * @return
+ *   The traffic metering and policing operations structure associated with
+ *   port_id on success, NULL otherwise.
+ */
+const struct rte_mtr_ops *
+rte_mtr_ops_get(uint8_t port_id, struct rte_mtr_error *error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_RTE_MTR_DRIVER_H__ */
-- 
2.7.4

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

* [PATCH V2 4/5] doc: ethdev traffic metering and policing api
  2017-10-05 13:09       ` [PATCH V2 0/5] rte_mtr: generic ethdev api for metering and policing Cristian Dumitrescu
                           ` (2 preceding siblings ...)
  2017-10-05 13:09         ` [PATCH V2 3/5] ethdev: add new api for traffic metering and policing Cristian Dumitrescu
@ 2017-10-05 13:09         ` Cristian Dumitrescu
  2017-10-05 13:09         ` [PATCH V2 5/5] app/testpmd: cli for traffic metering and policing Cristian Dumitrescu
  4 siblings, 0 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-05 13:09 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, hemant.agrawal,
	jerin.jacob, jasvinder.singh

Add new section in the Programmer Guide for the ethdev traffic metering
and policing (MTR) API.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 doc/guides/prog_guide/index.rst                    |  1 +
 .../prog_guide/traffic_metering_and_policing.rst   | 97 ++++++++++++++++++++++
 2 files changed, 98 insertions(+)
 create mode 100644 doc/guides/prog_guide/traffic_metering_and_policing.rst

diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index 40f04a1..c9eeba9 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -44,6 +44,7 @@ Programmer's Guide
     mbuf_lib
     poll_mode_drv
     rte_flow
+    traffic_metering_and_policing
     traffic_management
     cryptodev_lib
     link_bonding_poll_mode_drv_lib
diff --git a/doc/guides/prog_guide/traffic_metering_and_policing.rst b/doc/guides/prog_guide/traffic_metering_and_policing.rst
new file mode 100644
index 0000000..39a7051
--- /dev/null
+++ b/doc/guides/prog_guide/traffic_metering_and_policing.rst
@@ -0,0 +1,97 @@
+..  BSD LICENSE
+    Copyright(c) 2017 Intel Corporation. All rights reserved.
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+    * Neither the name of Intel Corporation nor the names of its
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Traffic Metering and Policing (MTR) API
+=======================================
+
+
+Overview
+--------
+
+This is the generic API for the Quality of Service (QoS) Traffic Metering and
+Policing (MTR) of Ethernet devices. This API is agnostic of the underlying HW,
+SW or mixed HW-SW implementation.
+
+Main features:
+
+* Part of DPDK rte_ethdev API
+* Capability query API
+* Metering algorithms: RFC 2697 Single Rate Three Color Marker (srTCM), RFC 2698
+  and RFC 4115 Two Rate Three Color Marker (trTCM)
+* Policer actions (per meter output color): recolor, drop
+* Statistics (per policer output color)
+
+Configuration steps
+-------------------
+
+Metering and policing stage typically sits on top of flow classification,
+which is why the MTR objects are enabled through a special "meter" action.
+
+The MTR objects are created and updated in their own name space (rte_mtr)
+within the librte_ether library. Whether an MTR object is private to a flow
+or potentially shared by several flows has to be specified at its creation
+time.
+
+Once successfully created, an MTR object is hooked into the RX processing path
+of the Ethernet device by linking it to one or several flows through the
+dedicated "meter" flow action. One or several "meter" actions can be registered
+for the same flow. An MTR object can only be destroyed if there are no flows
+using it.
+
+Run-time processing
+-------------------
+
+Traffic metering determines the color for the current packet (green, yellow,
+red) based on the previous history for this flow as maintained by the MTR
+object. The policer can do nothing, override the color the packet or drop the
+packet. Statistics counters are maintained for MTR object, as configured.
+
+The processing done for each input packet hitting an MTR object is:
+* Traffic metering: The packet is assigned a color (the meter output
+  color) based on the previous traffic history reflected in the
+  current state of the MTR object, according to the specific traffic
+  metering algorithm. The traffic metering algorithm can typically work
+  in color aware mode, in which case the input packet already has an
+  initial color (the input color), or in 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).
+* Statistics: The set of counters maintained for each MTR object is
+  configurable and subject to the implementation support. This set
+  includes the number of packets and bytes dropped or passed for each
+  output color.
-- 
2.7.4

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

* [PATCH V2 5/5] app/testpmd: cli for traffic metering and policing
  2017-10-05 13:09       ` [PATCH V2 0/5] rte_mtr: generic ethdev api for metering and policing Cristian Dumitrescu
                           ` (3 preceding siblings ...)
  2017-10-05 13:09         ` [PATCH V2 4/5] doc: ethdev traffic metering and policing api Cristian Dumitrescu
@ 2017-10-05 13:09         ` Cristian Dumitrescu
  2017-10-06 13:58           ` Adrien Mazarguil
  4 siblings, 1 reply; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-05 13:09 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, hemant.agrawal,
	jerin.jacob, jasvinder.singh

Add CLI commands to exercise the ethdev Traffic Metering and Policing
(MTR) API.

Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 app/test-pmd/Makefile       |    1 +
 app/test-pmd/cmdline.c      |   10 +
 app/test-pmd/cmdline_flow.c |   24 +
 app/test-pmd/cmdline_mtr.c  | 1013 +++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/cmdline_mtr.h  |   49 +++
 5 files changed, 1097 insertions(+)
 create mode 100644 app/test-pmd/cmdline_mtr.c
 create mode 100644 app/test-pmd/cmdline_mtr.h

diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile
index c36be19..8fb6491 100644
--- a/app/test-pmd/Makefile
+++ b/app/test-pmd/Makefile
@@ -48,6 +48,7 @@ SRCS-y := testpmd.c
 SRCS-y += parameters.c
 SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline.c
 SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_flow.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_mtr.c
 SRCS-y += config.c
 SRCS-y += iofwd.c
 SRCS-y += macfwd.c
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index ccdf239..8338b5c 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -99,6 +99,7 @@
 #include <rte_pmd_bnxt.h>
 #endif
 #include "testpmd.h"
+#include "cmdline_mtr.h"
 
 static struct cmdline *testpmd_cl;
 
@@ -14334,6 +14335,15 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_hash_input_set,
 	(cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
 	(cmdline_parse_inst_t *)&cmd_flow,
+	(cmdline_parse_inst_t *)&cmd_add_port_meter_profile_srtcm,
+	(cmdline_parse_inst_t *)&cmd_add_port_meter_profile_trtcm,
+	(cmdline_parse_inst_t *)&cmd_del_port_meter_profile,
+	(cmdline_parse_inst_t *)&cmd_set_port_meter,
+	(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_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,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index a17a004..f210ce5 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -194,6 +194,8 @@ enum index {
 	ACTION_VF,
 	ACTION_VF_ORIGINAL,
 	ACTION_VF_ID,
+	ACTION_METER,
+	ACTION_METER_ID,
 };
 
 /** Size of pattern[] field in struct rte_flow_item_raw. */
@@ -601,6 +603,7 @@ static const enum index next_action[] = {
 	ACTION_RSS,
 	ACTION_PF,
 	ACTION_VF,
+	ACTION_METER,
 	ZERO,
 };
 
@@ -635,6 +638,12 @@ static const enum index action_vf[] = {
 	ZERO,
 };
 
+static const enum index action_meter[] = {
+	ACTION_METER_ID,
+	ACTION_NEXT,
+	ZERO,
+};
+
 static int parse_init(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
@@ -1566,6 +1575,21 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
 		.call = parse_vc_conf,
 	},
+	[ACTION_METER] = {
+		.name = "meter",
+		.help = "meter the directed packets at given id",
+		.priv = PRIV_ACTION(METER,
+				    sizeof(struct rte_flow_action_meter)),
+		.next = NEXT(action_meter),
+		.call = parse_vc,
+	},
+	[ACTION_METER_ID] = {
+		.name = "mtr_id",
+		.help = "meter id to use",
+		.next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
+		.call = parse_vc_conf,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
diff --git a/app/test-pmd/cmdline_mtr.c b/app/test-pmd/cmdline_mtr.c
new file mode 100644
index 0000000..58feee5
--- /dev/null
+++ b/app/test-pmd/cmdline_mtr.c
@@ -0,0 +1,1013 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+
+#include <rte_ethdev.h>
+#include <rte_flow.h>
+#include <rte_mtr.h>
+
+#include "testpmd.h"
+#include "cmdline_mtr.h"
+
+/** Display Meter Error Message */
+static void
+print_err_msg(struct rte_mtr_error *error)
+{
+	static const char *const errstrlist[] = {
+		[RTE_MTR_ERROR_TYPE_NONE] = "no error",
+		[RTE_MTR_ERROR_TYPE_UNSPECIFIED] = "cause unspecified",
+		[RTE_MTR_ERROR_TYPE_METER_PROFILE_ID] = "meter profile id",
+		[RTE_MTR_ERROR_TYPE_METER_PROFILE] = "meter profile null",
+		[RTE_MTR_ERROR_TYPE_MTR_ID]	= "meter id",
+		[RTE_MTR_ERROR_TYPE_MTR_PARAMS] = "meter params null",
+		[RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN]
+			= "policer action(green)",
+		[RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW]
+			= "policer action(yellow)",
+		[RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED]
+			= "policer action(red)",
+		[RTE_MTR_ERROR_TYPE_STATS_MASK] = "stats mask",
+		[RTE_MTR_ERROR_TYPE_STATS] = "stats",
+		[RTE_MTR_ERROR_TYPE_SHARED]
+			= "shared meter",
+	};
+
+	const char *errstr;
+	char buf[64];
+
+	if ((unsigned int)error->type >= RTE_DIM(errstrlist) ||
+		!errstrlist[error->type])
+		errstr = "unknown type";
+	else
+		errstr = errstrlist[error->type];
+
+	if (error->cause)
+		snprintf(buf, sizeof(buf), "cause: %p, ", error->cause);
+
+	printf("%s: %s%s (error %d)\n", errstr, error->cause ? buf : "",
+		error->message ? error->message : "(no stated reason)",
+		error->type);
+}
+
+static int
+string_to_policer_action(char *s)
+{
+	if (strcmp(s, "G") == 0)
+		return MTR_POLICER_ACTION_COLOR_GREEN;
+
+	if (strcmp(s, "Y") == 0)
+		return MTR_POLICER_ACTION_COLOR_YELLOW;
+
+	if (strcmp(s, "R") == 0)
+		return MTR_POLICER_ACTION_COLOR_RED;
+
+	if (strcmp(s, "D") == 0)
+		return MTR_POLICER_ACTION_DROP;
+
+	return -1;
+}
+
+/* *** Add Port Meter Profile srtcm_rfc2697 *** */
+struct cmd_add_port_meter_profile_srtcm_result {
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	cmdline_fixed_string_t srtcm_rfc2697;
+	uint8_t port_id;
+	uint32_t profile_id;
+	uint64_t cir;
+	uint64_t cbs;
+	uint64_t ebs;
+	uint8_t color_aware;
+};
+
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_add =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result, add, "add");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			port, "port");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			meter, "meter");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			profile, "profile");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_srtcm_rfc2697 =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			srtcm_rfc2697, "srtcm_rfc2697");
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			port_id, UINT8);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			profile_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_cir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			cir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_cbs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			cbs, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_ebs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			ebs, UINT64);
+
+static void cmd_add_port_meter_profile_srtcm_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_add_port_meter_profile_srtcm_result *res = parsed_result;
+	struct rte_mtr_meter_profile mp;
+	struct rte_mtr_error error;
+	uint32_t profile_id = res->profile_id;
+	uint8_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Private shaper profile params */
+	memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
+	mp.alg = 0;
+	mp.srtcm_rfc2697.cir = res->cir;
+	mp.srtcm_rfc2697.cbs = res->cbs;
+	mp.srtcm_rfc2697.ebs = res->ebs;
+
+	ret = rte_mtr_meter_profile_add(port_id, profile_id, &mp, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_add_port_meter_profile_srtcm = {
+	.f = cmd_add_port_meter_profile_srtcm_parsed,
+	.data = NULL,
+	.help_str = "Add port meter profile srtcm (rfc2697)",
+	.tokens = {
+		(void *)&cmd_add_port_meter_profile_srtcm_add,
+		(void *)&cmd_add_port_meter_profile_srtcm_port,
+		(void *)&cmd_add_port_meter_profile_srtcm_meter,
+		(void *)&cmd_add_port_meter_profile_srtcm_profile,
+		(void *)&cmd_add_port_meter_profile_srtcm_port_id,
+		(void *)&cmd_add_port_meter_profile_srtcm_profile_id,
+		(void *)&cmd_add_port_meter_profile_srtcm_srtcm_rfc2697,
+		(void *)&cmd_add_port_meter_profile_srtcm_cir,
+		(void *)&cmd_add_port_meter_profile_srtcm_cbs,
+		(void *)&cmd_add_port_meter_profile_srtcm_ebs,
+		NULL,
+	},
+};
+
+/* *** Add Port Meter Profile trtcm_rfc2698 *** */
+struct cmd_add_port_meter_profile_trtcm_result {
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	cmdline_fixed_string_t trtcm_rfc2698;
+	uint8_t port_id;
+	uint32_t profile_id;
+	uint64_t cir;
+	uint64_t pir;
+	uint64_t cbs;
+	uint64_t pbs;
+};
+
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_add =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result, add, "add");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			port, "port");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			meter, "meter");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			profile, "profile");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_trtcm_rfc2698 =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			trtcm_rfc2698, "trtcm_rfc2698");
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			port_id, UINT8);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			profile_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_cir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			cir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_pir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			pir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_cbs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			cbs, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_pbs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			pbs, UINT64);
+
+static void cmd_add_port_meter_profile_trtcm_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_add_port_meter_profile_trtcm_result *res = parsed_result;
+	struct rte_mtr_meter_profile mp;
+	struct rte_mtr_error error;
+	uint32_t profile_id = res->profile_id;
+	uint8_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Private shaper profile params */
+	memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
+	mp.alg = 0;
+	mp.trtcm_rfc2698.cir = res->cir;
+	mp.trtcm_rfc2698.pir = res->pir;
+	mp.trtcm_rfc2698.cbs = res->cbs;
+	mp.trtcm_rfc2698.pbs = res->pbs;
+
+	ret = rte_mtr_meter_profile_add(port_id, profile_id, &mp, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm = {
+	.f = cmd_add_port_meter_profile_trtcm_parsed,
+	.data = NULL,
+	.help_str = "Add port meter profile trtcm (rfc2698)",
+	.tokens = {
+		(void *)&cmd_add_port_meter_profile_trtcm_add,
+		(void *)&cmd_add_port_meter_profile_trtcm_port,
+		(void *)&cmd_add_port_meter_profile_trtcm_meter,
+		(void *)&cmd_add_port_meter_profile_trtcm_profile,
+		(void *)&cmd_add_port_meter_profile_trtcm_port_id,
+		(void *)&cmd_add_port_meter_profile_trtcm_profile_id,
+		(void *)&cmd_add_port_meter_profile_trtcm_trtcm_rfc2698,
+		(void *)&cmd_add_port_meter_profile_trtcm_cir,
+		(void *)&cmd_add_port_meter_profile_trtcm_pir,
+		(void *)&cmd_add_port_meter_profile_trtcm_cbs,
+		(void *)&cmd_add_port_meter_profile_trtcm_pbs,
+		NULL,
+	},
+};
+
+/* *** Add Port Meter Profile trtcm_rfc4115 *** */
+struct cmd_add_port_meter_profile_trtcm_rfc4115_result {
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	cmdline_fixed_string_t trtcm_rfc4115;
+	uint8_t port_id;
+	uint32_t profile_id;
+	uint64_t cir;
+	uint64_t eir;
+	uint64_t cbs;
+	uint64_t ebs;
+};
+
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_add =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result, add,
+		"add");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			port, "port");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			meter, "meter");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			profile, "profile");
+cmdline_parse_token_string_t
+	cmd_add_port_meter_profile_trtcm_rfc4115_trtcm_rfc4115 =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			trtcm_rfc4115, "trtcm_rfc4115");
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			port_id, UINT8);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			profile_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_cir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			cir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_eir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			eir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_cbs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			cbs, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_ebs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			ebs, UINT64);
+
+static void cmd_add_port_meter_profile_trtcm_rfc4115_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_add_port_meter_profile_trtcm_rfc4115_result *res =
+		parsed_result;
+	struct rte_mtr_meter_profile mp;
+	struct rte_mtr_error error;
+	uint32_t profile_id = res->profile_id;
+	uint8_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Private shaper profile params */
+	memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
+	mp.alg = 0;
+	mp.trtcm_rfc4115.cir = res->cir;
+	mp.trtcm_rfc4115.eir = res->eir;
+	mp.trtcm_rfc4115.cbs = res->cbs;
+	mp.trtcm_rfc4115.ebs = res->ebs;
+
+	ret = rte_mtr_meter_profile_add(port_id, profile_id, &mp, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm_rfc4115 = {
+	.f = cmd_add_port_meter_profile_trtcm_rfc4115_parsed,
+	.data = NULL,
+	.help_str = "Add port meter profile trtcm (rfc4115)",
+	.tokens = {
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_add,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_port,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_meter,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_profile,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_port_id,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_profile_id,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_trtcm_rfc4115,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_cir,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_eir,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_cbs,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_ebs,
+		NULL,
+	},
+};
+
+/* *** Delete Port Meter Profile *** */
+struct cmd_del_port_meter_profile_result {
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	uint8_t port_id;
+	uint32_t profile_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_meter_profile_del =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_profile_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_meter_profile_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			port, "port");
+cmdline_parse_token_string_t cmd_del_port_meter_profile_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			meter, "meter");
+cmdline_parse_token_string_t cmd_del_port_meter_profile_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			profile, "profile");
+cmdline_parse_token_num_t cmd_del_port_meter_profile_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			port_id, UINT8);
+cmdline_parse_token_num_t cmd_del_port_meter_profile_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			profile_id, UINT32);
+
+static void cmd_del_port_meter_profile_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_del_port_meter_profile_result *res = parsed_result;
+	struct rte_mtr_error error;
+	uint32_t profile_id = res->profile_id;
+	uint8_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Delete meter profile */
+	ret = rte_mtr_meter_profile_delete(port_id, profile_id, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_del_port_meter_profile = {
+	.f = cmd_del_port_meter_profile_parsed,
+	.data = NULL,
+	.help_str = "Delete port meter profile",
+	.tokens = {
+		(void *)&cmd_del_port_meter_profile_del,
+		(void *)&cmd_del_port_meter_profile_port,
+		(void *)&cmd_del_port_meter_profile_meter,
+		(void *)&cmd_del_port_meter_profile_profile,
+		(void *)&cmd_del_port_meter_profile_port_id,
+		(void *)&cmd_del_port_meter_profile_profile_id,
+		NULL,
+	},
+};
+
+/* *** Create Port Meter Object *** */
+struct cmd_set_port_meter_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	uint8_t port_id;
+	uint32_t mtr_id;
+	uint32_t profile_id;
+	cmdline_fixed_string_t g_action;
+	cmdline_fixed_string_t y_action;
+	cmdline_fixed_string_t r_action;
+	uint64_t statistics_mask;
+	uint32_t shared;
+};
+
+cmdline_parse_token_string_t cmd_set_port_meter_set =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_meter_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_meter_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_result, meter, "meter");
+cmdline_parse_token_num_t cmd_set_port_meter_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_port_meter_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_set_port_meter_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_result, profile_id, UINT32);
+cmdline_parse_token_string_t cmd_set_port_meter_g_action =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_port_meter_result,
+		g_action, "R#Y#G#D");
+cmdline_parse_token_string_t cmd_set_port_meter_y_action =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_port_meter_result,
+		y_action, "R#Y#G#D");
+cmdline_parse_token_string_t cmd_set_port_meter_r_action =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_port_meter_result,
+		r_action, "R#Y#G#D");
+cmdline_parse_token_num_t cmd_set_port_meter_statistics_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_port_meter_result,
+		statistics_mask, UINT64);
+cmdline_parse_token_num_t cmd_set_port_meter_shared =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_port_meter_result,
+		shared, UINT32);
+
+static void cmd_set_port_meter_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_port_meter_result *res = parsed_result;
+	struct rte_mtr_error error;
+	struct rte_mtr_params params;
+	uint32_t mtr_id = res->mtr_id;
+	uint32_t shared = res->shared;
+	uint8_t port_id = res->port_id;
+	
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Meter params */
+	memset(&params, 0, sizeof(struct rte_mtr_params));
+	params.meter_profile_id = res->profile_id;
+	params.use_prev_mtr_color = 1;
+	params.dscp_table = NULL;
+	params.meter_enable = 1;
+	params.action[RTE_MTR_GREEN] =
+		string_to_policer_action(res->g_action);
+	params.action[RTE_MTR_YELLOW] =
+		string_to_policer_action(res->y_action);
+	params.action[RTE_MTR_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);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_port_meter = {
+	.f = cmd_set_port_meter_parsed,
+	.data = NULL,
+	.help_str = "Set port meter",
+	.tokens = {
+		(void *)&cmd_set_port_meter_set,
+		(void *)&cmd_set_port_meter_port,
+		(void *)&cmd_set_port_meter_meter,
+		(void *)&cmd_set_port_meter_port_id,
+		(void *)&cmd_set_port_meter_mtr_id,
+		(void *)&cmd_set_port_meter_profile_id,
+		(void *)&cmd_set_port_meter_g_action,
+		(void *)&cmd_set_port_meter_y_action,
+		(void *)&cmd_set_port_meter_r_action,
+		(void *)&cmd_set_port_meter_statistics_mask,
+		(void *)&cmd_set_port_meter_shared,	
+		NULL,
+	},
+};
+
+/* *** Delete Port Meter Object *** */
+struct cmd_del_port_meter_result {
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	uint8_t port_id;
+	uint32_t mtr_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_meter_del =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_meter_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_result, port, "port");
+cmdline_parse_token_string_t cmd_del_port_meter_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_result, meter, "meter");
+cmdline_parse_token_num_t cmd_del_port_meter_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_del_port_meter_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_result, mtr_id, UINT32);
+
+static void cmd_del_port_meter_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_del_port_meter_result *res = parsed_result;
+	struct rte_mtr_error error;
+	uint32_t mtr_id = res->mtr_id;
+	uint8_t port_id = res->port_id;
+	
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Destroy Meter */
+	ret = rte_mtr_destroy(port_id, mtr_id, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_del_port_meter = {
+	.f = cmd_del_port_meter_parsed,
+	.data = NULL,
+	.help_str = "Delete port meter",
+	.tokens = {
+		(void *)&cmd_del_port_meter_del,
+		(void *)&cmd_del_port_meter_port,
+		(void *)&cmd_del_port_meter_meter,
+		(void *)&cmd_del_port_meter_port_id,
+		(void *)&cmd_del_port_meter_mtr_id,
+		NULL,
+	},
+};
+
+/* *** Set Port Meter Profile *** */
+struct cmd_set_port_meter_profile_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	uint8_t port_id;
+	uint32_t mtr_id;
+	uint32_t profile_id;
+};
+
+cmdline_parse_token_string_t cmd_set_port_meter_profile_set =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_meter_profile_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_meter_profile_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, meter, "meter");
+cmdline_parse_token_string_t cmd_set_port_meter_profile_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, profile, "profile");
+cmdline_parse_token_num_t cmd_set_port_meter_profile_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_port_meter_profile_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_set_port_meter_profile_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, profile_id, UINT32);
+
+static void cmd_set_port_meter_profile_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_port_meter_profile_result *res = parsed_result;
+	struct rte_mtr_error error;
+	uint32_t mtr_id = res->mtr_id;
+	uint32_t profile_id = res->profile_id;
+	uint8_t port_id = res->port_id;
+	
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Set meter profile */
+	ret = rte_mtr_meter_profile_update(port_id, mtr_id,
+		profile_id, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_port_meter_profile = {
+	.f = cmd_set_port_meter_profile_parsed,
+	.data = NULL,
+	.help_str = "Set port meter profile",
+	.tokens = {
+		(void *)&cmd_set_port_meter_profile_set,
+		(void *)&cmd_set_port_meter_profile_port,
+		(void *)&cmd_set_port_meter_profile_meter,
+		(void *)&cmd_set_port_meter_profile_profile,
+		(void *)&cmd_set_port_meter_profile_port_id,
+		(void *)&cmd_set_port_meter_profile_mtr_id,
+		(void *)&cmd_set_port_meter_profile_profile_id,
+		NULL,
+	},
+};
+
+/* *** 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;
+	uint8_t port_id;
+	uint32_t mtr_id;
+	cmdline_fixed_string_t color;
+	cmdline_fixed_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, UINT8);
+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, UINT32);
+cmdline_parse_token_string_t cmd_set_port_meter_policer_action_color =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_policer_action_result, color, "G#Y#R");
+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, "G#Y#R#D");
+
+static void cmd_set_port_meter_policer_action_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_port_meter_policer_action_result *res = parsed_result;
+	enum rte_mtr_color color;
+	enum rte_mtr_policer_action action[RTE_MTR_COLORS];
+	struct rte_mtr_error error;
+	uint32_t mtr_id = res->mtr_id;
+	uint8_t port_id = res->port_id;
+	char *c = res->color;
+	char *a = res->policer_action;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Color */
+	if (strcmp(c, "G") == 0)
+		color = RTE_MTR_GREEN;
+	else if (strcmp(c, "Y") == 0)
+		color = RTE_MTR_YELLOW;
+	else if (strcmp(c, "Y") == 0)
+		color = RTE_MTR_RED;
+	else
+		color = RTE_MTR_COLORS;
+
+	/* Action */
+	if (strcmp(a, "G") == 0)
+		action[color] = MTR_POLICER_ACTION_COLOR_GREEN;
+	else if (strcmp(a, "Y") == 0)
+		action[color] = MTR_POLICER_ACTION_COLOR_YELLOW;
+	else if (strcmp(a, "Y") == 0)
+		action[color] = MTR_POLICER_ACTION_COLOR_RED;
+	else
+		action[color] = MTR_POLICER_ACTION_DROP;
+
+	ret = rte_mtr_policer_actions_update(port_id, mtr_id,
+		1 << color, action, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+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",
+	.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_color,
+		(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;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t stats;
+	cmdline_fixed_string_t mask;
+	uint8_t port_id;
+	uint32_t mtr_id;
+	uint64_t stats_mask;
+};
+
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_set =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, meter, "meter");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_stats =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, stats, "stats");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_mask =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, mask, "mask");
+cmdline_parse_token_num_t cmd_set_port_meter_stats_mask_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_port_meter_stats_mask_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_set_port_meter_stats_mask_stats_mask =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, stats_mask, UINT64);
+
+static void cmd_set_port_meter_stats_mask_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_port_meter_stats_mask_result *res = parsed_result;
+	struct rte_mtr_error error;
+	uint64_t stats_mask = res->stats_mask;
+	uint32_t mtr_id = res->mtr_id;
+	uint8_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	ret = rte_mtr_stats_update(port_id, mtr_id, stats_mask, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_port_meter_stats_mask = {
+	.f = cmd_set_port_meter_stats_mask_parsed,
+	.data = NULL,
+	.help_str = "Set port meter stats mask",
+	.tokens = {
+		(void *)&cmd_set_port_meter_stats_mask_set,
+		(void *)&cmd_set_port_meter_stats_mask_port,
+		(void *)&cmd_set_port_meter_stats_mask_meter,
+		(void *)&cmd_set_port_meter_stats_mask_stats,
+		(void *)&cmd_set_port_meter_stats_mask_mask,
+		(void *)&cmd_set_port_meter_stats_mask_port_id,
+		(void *)&cmd_set_port_meter_stats_mask_mtr_id,
+		(void *)&cmd_set_port_meter_stats_mask_stats_mask,
+		NULL,
+	},
+};
+
+/* *** Show Port Meter Stats *** */
+struct cmd_show_port_meter_stats_result {
+	cmdline_fixed_string_t show;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t stats;
+	uint8_t port_id;
+	uint32_t mtr_id;
+	uint32_t clear;
+};
+
+cmdline_parse_token_string_t cmd_show_port_meter_stats_show =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, show, "show");
+cmdline_parse_token_string_t cmd_show_port_meter_stats_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, port, "port");
+cmdline_parse_token_string_t cmd_show_port_meter_stats_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, meter, "meter");
+cmdline_parse_token_string_t cmd_show_port_meter_stats_stats =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, stats, "stats");
+cmdline_parse_token_num_t cmd_show_port_meter_stats_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_show_port_meter_stats_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_show_port_meter_stats_clear =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, clear, UINT32);
+
+static void cmd_show_port_meter_stats_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_show_port_meter_stats_result *res = parsed_result;
+	struct rte_mtr_stats stats;
+	uint64_t stats_mask = 0;
+	struct rte_mtr_error error;
+	uint32_t mtr_id = res->mtr_id;
+	uint32_t clear = res->clear;
+	uint8_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	memset(&stats, 0, sizeof(struct rte_mtr_stats));
+	ret = rte_mtr_stats_read(port_id, mtr_id, &stats,
+		&stats_mask, clear, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+
+	/* Display stats */
+	if (stats_mask & RTE_MTR_STATS_N_PKTS_GREEN)
+		printf("\tPkts G: %" PRIu64 "\n",
+			stats.n_pkts[RTE_MTR_GREEN]);
+	if (stats_mask & RTE_MTR_STATS_N_BYTES_GREEN)
+		printf("\tBytes G: %" PRIu64 "\n",
+			stats.n_bytes[RTE_MTR_GREEN]);
+	if (stats_mask & RTE_MTR_STATS_N_PKTS_YELLOW)
+		printf("\tPkts Y: %" PRIu64 "\n",
+			stats.n_pkts[RTE_MTR_YELLOW]);
+	if (stats_mask & RTE_MTR_STATS_N_BYTES_YELLOW)
+		printf("\tBytes Y: %" PRIu64 "\n",
+			stats.n_bytes[RTE_MTR_YELLOW]);
+	if (stats_mask & RTE_MTR_STATS_N_PKTS_RED)
+		printf("\tPkts R: %" PRIu64 "\n",
+			stats.n_pkts[RTE_MTR_RED]);
+	if (stats_mask & RTE_MTR_STATS_N_BYTES_RED)
+		printf("\tBytes Y: %" PRIu64 "\n",
+			stats.n_bytes[RTE_MTR_RED]);
+	if (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED)
+		printf("\tPkts DROPPED: %" PRIu64 "\n",
+			stats.n_pkts_dropped);
+	if (stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED)
+		printf("\tBytes DROPPED: %" PRIu64 "\n",
+			stats.n_bytes_dropped);
+}
+
+cmdline_parse_inst_t cmd_show_port_meter_stats = {
+	.f = cmd_show_port_meter_stats_parsed,
+	.data = NULL,
+	.help_str = "Show port meter stats",
+	.tokens = {
+		(void *)&cmd_show_port_meter_stats_show,
+		(void *)&cmd_show_port_meter_stats_port,
+		(void *)&cmd_show_port_meter_stats_meter,
+		(void *)&cmd_show_port_meter_stats_stats,
+		(void *)&cmd_show_port_meter_stats_port_id,
+		(void *)&cmd_show_port_meter_stats_mtr_id,
+		(void *)&cmd_show_port_meter_stats_clear,
+		NULL,
+	},
+};
diff --git a/app/test-pmd/cmdline_mtr.h b/app/test-pmd/cmdline_mtr.h
new file mode 100644
index 0000000..5e9af77
--- /dev/null
+++ b/app/test-pmd/cmdline_mtr.h
@@ -0,0 +1,49 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CMDLINE_MTR_H_
+#define _CMDLINE_MTR_H_
+
+/* Traffic Metering and Policing */
+extern cmdline_parse_inst_t cmd_add_port_meter_profile_srtcm;
+extern cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm;
+extern cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm_rfc4115;
+extern cmdline_parse_inst_t cmd_del_port_meter_profile;
+extern cmdline_parse_inst_t cmd_set_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_policer_action;
+extern cmdline_parse_inst_t cmd_set_port_meter_stats_mask;
+extern cmdline_parse_inst_t cmd_show_port_meter_stats;
+
+#endif /* _CMDLINE_MTR_H_ */
\ No newline at end of file
-- 
2.7.4

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

* Re: [PATCH 3/3] rte_flow: add new action for traffic metering and policing
  2017-09-19 17:00           ` Adrien Mazarguil
@ 2017-10-06 10:02             ` Dumitrescu, Cristian
  0 siblings, 0 replies; 64+ messages in thread
From: Dumitrescu, Cristian @ 2017-10-06 10:02 UTC (permalink / raw)
  To: Adrien Mazarguil; +Cc: dev, thomas, jerin.jacob, hemant.agrawal

Hi Adrien,

> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Tuesday, September 19, 2017 6:01 PM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Cc: dev@dpdk.org; thomas@monjalon.net;
> jerin.jacob@caviumnetworks.com; hemant.agrawal@nxp.com
> Subject: Re: [PATCH 3/3] rte_flow: add new action for traffic metering and
> policing
> 
> Hi Cristian,
> 
> On Tue, Sep 19, 2017 at 04:36:50PM +0000, Dumitrescu, Cristian wrote:
> <snip>
> > > >  /**
> > > > + * RTE_FLOW_ACTION_TYPE_METER
> > > > + *
> > > > + * Traffic metering and policing (MTR).
> > > > + *
> > > > + * Packets matched by items of this type can be either dropped or
> passed
> > > to the
> > > > + * next item with their color set by the MTR object.
> > > > + *
> > > > + * Non-terminating by default.
> > > > + */
> > > > +struct rte_flow_action_meter {
> > > > +	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create().
> > > */
> > > > +};
> > > > +
> > >
> > > Default mask definition is missing.
> > >
> >
> > I do not understand this comment. This is a flow action, not a flow item
> (that might be a packet field with an associated mask); this mtr_id is similar to
> queue ID/index/VF ID from other flow actions, none having any mask
> attached. Adrien, can you please clarify?
> 
> Yes, I actually misread it as a pattern item definition for some
> reason. Nothing to see here, move along!
> 

No worries.

> >
> > > > +/**
> > > >   * Definition of a single action.
> > > >   *
> > > >   * A list of actions is terminated by a END action.
> > > > --
> > > > 2.7.4
> > > >
> > >
> > > Even if MTR is a separate API, please add to this commit:
> > >
> > > - Documentation update: guides/prog_guide/rte_flow.rst
> > > - Testpmd update: app/test-pmd/cmdline_flow.c
> > > - Testpmd documentation update:
> > > doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > >
> > > You can find examples in previous commits related to rte_flow.
> > >
> >
> > All of these items are a must and will get done, but do they have to be
> done in the same patch set?
> 
> That'd be much better as far as I'm involved in this review (rte_flow
> changes). You should put them in the same patch as the above.
> 
> > My plan was to introduce test-pmd updates through separate patch sets
> after the API is accepted. I know you had these items done in the same patch
> set for rte_flow, but there are other APIs such as eventdev and ethdev
> traffic management which introduced sample app one release later.
> 
> In that case, could you split these changes in two parts?
> 
> This patch could bring the basic MTR action support in testpmd, by this I
> mean the ability to type a flow command with such an action and not get
> rejected with a "bad arguments" error since it is actually part of the API,
> even if nothing is connected to that action at this point. The rule should
> however get rejected by its lack of support in the underlying PMD.
> 
> Same idea for rte_flow and testpmd documentation update, this patch only
> needs the minimum amount describing what this action is without a link to
> the actual MTR documentation, which is not present at this point.
> 
> Subsequent commits shall update these as they complete the MTR API.
> 

Full doc and test-pmd have been implemented in V2 just sent earlier, so let me know if you are OK with V2.

> --
> Adrien Mazarguil
> 6WIND

Thanks,
Cristian

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

* Re: [PATCH 2/3] ethdev: add new rte_mtr API for traffic metering and policing
  2017-09-21 13:20       ` Thomas Monjalon
@ 2017-10-06 10:03         ` Dumitrescu, Cristian
  0 siblings, 0 replies; 64+ messages in thread
From: Dumitrescu, Cristian @ 2017-10-06 10:03 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev, adrien.mazarguil, jerin.jacob, hemant.agrawal



> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> Sent: Thursday, September 21, 2017 2:20 PM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Cc: dev@dpdk.org; adrien.mazarguil@6wind.com;
> jerin.jacob@caviumnetworks.com; hemant.agrawal@nxp.com
> Subject: Re: [dpdk-dev] [PATCH 2/3] ethdev: add new rte_mtr API for traffic
> metering and policing
> 
> 26/08/2017 02:06, Cristian Dumitrescu:
> > +DPDK_17.11 {
> > +       global:
> > +
> > +       rte_eth_dev_mtr_ops_get;
> > +       rte_mtr_meter_profile_add;
> > +       rte_mtr_meter_profile_delete;
> > +       rte_mtr_create;
> > +       rte_mtr_destroy;
> > +       rte_mtr_meter_profile_update;
> > +       rte_mtr_policer_action_update;
> > +       rte_mtr_stats_update;
> > +       rte_mtr_stats_read;
> > +
> > +} DPDK_17.08;
> 
> This API is experimental. So you should not version it in 17.11.
> You can look how it was done for EAL:
> 
> EXPERIMENTAL {
>     global:
> ...
> } DPDK_17.11;

Hi Thomas,

Done as requested in V2 sent yesterday. Let me know if you are OK with V2.

Thanks,
Cristian

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

* Re: [PATCH V2 1/5] ethdev: add new flow action for metering and policing
  2017-10-05 13:09         ` [PATCH V2 1/5] ethdev: add new flow action " Cristian Dumitrescu
@ 2017-10-06 13:57           ` Adrien Mazarguil
  2017-10-06 14:50             ` Dumitrescu, Cristian
  2017-10-06 14:45           ` [PATCH V3 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
  1 sibling, 1 reply; 64+ messages in thread
From: Adrien Mazarguil @ 2017-10-06 13:57 UTC (permalink / raw)
  To: Cristian Dumitrescu
  Cc: dev, thomas, jingjing.wu, hemant.agrawal, jerin.jacob, jasvinder.singh

On Thu, Oct 05, 2017 at 02:09:30PM +0100, Cristian Dumitrescu wrote:
> Metering and policing action typically sits on top of flow classification,
> which is why MTR objects are enabled through a newly introduced flow
> action.
> 
> The configuration of MTR objects is done in their own namespace (rte_mtr)
> within the librte_ether library. The MTR object is hooked into ethdev RX
> processing path using the "meter" flow action.
> 
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>

Looks good, one minor comment about the METER action semantics before acking
this patch, see below.

> ---
>  doc/guides/prog_guide/rte_flow.rst | 24 ++++++++++++++++++++++++
>  lib/librte_ether/rte_flow.h        | 22 ++++++++++++++++++++++
>  2 files changed, 46 insertions(+)
> 
> diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
> index 662a912..6b9cdc2 100644
> --- a/doc/guides/prog_guide/rte_flow.rst
> +++ b/doc/guides/prog_guide/rte_flow.rst
> @@ -1354,6 +1354,30 @@ rule or if packets are not addressed to a VF in the first place.
>     | ``vf``       | VF ID to redirect packets to   |
>     +--------------+--------------------------------+
>  
> +Action: ``METER``
> +^^^^^^^^^^^^^^^^^
> +
> +Applies a stage of metering and policing.
> +
> +The metering and policing (MTR) object has to be first created using the
> +rte_mtr_create() API function. The ID of the MTR object is specified as
> +action parameter. One or several meter actions can be added to the same
> +flow. More than one flow can use the same MTR object through the meter
> +action. The MTR object can be further updated or queried using the
> +rte_mtr* API.

rte_flow is currently documented [1] as ignoring several actions of the same
kind in a given rule, in which case only the last one is taken into
account. It's a deliberate design choice to simplify implementation, which
I now think wasn't such a good idea after all.

I'm therefore not opposed to remove this restriction globally, however in
that case rte_flow documentation must be modified and PMDs reworked to
implement the new behavior (failing by default when encountering multiple
actions of the same time instead of ignoring them). It's probably a little
late to do this now though.

So my suggestion for the time being is to not describe what happens when
several MTR actions are provided. We'll keep this for the next overhaul of
rte_flow (some other changes are already planned).

[1] http://dpdk.org/doc/guides/prog_guide/rte_flow.html#actions

-- 
Adrien Mazarguil
6WIND

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

* Re: [PATCH V2 5/5] app/testpmd: cli for traffic metering and policing
  2017-10-05 13:09         ` [PATCH V2 5/5] app/testpmd: cli for traffic metering and policing Cristian Dumitrescu
@ 2017-10-06 13:58           ` Adrien Mazarguil
  0 siblings, 0 replies; 64+ messages in thread
From: Adrien Mazarguil @ 2017-10-06 13:58 UTC (permalink / raw)
  To: Cristian Dumitrescu
  Cc: dev, thomas, jingjing.wu, hemant.agrawal, jerin.jacob, jasvinder.singh

On Thu, Oct 05, 2017 at 02:09:34PM +0100, Cristian Dumitrescu wrote:
> Add CLI commands to exercise the ethdev Traffic Metering and Policing
> (MTR) API.
> 
> Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
> Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>

I can't comment most of these changes, however for the part related to the
flow command:

<snip>
> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> index a17a004..f210ce5 100644
> --- a/app/test-pmd/cmdline_flow.c
> +++ b/app/test-pmd/cmdline_flow.c
> @@ -194,6 +194,8 @@ enum index {
>  	ACTION_VF,
>  	ACTION_VF_ORIGINAL,
>  	ACTION_VF_ID,
> +	ACTION_METER,
> +	ACTION_METER_ID,
>  };
>  
>  /** Size of pattern[] field in struct rte_flow_item_raw. */
> @@ -601,6 +603,7 @@ static const enum index next_action[] = {
>  	ACTION_RSS,
>  	ACTION_PF,
>  	ACTION_VF,
> +	ACTION_METER,
>  	ZERO,
>  };
>  
> @@ -635,6 +638,12 @@ static const enum index action_vf[] = {
>  	ZERO,
>  };
>  
> +static const enum index action_meter[] = {
> +	ACTION_METER_ID,
> +	ACTION_NEXT,
> +	ZERO,
> +};
> +
>  static int parse_init(struct context *, const struct token *,
>  		      const char *, unsigned int,
>  		      void *, unsigned int);
> @@ -1566,6 +1575,21 @@ static const struct token token_list[] = {
>  		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
>  		.call = parse_vc_conf,
>  	},
> +	[ACTION_METER] = {
> +		.name = "meter",
> +		.help = "meter the directed packets at given id",
> +		.priv = PRIV_ACTION(METER,
> +				    sizeof(struct rte_flow_action_meter)),
> +		.next = NEXT(action_meter),
> +		.call = parse_vc,
> +	},
> +	[ACTION_METER_ID] = {
> +		.name = "mtr_id",
> +		.help = "meter id to use",
> +		.next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)),
> +		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
> +		.call = parse_vc_conf,
> +	},
>  };
<snip>

Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>

One remaining minor comment:

> diff --git a/app/test-pmd/cmdline_mtr.h b/app/test-pmd/cmdline_mtr.h
<snip>
> +#endif /* _CMDLINE_MTR_H_ */
> \ No newline at end of file

Make sure to add this missing new line for the next iteration.

-- 
Adrien Mazarguil
6WIND

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

* [PATCH V3 0/5] rte_mtr: generic ethdev api for metering and policing
  2017-10-05 13:09         ` [PATCH V2 1/5] ethdev: add new flow action " Cristian Dumitrescu
  2017-10-06 13:57           ` Adrien Mazarguil
@ 2017-10-06 14:45           ` Cristian Dumitrescu
  2017-10-06 14:45             ` [PATCH V3 1/5] ethdev: add new flow action " Cristian Dumitrescu
                               ` (4 more replies)
  1 sibling, 5 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-06 14:45 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, hemant.agrawal,
	jerin.jacob, jasvinder.singh

This patch set introduces an ethdev-based generic API for Traffic
Metering and Policing (MTR), which is yet another standard RX offload for
Ethernet devices.

Similar to rte_flow and rte_tm APIs, the configuration of MTR objects is
done in their own namespace (rte_mtr) within the librte_ether library.
Metering and policing action typically sits on top of flow classification,
which is why MTR objects are enabled through a newly introduced flow
action, which is the only impact to flow API.

Q1: Why introduce ethdev-based traffic metering ad policing API?
A1: Traffic metering and policing is a standard RX offload for Ethernet
devices present in NICs, SoCs and NPUs across the industry.

Q2: What's the connection between the new rte_mtr API and the existing
librte_meter library?
A2: The existing librte_meter library provides a SW implementation for a
subset of the features exposed by this API. The rte_mtr API is agnostic to
whether the implementation is HW, SW or mixed HW-SW.

Q3: What's the connection between the new rte_mtr API and the existing
flow API?
A3: The MTR object is hooked into ethdev RX processing path using a newly
introduced flow action, which is the only impact to the flow API.
The configuration of MTR objects is done in separate namespace (rte_mtr)
outside of flow API.

Q4: Can the new flow API meter action drop packets? Is this a terminating
action or not?
A4: Although packets can be dropped by the newly introduced flow API meter
action, this action is non-terminating, i.e. the action list typically
contains at least one more action, which is a terminating action.
Depending on the policer actions configured for the MTR object, some
packets might be dropped while some packets passed to the next flow action
with their color set in the packet mbuf. For example, a typical policer
configuration is to drop the red packets while passing the green packets,
therefore a subsequent flow action needs to be configured to determine the
final destination of green packets.

Q5: Which are the main operations exposed for the MTR object?
A5: Traffic metering, policing and statistics update. Traffic metering
determines the color for the current packet (green, yellow, red) based on
the previous history for this flow as maintained by the MTR object.
The policer can do nothing, recolor or drop the packet. Stats are
maintained for MTR object, as configured.

Q6: Where is the output color stored for the current packet.
A6: struct rte_mbuf::sched::color.

Q7: Which are the supported metering algorithms?
A7: srTCM (RFC 2697), trTCM (RFC 2698 and RFC 4115).

Q8: Which are the supported policer actions?
A8: Recolor the packet (keep or change the color determined by metering)
or drop the packet.

Cristian Dumitrescu (5):
  ethdev: add new flow action for metering and policing
  ethdev: add new eth_dev_ops function for mtr ops get
  ethdev: add new api for traffic metering and policing
  doc: ethdev traffic metering and policing api
  app/testpmd: cli for traffic metering and policing

 MAINTAINERS                                        |    4 +
 app/test-pmd/Makefile                              |    1 +
 app/test-pmd/cmdline.c                             |   10 +
 app/test-pmd/cmdline_flow.c                        |   24 +
 app/test-pmd/cmdline_mtr.c                         | 1013 ++++++++++++++++++++
 app/test-pmd/cmdline_mtr.h                         |   49 +
 doc/api/doxy-api-index.md                          |    1 +
 doc/guides/prog_guide/index.rst                    |    1 +
 doc/guides/prog_guide/rte_flow.rst                 |   23 +
 .../prog_guide/traffic_metering_and_policing.rst   |   97 ++
 lib/librte_ether/Makefile                          |    3 +
 lib/librte_ether/rte_ethdev.h                      |    6 +
 lib/librte_ether/rte_ethdev_version.map            |   18 +
 lib/librte_ether/rte_flow.h                        |   22 +
 lib/librte_ether/rte_mtr.c                         |  229 +++++
 lib/librte_ether/rte_mtr.h                         |  723 ++++++++++++++
 lib/librte_ether/rte_mtr_driver.h                  |  221 +++++
 17 files changed, 2445 insertions(+)
 create mode 100644 app/test-pmd/cmdline_mtr.c
 create mode 100644 app/test-pmd/cmdline_mtr.h
 create mode 100644 doc/guides/prog_guide/traffic_metering_and_policing.rst
 create mode 100644 lib/librte_ether/rte_mtr.c
 create mode 100644 lib/librte_ether/rte_mtr.h
 create mode 100644 lib/librte_ether/rte_mtr_driver.h

-- 
2.7.4

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

* [PATCH V3 1/5] ethdev: add new flow action for metering and policing
  2017-10-06 14:45           ` [PATCH V3 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
@ 2017-10-06 14:45             ` Cristian Dumitrescu
  2017-10-06 14:55               ` Adrien Mazarguil
  2017-10-13 12:22               ` [PATCH V4 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
  2017-10-06 14:45             ` [PATCH V3 2/5] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
                               ` (3 subsequent siblings)
  4 siblings, 2 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-06 14:45 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, hemant.agrawal,
	jerin.jacob, jasvinder.singh

Metering and policing action typically sits on top of flow classification,
which is why MTR objects are enabled through a newly introduced flow
action.

The configuration of MTR objects is done in their own namespace (rte_mtr)
within the librte_ether library. The MTR object is hooked into ethdev RX
processing path using the "meter" flow action.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
Changes in v3:
- Implemented input from Adrien:
     - Removed doc mention on multiple MTR objects for same flow.

 doc/guides/prog_guide/rte_flow.rst | 23 +++++++++++++++++++++++
 lib/librte_ether/rte_flow.h        | 22 ++++++++++++++++++++++
 2 files changed, 45 insertions(+)

diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 662a912..5aee7ce 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1354,6 +1354,29 @@ rule or if packets are not addressed to a VF in the first place.
    | ``vf``       | VF ID to redirect packets to   |
    +--------------+--------------------------------+
 
+Action: ``METER``
+^^^^^^^^^^^^^^^^^
+
+Applies a stage of metering and policing.
+
+The metering and policing (MTR) object has to be first created using the
+rte_mtr_create() API function. The ID of the MTR object is specified as
+action parameter. More than one flow can use the same MTR object through
+the meter action. The MTR object can be further updated or queried using
+the rte_mtr* API.
+
+- Non-terminating by default.
+
+.. _table_rte_flow_action_meter:
+
+.. table:: METER
+
+   +--------------+---------------+
+   | Field        | Value         |
+   +==============+===============+
+   | ``mtr_id``   | MTR object ID |
+   +--------------+---------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index bba6169..5569a87 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -915,6 +915,14 @@ enum rte_flow_action_type {
 	 * See struct rte_flow_action_vf.
 	 */
 	RTE_FLOW_ACTION_TYPE_VF,
+
+	/**
+	 * Traffic metering and policing (MTR).
+	 *
+	 * See struct rte_flow_action_meter.
+	 * See file rte_mtr.h for MTR object configuration.
+	 */
+	RTE_FLOW_ACTION_TYPE_METER,
 };
 
 /**
@@ -1008,6 +1016,20 @@ struct rte_flow_action_vf {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_METER
+ *
+ * Traffic metering and policing (MTR).
+ *
+ * Packets matched by items of this type can be either dropped or passed to the
+ * next item with their color set by the MTR object.
+ *
+ * Non-terminating by default.
+ */
+struct rte_flow_action_meter {
+	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create(). */
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.7.4

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

* [PATCH V3 2/5] ethdev: add new eth_dev_ops function for mtr ops get
  2017-10-06 14:45           ` [PATCH V3 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
  2017-10-06 14:45             ` [PATCH V3 1/5] ethdev: add new flow action " Cristian Dumitrescu
@ 2017-10-06 14:45             ` Cristian Dumitrescu
  2017-10-12 10:58               ` Hemant Agrawal
  2017-10-06 14:45             ` [PATCH V3 3/5] ethdev: add new api for traffic metering and policing Cristian Dumitrescu
                               ` (2 subsequent siblings)
  4 siblings, 1 reply; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-06 14:45 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, hemant.agrawal,
	jerin.jacob, jasvinder.singh

Following similar approach as rte_flow and rte_tm for modularity reasons,
the ops for the new rte_mtr API are retrieved through a new eth_dev_ops
function.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
Changes in v3:
- None

Changes in v2:
-None

Changes in v1 (from RFC [1]):
- Removed ethdev API function to get the MTR ops, as it is not needed
  (input from Thomas)

[1] RFC: http://www.dpdk.org/ml/archives/dev/2017-May/066888.html

 lib/librte_ether/rte_ethdev.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 99cdd54..a5802b0 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1424,6 +1424,9 @@ typedef int (*eth_filter_ctrl_t)(struct rte_eth_dev *dev,
 typedef int (*eth_tm_ops_get_t)(struct rte_eth_dev *dev, void *ops);
 /**< @internal Get Traffic Management (TM) operations on an Ethernet device */
 
+typedef int (*eth_mtr_ops_get_t)(struct rte_eth_dev *dev, void *ops);
+/**< @internal Get Trafffic Metering and Policing (MTR) operations */
+
 typedef int (*eth_get_dcb_info)(struct rte_eth_dev *dev,
 				 struct rte_eth_dcb_info *dcb_info);
 /**< @internal Get dcb information on an Ethernet device */
@@ -1548,6 +1551,9 @@ struct eth_dev_ops {
 
 	eth_tm_ops_get_t tm_ops_get;
 	/**< Get Traffic Management (TM) operations. */
+
+	eth_mtr_ops_get_t mtr_ops_get;
+	/**< Get Traffic Metering and Policing (MTR) operations. */
 };
 
 /**
-- 
2.7.4

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

* [PATCH V3 3/5] ethdev: add new api for traffic metering and policing
  2017-10-06 14:45           ` [PATCH V3 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
  2017-10-06 14:45             ` [PATCH V3 1/5] ethdev: add new flow action " Cristian Dumitrescu
  2017-10-06 14:45             ` [PATCH V3 2/5] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
@ 2017-10-06 14:45             ` Cristian Dumitrescu
  2017-10-12 10:48               ` Hemant Agrawal
  2017-10-06 14:45             ` [PATCH V3 4/5] doc: ethdev traffic metering and policing api Cristian Dumitrescu
  2017-10-06 14:45             ` [PATCH V3 5/5] app/testpmd: cli for traffic metering and policing Cristian Dumitrescu
  4 siblings, 1 reply; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-06 14:45 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, hemant.agrawal,
	jerin.jacob, jasvinder.singh

This patch introduces new ethdev generic API for Traffic Metering and
Policing (MTR), which is yet another standard RX offload for Ethernet
devices.

Similar to rte_flow and rte_tm APIs, the configuration of MTR objects is
done in their own namespace (rte_mtr) within the librte_ether library.

Main features:
1. Traffic metering: determine the color for the current packet (green,
   yellow, red) based on history maintained by the MTR object. Supported
   algorithms: srTCM (RFC 2697), trTCM (RFC 2698 and RFC 4115).
2. Policing (per meter output color actions): re-color the packet (keep
   or change the meter output color) or drop the packet.
3. Statistics
4. Capability API

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
Changes in v3:
- None

Changes in v2:
- Implemented input from Hemant:
     - Added support for RFC 4115 trTCM algorithm
     - Added support for meter pass-through mode: see API functions
       rte_mtr_meter_enable() and rte_mtr_meter_disable()
- Implemented input from Jerin:
     - Added capability API
- Implemented input from Thomas:
     - Added new API functions under the EXPERIMENTAL section in map file
- Improved the mechanism for MTR object chaining: each MTR object can be
  configured whther to read input color from a previous MTR object in the
  same flow (if any) of from DSCP traslation table
- Improved run-time update functions
- Doxygen: added more descriptions, small fixes

Changes in v1 (from RFC [1]):
- Implemented input from Thomas:
     - Added EXPERIMENTAL tag in rte_mtr.h and MANTAINERS for this new API
- Implemented input from Adrien:
     - Added more Doxygen comments to re-inforce relationship between MTR and
       flow
- Doxygen: added hook in doxy-api-index.md

[1] RFC: http://www.dpdk.org/ml/archives/dev/2017-May/066888.html

 MAINTAINERS                             |   4 +
 doc/api/doxy-api-index.md               |   1 +
 lib/librte_ether/Makefile               |   3 +
 lib/librte_ether/rte_ethdev_version.map |  18 +
 lib/librte_ether/rte_mtr.c              | 229 ++++++++++
 lib/librte_ether/rte_mtr.h              | 723 ++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_mtr_driver.h       | 221 ++++++++++
 7 files changed, 1199 insertions(+)
 create mode 100644 lib/librte_ether/rte_mtr.c
 create mode 100644 lib/librte_ether/rte_mtr.h
 create mode 100644 lib/librte_ether/rte_mtr_driver.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5c3abf9..bce6b6f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -260,6 +260,10 @@ M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
 T: git://dpdk.org/next/dpdk-next-tm
 F: lib/librte_ether/rte_tm*
 
+Traffic Metering and Policing API - EXPERIMENTAL
+M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
+F: lib/librte_ether/rte_mtr*
+
 Crypto API
 M: Declan Doherty <declan.doherty@intel.com>
 F: lib/librte_cryptodev/
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 19e0d4f..b2342a9 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -41,6 +41,7 @@ The public API headers are grouped by topics:
   [ethctrl]            (@ref rte_eth_ctrl.h),
   [rte_flow]           (@ref rte_flow.h),
   [rte_tm]             (@ref rte_tm.h),
+  [rte_mtr]            (@ref rte_mtr.h),
   [cryptodev]          (@ref rte_cryptodev.h),
   [eventdev]           (@ref rte_eventdev.h),
   [metrics]            (@ref rte_metrics.h),
diff --git a/lib/librte_ether/Makefile b/lib/librte_ether/Makefile
index 201cb96..35ba5d9 100644
--- a/lib/librte_ether/Makefile
+++ b/lib/librte_ether/Makefile
@@ -46,6 +46,7 @@ LIBABIVER := 7
 SRCS-y += rte_ethdev.c
 SRCS-y += rte_flow.c
 SRCS-y += rte_tm.c
+SRCS-y += rte_mtr.c
 SRCS-y += ethdev_profile.c
 
 #
@@ -60,5 +61,7 @@ SYMLINK-y-include += rte_flow.h
 SYMLINK-y-include += rte_flow_driver.h
 SYMLINK-y-include += rte_tm.h
 SYMLINK-y-include += rte_tm_driver.h
+SYMLINK-y-include += rte_mtr.h
+SYMLINK-y-include += rte_mtr_driver.h
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_ether/rte_ethdev_version.map b/lib/librte_ether/rte_ethdev_version.map
index 07f9e17..c8f59a0 100644
--- a/lib/librte_ether/rte_ethdev_version.map
+++ b/lib/librte_ether/rte_ethdev_version.map
@@ -194,3 +194,21 @@ DPDK_17.11 {
 	rte_eth_dev_reset;
 
 } DPDK_17.08;
+
+EXPERIMENTAL {
+	global:
+
+	rte_mtr_capabilities_get;
+	rte_mtr_meter_profile_add;
+	rte_mtr_meter_profile_delete;
+	rte_mtr_create;
+	rte_mtr_destroy;
+	rte_mtr_meter_enable;
+	rte_mtr_meter_disable;
+	rte_mtr_meter_profile_update;
+	rte_mtr_meter_dscp_table_update;
+	rte_mtr_policer_actions_update;
+	rte_mtr_stats_update;
+	rte_mtr_stats_read;
+
+} DPDK_17.11;
diff --git a/lib/librte_ether/rte_mtr.c b/lib/librte_ether/rte_mtr.c
new file mode 100644
index 0000000..6526a97
--- /dev/null
+++ b/lib/librte_ether/rte_mtr.c
@@ -0,0 +1,229 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+
+#include <rte_errno.h>
+#include "rte_ethdev.h"
+#include "rte_mtr_driver.h"
+#include "rte_mtr.h"
+
+/* Get generic traffic metering & policing operations structure from a port. */
+const struct rte_mtr_ops *
+rte_mtr_ops_get(uint8_t port_id, struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	const struct rte_mtr_ops *ops;
+
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		rte_mtr_error_set(error,
+			ENODEV,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			rte_strerror(ENODEV));
+		return NULL;
+	}
+
+	if ((dev->dev_ops->mtr_ops_get == NULL) ||
+		(dev->dev_ops->mtr_ops_get(dev, &ops) != 0) ||
+		(ops == NULL)) {
+		rte_mtr_error_set(error,
+			ENOSYS,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			rte_strerror(ENOSYS));
+		return NULL;
+	}
+
+	return ops;
+}
+
+#define RTE_MTR_FUNC(port_id, func)			\
+({							\
+	const struct rte_mtr_ops *ops =			\
+		rte_mtr_ops_get(port_id, error);		\
+	if (ops == NULL)					\
+		return -rte_errno;			\
+							\
+	if (ops->func == NULL)				\
+		return -rte_mtr_error_set(error,		\
+			ENOSYS,				\
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,	\
+			NULL,				\
+			rte_strerror(ENOSYS));		\
+							\
+	ops->func;					\
+})
+
+/* MTR capabilities get */
+int
+rte_mtr_capabilities_get(uint8_t port_id,
+	struct rte_mtr_capabilities *cap,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, capabilities_get)(dev,
+		cap, error);
+}
+
+/* MTR meter profile add */
+int
+rte_mtr_meter_profile_add(uint8_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);
+}
+
+/** MTR meter profile delete */
+int
+rte_mtr_meter_profile_delete(uint8_t port_id,
+	uint32_t meter_profile_id,
+	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);
+}
+
+/** MTR object create */
+int
+rte_mtr_create(uint8_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);
+}
+
+/** MTR object destroy */
+int
+rte_mtr_destroy(uint8_t port_id,
+	uint32_t mtr_id,
+	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 object meter enable */
+int
+rte_mtr_meter_enable(uint8_t port_id,
+	uint32_t mtr_id,
+	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 object meter disable */
+int
+rte_mtr_meter_disable(uint8_t port_id,
+	uint32_t mtr_id,
+	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 object meter profile update */
+int
+rte_mtr_meter_profile_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint32_t meter_profile_id,
+	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 object meter DSCP table update */
+int
+rte_mtr_meter_dscp_table_update(uint8_t port_id,
+	uint32_t mtr_id,
+	enum rte_mtr_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 object policer action update */
+int
+rte_mtr_policer_actions_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint32_t action_mask,
+	enum rte_mtr_policer_action *actions,
+	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);
+}
+
+/** MTR object enabled stats update */
+int
+rte_mtr_stats_update(uint8_t port_id,
+	uint32_t mtr_id,
+	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 object stats read */
+int
+rte_mtr_stats_read(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error)
+{
+	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);
+}
diff --git a/lib/librte_ether/rte_mtr.h b/lib/librte_ether/rte_mtr.h
new file mode 100644
index 0000000..f0f897f
--- /dev/null
+++ b/lib/librte_ether/rte_mtr.h
@@ -0,0 +1,723 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation.
+ *   Copyright(c) 2017 NXP.
+ *   Copyright(c) 2017 Cavium.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __INCLUDE_RTE_MTR_H__
+#define __INCLUDE_RTE_MTR_H__
+
+/**
+ * @file
+ * RTE Generic Traffic Metering and Policing API
+ *
+ * This interface provides the ability to configure the traffic metering and
+ * policing (MTR) in a generic way.
+ *
+ * The processing done for each input packet hitting a MTR object is:
+ *    A) Traffic metering: The packet is assigned a color (the meter output
+ *       color), based on the previous history of the flow reflected in the
+ *       current state of the MTR object, according to the specific traffic
+ *       metering algorithm. The traffic metering algorithm can typically work
+ *       in color aware mode, in which case the input packet already has an
+ *       initial color (the input color), or in color blind mode, which is
+ *       equivalent to considering all input packets initially colored as green.
+ *    B) Policing: There is a separate policer action configured for each meter
+ *       output color, which can:
+ *          a) Drop the packet.
+ *          b) Keep the same packet color: the policer output color matches the
+ *             meter output color (essentially a no-op action).
+ *          c) Recolor the packet: the policer output color is different 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).
+ *    C) Statistics: The set of counters maintained for each MTR object is
+ *       configurable and subject to the implementation support. This set
+ *       includes the number of packets and bytes dropped or passed for each
+ *       output color.
+ *
+ * Once successfully created, an MTR object is linked to one or several flows
+ * through the meter action of the flow API.
+ *    A) Whether an MTR object is private to a flow or potentially shared by
+ *       several flows has to be specified at creation time.
+ *    B) Several meter actions can be potentially registered for the same flow.
+ *
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ */
+#include <stdint.h>
+
+#include <rte_common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Color
+ */
+enum rte_mtr_color {
+	RTE_MTR_GREEN = 0, /**< Green */
+	RTE_MTR_YELLOW, /**< Yellow */
+	RTE_MTR_RED, /**< Red */
+	RTE_MTR_COLORS /**< Number of colors. */
+};
+
+/**
+ * Statistics counter type
+ */
+enum rte_mtr_stats_type {
+	/** Number of packets passed as green by the policer. */
+	RTE_MTR_STATS_N_PKTS_GREEN = 1 << 0,
+
+	/** Number of bytes passed as green by the policer. */
+	RTE_MTR_STATS_N_BYTES_GREEN = 1 << 1,
+
+	/** Number of packets passed as yellow by the policer. */
+	RTE_MTR_STATS_N_PKTS_YELLOW = 1 << 2,
+
+	/** Number of bytes passed as yellow by the policer. */
+	RTE_MTR_STATS_N_BYTES_YELLOW = 1 << 3,
+
+	/** Number of packets passed as red by the policer. */
+	RTE_MTR_STATS_N_PKTS_RED = 1 << 4,
+
+	/** Number of bytes passed as red by the policer. */
+	RTE_MTR_STATS_N_BYTES_RED = 1 << 5,
+
+	/** Number of packets dropped by the policer. */
+	RTE_MTR_STATS_N_PKTS_DROPPED = 1 << 6,
+
+	/** Number of bytes dropped by the policer. */
+	RTE_MTR_STATS_N_BYTES_DROPPED = 1 << 7,
+};
+
+/**
+ * Statistics counters
+ */
+struct rte_mtr_stats {
+	/** Number of packets passed by the policer (per color). */
+	uint64_t n_pkts[RTE_MTR_COLORS];
+
+	/** Number of bytes passed by the policer (per color). */
+	uint64_t n_bytes[RTE_MTR_COLORS];
+
+	/** Number of packets dropped by the policer. */
+	uint64_t n_pkts_dropped;
+
+	/** Number of bytes passed by the policer. */
+	uint64_t n_bytes_dropped;
+};
+
+/**
+ * Traffic metering algorithms
+ */
+enum rte_mtr_algorithm {
+	/** Single Rate Three Color Marker (srTCM) - IETF RFC 2697. */
+	RTE_MTR_SRTCM_RFC2697,
+
+	/** Two Rate Three Color Marker (trTCM) - IETF RFC 2698. */
+	RTE_MTR_TRTCM_RFC2698,
+
+	/** Two Rate Three Color Marker (trTCM) - IETF RFC 4115. */
+	RTE_MTR_TRTCM_RFC4115,
+};
+
+/**
+ * Meter profile
+ */
+struct rte_mtr_meter_profile {
+	/** Traffic metering algorithm. */
+	enum rte_mtr_algorithm alg;
+
+	RTE_STD_C11
+	union {
+		/** Items only valid when *alg* is set to srTCM - RFC 2697. */
+		struct {
+			/** Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/** Committed Burst Size (CBS) (bytes). */
+			uint64_t cbs;
+
+			/** Excess Burst Size (EBS) (bytes). */
+			uint64_t ebs;
+		} srtcm_rfc2697;
+
+		/** Items only valid when *alg* is set to trTCM - RFC 2698. */
+		struct {
+			/** Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/** Peak Information Rate (PIR) (bytes/second). */
+			uint64_t pir;
+
+			/** Committed Burst Size (CBS) (byes). */
+			uint64_t cbs;
+
+			/** Peak Burst Size (PBS) (bytes). */
+			uint64_t pbs;
+		} trtcm_rfc2698;
+
+		/** Items only valid when *alg* is set to trTCM - RFC 4115. */
+		struct {
+			/** Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/** Excess Information Rate (EIR) (bytes/second). */
+			uint64_t eir;
+
+			/** Committed Burst Size (CBS) (byes). */
+			uint64_t cbs;
+
+			/** Excess Burst Size (EBS) (bytes). */
+			uint64_t ebs;
+		} trtcm_rfc4115;
+	};
+};
+
+/**
+ * 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
+ *
+ * @see enum rte_mtr_stats_type
+ */
+struct rte_mtr_params {
+	/** Meter profile ID. */
+	uint32_t meter_profile_id;
+
+	/** 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
+	 * determined by the latest MTR object in the same flow is used as the
+	 * input color by the current MTR object, otherwise the current MTR
+	 * object uses the *dscp_table* to determine the input color. When zero:
+	 * the color determined by any previous MTR object in same flow is
+	 * ignored by the current MTR object, which uses the *dscp_table* to
+	 * determine the input color.
+	 */
+	int use_prev_mtr_color;
+
+	/** Meter input color. 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). The color blind mode
+	 * is configured by setting *use_prev_mtr_color* to 0 and *dscp_table*
+	 * to either NULL or to an all-green populated table. When
+	 * *use_prev_mtr_color* is non-zero value or when *dscp_table* contains
+	 * at least one yellow or red color element, then the color aware mode
+	 * is configured.
+	 */
+	enum rte_mtr_color *dscp_table;
+
+	/** Non-zero to enable the meter, zero to disable the meter at the time
+	 * of MTR object creation.
+	 * @see rte_mtr_meter_disable()
+	 */
+	int meter_enable;
+
+	/** Policer actions (per meter output color). */
+	enum rte_mtr_policer_action action[RTE_MTR_COLORS];
+
+	/** Set of stats counters to be enabled.
+	 * @see enum rte_mtr_stats_type
+	 */
+	uint64_t stats_mask;
+};
+
+/**
+ * MTR capabilities
+ */
+struct rte_mtr_capabilities {
+	/** Maximum number of MTR objects. */
+	uint32_t n_max;
+
+	/** Maximum number of MTR objects that can be shared by multiple flows.
+	 * The value of zero indicates that shared MTR objects are not
+	 * supported. The maximum value is *n_max*.
+	 */
+	uint32_t n_shared_max;
+
+	/** When non-zero, this flag indicates that all the MTR objects that
+	 * cannot be shared by multiple flows have identical capability set.
+	 */
+	int identical;
+
+	/** When non-zero, this flag indicates that all the MTR objects that
+	 * can be shared by multiple flows have identical capability set.
+	 */
+	int shared_identical;
+
+	/** Maximum number of flows that can share the same MTR object. The
+	 * value of zero is invalid. The value of 1 means that shared MTR
+	 * objects not supported.
+	 */
+	uint32_t shared_n_flows_per_mtr_max;
+
+	/** Maximum number of MTR objects that can be part of the same flow. The
+	 * value of zero is invalid. The value of 1 indicates that MTR object
+	 * chaining is not supported. The maximum value is *n_max*.
+	 */
+	uint32_t chaining_n_mtrs_per_flow_max;
+
+	/**
+	 * When non-zero, it indicates that the packet color identified by one
+	 * MTR object can be used as the packet input color by any subsequent
+	 * MTR object from the same flow. When zero, it indicates that the color
+	 * determined by one MTR object is always ignored by any subsequent MTR
+	 * object from the same flow. Only valid when MTR chaining is supported,
+	 * i.e. *chaining_n_mtrs_per_flow_max* is greater than 1. When non-zero,
+	 * it also means that the color aware mode is supported by at least one
+	 * metering algorithm.
+	 */
+	int chaining_use_prev_mtr_color_supported;
+
+	/**
+	 * When non-zero, it indicates that the packet color identified by one
+	 * MTR object is always used as the packet input color by any subsequent
+	 * MTR object that is part of the same flow. When zero, it indicates
+	 * that whether the color determined by one MTR object is either ignored
+	 * or used as the packet input color by any subsequent MTR object from
+	 * the same flow is individually configurable for each MTR object. Only
+	 * valid when *chaining_use_prev_mtr_color_supported* is non-zero.
+	 */
+	int chaining_use_prev_mtr_color_enforced;
+
+	/** Maximum number of MTR objects that can have their meter configured
+	 * to run the srTCM RFC 2697 algorithm. The value of 0 indicates this
+	 * metering algorithm is not supported. The maximum value is *n_max*.
+	 */
+	uint32_t meter_srtcm_rfc2697_n_max;
+
+	/** Maximum number of MTR objects that can have their meter configured
+	 * to run the trTCM RFC 2698 algorithm. The value of 0 indicates this
+	 * metering algorithm is not supported. The maximum value is *n_max*.
+	 */
+	uint32_t meter_trtcm_rfc2698_n_max;
+
+	/** Maximum number of MTR objects that can have their meter configured
+	 * to run the trTCM RFC 4115 algorithm. The value of 0 indicates this
+	 * metering algorithm is not supported. The maximum value is *n_max*.
+	 */
+	uint32_t meter_trtcm_rfc4115_n_max;
+
+	/** Maximum traffic rate that can be metered by a single MTR object. For
+	 * srTCM RFC 2697, this is the maximum CIR rate. For trTCM RFC 2698,
+	 * this is the maximum PIR rate. For trTCM RFC 4115, this is the maximum
+	 * value for the sum of PIR and EIR rates.
+	 */
+	uint64_t meter_rate_max;
+
+	/**
+	 * When non-zero, it indicates that color aware mode is supported for
+	 * the srTCM RFC 2697 metering algorithm.
+	 */
+	int color_aware_srtcm_rfc2697_supported;
+
+	/**
+	 * When non-zero, it indicates that color aware mode is supported for
+	 * the trTCM RFC 2698 metering algorithm.
+	 */
+	int color_aware_trtcm_rfc2698_supported;
+
+	/**
+	 * When non-zero, it indicates that color aware mode is supported for
+	 * the trTCM RFC 4115 metering algorithm.
+	 */
+	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
+	 */
+	uint64_t stats_mask;
+};
+
+/**
+ * Verbose error types.
+ *
+ * Most of them provide the type of the object referenced by struct
+ * rte_mtr_error::cause.
+ */
+enum rte_mtr_error_type {
+	RTE_MTR_ERROR_TYPE_NONE, /**< No error. */
+	RTE_MTR_ERROR_TYPE_UNSPECIFIED, /**< Cause unspecified. */
+	RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+	RTE_MTR_ERROR_TYPE_METER_PROFILE,
+	RTE_MTR_ERROR_TYPE_MTR_ID,
+	RTE_MTR_ERROR_TYPE_MTR_PARAMS,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED,
+	RTE_MTR_ERROR_TYPE_STATS_MASK,
+	RTE_MTR_ERROR_TYPE_STATS,
+	RTE_MTR_ERROR_TYPE_SHARED,
+};
+
+/**
+ * Verbose error structure definition.
+ *
+ * This object is normally allocated by applications and set by PMDs, the
+ * message points to a constant string which does not need to be freed by
+ * the application, however its pointer can be considered valid only as long
+ * as its associated DPDK port remains configured. Closing the underlying
+ * device or unloading the PMD invalidates it.
+ *
+ * Both cause and message may be NULL regardless of the error type.
+ */
+struct rte_mtr_error {
+	enum rte_mtr_error_type type; /**< Cause field and error type. */
+	const void *cause; /**< Object responsible for the error. */
+	const char *message; /**< Human-readable error message. */
+};
+
+/**
+ * MTR capabilities get
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[out] cap
+ *   MTR capabilities. 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.
+ */
+int
+rte_mtr_capabilities_get(uint8_t port_id,
+	struct rte_mtr_capabilities *cap,
+	struct rte_mtr_error *error);
+
+/**
+ * Meter profile add
+ *
+ * Create a new meter profile with ID set to *meter_profile_id*. 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.
+ */
+int
+rte_mtr_meter_profile_add(uint8_t port_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_meter_profile *profile,
+	struct rte_mtr_error *error);
+
+/**
+ * Meter profile delete
+ *
+ * Delete an existing meter profile. This operation fails when there is
+ * currently at least one user (i.e. MTR object) of this profile.
+ *
+ * @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[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_profile_delete(uint8_t port_id,
+	uint32_t meter_profile_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
+ * associated flow action for traffic metering and policing.
+ *
+ * @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
+ *   Non-zero when this MTR object can be shared by multiple flows, zero when
+ *   this MTR object can be used by a single flow.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_flow_action_type::RTE_FLOW_ACTION_TYPE_METER
+ */
+int
+rte_mtr_create(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_params *params,
+	int shared,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object destroy
+ *
+ * Delete an existing MTR object. This operation fails when there is currently
+ * at least one user (i.e. flow) of this MTR object.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be valid.
+ *   created for the current port.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_destroy(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object meter disable
+ *
+ * Disable the meter of an existing MTR object. In disabled state, the meter of
+ * the current MTR object works in pass-through mode, meaning that for each
+ * input packet the meter output color is always the same as the input color. In
+ * particular, when the meter of the current MTR object is configured in color
+ * blind mode, the input color is always green, so the meter output color is
+ * also always green. Note that the policer and the statistics of the current
+ * MTR object are working as usual while the meter is disabled. No action is
+ * taken and this function returns successfully when the meter of the current
+ * MTR object is already disabled.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_disable(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object meter enable
+ *
+ * Enable the meter of an existing MTR object. If the MTR object has its meter
+ * already enabled, then no action is taken and this function returns
+ * successfully.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_enable(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object meter profile 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] meter_profile_id
+ *   Meter profile ID for the current MTR object. Needs to be valid.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_profile_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_error *error);
+
+/**
+ * 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] 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
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_dscp_table_update(uint8_t port_id,
+	uint32_t mtr_id,
+	enum rte_mtr_color *dscp_table,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object policer actions 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[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_policer_actions_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint32_t action_mask,
+	enum rte_mtr_policer_action *actions,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object enabled statistics counters 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] stats_mask
+ *   Mask of statistics counter types to be enabled for the current MTR object.
+ *   Any statistics counter type not included in this set is to be disabled for
+ *   the current MTR object.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_mtr_stats_type
+ */
+int
+rte_mtr_stats_update(uint8_t port_id,
+	uint32_t mtr_id,
+	uint64_t stats_mask,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object statistics counters read
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be valid.
+ * @param[out] stats
+ *   When non-NULL, it contains the current value for the statistics counters
+ *   enabled for the current MTR object.
+ * @param[out] stats_mask
+ *   When non-NULL, it contains the mask of statistics counter types that are
+ *   currently enabled for this MTR object, indicating which of the counters
+ *   retrieved with the *stats* structure are valid.
+ * @param[in] clear
+ *   When this parameter has a non-zero value, the statistics counters are
+ *   cleared (i.e. set to zero) immediately after they have been read,
+ *   otherwise the statistics counters are left untouched.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_mtr_stats_type
+ */
+int
+rte_mtr_stats_read(uint8_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_RTE_MTR_H__ */
diff --git a/lib/librte_ether/rte_mtr_driver.h b/lib/librte_ether/rte_mtr_driver.h
new file mode 100644
index 0000000..bb7deed
--- /dev/null
+++ b/lib/librte_ether/rte_mtr_driver.h
@@ -0,0 +1,221 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __INCLUDE_RTE_MTR_DRIVER_H__
+#define __INCLUDE_RTE_MTR_DRIVER_H__
+
+/**
+ * @file
+ * RTE Generic Traffic Metering and Policing API (Driver Side)
+ *
+ * This file provides implementation helpers for internal use by PMDs, they
+ * are not intended to be exposed to applications and are not subject to ABI
+ * versioning.
+ */
+
+#include <stdint.h>
+
+#include <rte_errno.h>
+#include "rte_ethdev.h"
+#include "rte_mtr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int (*rte_mtr_capabilities_get_t)(struct rte_eth_dev *dev,
+	struct rte_mtr_capabilities *cap,
+	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,
+	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_error *error);
+/**< @internal MTR meter profile delete */
+
+typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	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_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_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_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_error *error);
+/**< @internal MTR object meter profile update */
+
+typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	enum rte_mtr_color *dscp_table,
+	struct rte_mtr_error *error);
+/**< @internal MTR object meter DSCP table update */
+
+typedef int (*rte_mtr_policer_actions_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	uint32_t action_mask,
+	enum rte_mtr_policer_action *actions,
+	struct rte_mtr_error *error);
+/**< @internal MTR object policer action update*/
+
+typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	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_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error);
+/**< @internal MTR object stats read */
+
+struct rte_mtr_ops {
+	/** MTR capabilities get */
+	rte_mtr_capabilities_get_t capabilities_get;
+
+	/** MTR meter profile add */
+	rte_mtr_meter_profile_add_t meter_profile_add;
+
+	/** MTR meter profile delete */
+	rte_mtr_meter_profile_delete_t meter_profile_delete;
+
+	/** MTR object create */
+	rte_mtr_create_t create;
+
+	/** MTR object destroy */
+	rte_mtr_destroy_t destroy;
+
+	/** MTR object meter enable */
+	rte_mtr_meter_enable_t meter_enable;
+
+	/** MTR object meter disable */
+	rte_mtr_meter_disable_t meter_disable;
+
+	/** MTR object meter profile update */
+	rte_mtr_meter_profile_update_t meter_profile_update;
+
+	/** 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;
+};
+
+/**
+ * Initialize generic error structure.
+ *
+ * This function also sets rte_errno to a given value.
+ *
+ * @param[out] error
+ *   Pointer to error structure (may be NULL).
+ * @param[in] code
+ *   Related error code (rte_errno).
+ * @param[in] type
+ *   Cause field and error type.
+ * @param[in] cause
+ *   Object responsible for the error.
+ * @param[in] message
+ *   Human-readable error message.
+ *
+ * @return
+ *   Error code.
+ */
+static inline int
+rte_mtr_error_set(struct rte_mtr_error *error,
+		   int code,
+		   enum rte_mtr_error_type type,
+		   const void *cause,
+		   const char *message)
+{
+	if (error) {
+		*error = (struct rte_mtr_error){
+			.type = type,
+			.cause = cause,
+			.message = message,
+		};
+	}
+	rte_errno = code;
+	return code;
+}
+
+/**
+ * Get generic traffic metering and policing operations structure from a port
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[out] error
+ *   Error details
+ *
+ * @return
+ *   The traffic metering and policing operations structure associated with
+ *   port_id on success, NULL otherwise.
+ */
+const struct rte_mtr_ops *
+rte_mtr_ops_get(uint8_t port_id, struct rte_mtr_error *error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_RTE_MTR_DRIVER_H__ */
-- 
2.7.4

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

* [PATCH V3 4/5] doc: ethdev traffic metering and policing api
  2017-10-06 14:45           ` [PATCH V3 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
                               ` (2 preceding siblings ...)
  2017-10-06 14:45             ` [PATCH V3 3/5] ethdev: add new api for traffic metering and policing Cristian Dumitrescu
@ 2017-10-06 14:45             ` Cristian Dumitrescu
  2017-10-12 14:59               ` Mcnamara, John
  2017-10-12 15:01               ` Mcnamara, John
  2017-10-06 14:45             ` [PATCH V3 5/5] app/testpmd: cli for traffic metering and policing Cristian Dumitrescu
  4 siblings, 2 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-06 14:45 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, hemant.agrawal,
	jerin.jacob, jasvinder.singh

Add new section in the Programmer Guide for the ethdev traffic metering
and policing (MTR) API.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 doc/guides/prog_guide/index.rst                    |  1 +
 .../prog_guide/traffic_metering_and_policing.rst   | 97 ++++++++++++++++++++++
 2 files changed, 98 insertions(+)
 create mode 100644 doc/guides/prog_guide/traffic_metering_and_policing.rst

diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index 40f04a1..c9eeba9 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -44,6 +44,7 @@ Programmer's Guide
     mbuf_lib
     poll_mode_drv
     rte_flow
+    traffic_metering_and_policing
     traffic_management
     cryptodev_lib
     link_bonding_poll_mode_drv_lib
diff --git a/doc/guides/prog_guide/traffic_metering_and_policing.rst b/doc/guides/prog_guide/traffic_metering_and_policing.rst
new file mode 100644
index 0000000..39a7051
--- /dev/null
+++ b/doc/guides/prog_guide/traffic_metering_and_policing.rst
@@ -0,0 +1,97 @@
+..  BSD LICENSE
+    Copyright(c) 2017 Intel Corporation. All rights reserved.
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+    * Neither the name of Intel Corporation nor the names of its
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Traffic Metering and Policing (MTR) API
+=======================================
+
+
+Overview
+--------
+
+This is the generic API for the Quality of Service (QoS) Traffic Metering and
+Policing (MTR) of Ethernet devices. This API is agnostic of the underlying HW,
+SW or mixed HW-SW implementation.
+
+Main features:
+
+* Part of DPDK rte_ethdev API
+* Capability query API
+* Metering algorithms: RFC 2697 Single Rate Three Color Marker (srTCM), RFC 2698
+  and RFC 4115 Two Rate Three Color Marker (trTCM)
+* Policer actions (per meter output color): recolor, drop
+* Statistics (per policer output color)
+
+Configuration steps
+-------------------
+
+Metering and policing stage typically sits on top of flow classification,
+which is why the MTR objects are enabled through a special "meter" action.
+
+The MTR objects are created and updated in their own name space (rte_mtr)
+within the librte_ether library. Whether an MTR object is private to a flow
+or potentially shared by several flows has to be specified at its creation
+time.
+
+Once successfully created, an MTR object is hooked into the RX processing path
+of the Ethernet device by linking it to one or several flows through the
+dedicated "meter" flow action. One or several "meter" actions can be registered
+for the same flow. An MTR object can only be destroyed if there are no flows
+using it.
+
+Run-time processing
+-------------------
+
+Traffic metering determines the color for the current packet (green, yellow,
+red) based on the previous history for this flow as maintained by the MTR
+object. The policer can do nothing, override the color the packet or drop the
+packet. Statistics counters are maintained for MTR object, as configured.
+
+The processing done for each input packet hitting an MTR object is:
+* Traffic metering: The packet is assigned a color (the meter output
+  color) based on the previous traffic history reflected in the
+  current state of the MTR object, according to the specific traffic
+  metering algorithm. The traffic metering algorithm can typically work
+  in color aware mode, in which case the input packet already has an
+  initial color (the input color), or in 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).
+* Statistics: The set of counters maintained for each MTR object is
+  configurable and subject to the implementation support. This set
+  includes the number of packets and bytes dropped or passed for each
+  output color.
-- 
2.7.4

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

* [PATCH V3 5/5] app/testpmd: cli for traffic metering and policing
  2017-10-06 14:45           ` [PATCH V3 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
                               ` (3 preceding siblings ...)
  2017-10-06 14:45             ` [PATCH V3 4/5] doc: ethdev traffic metering and policing api Cristian Dumitrescu
@ 2017-10-06 14:45             ` Cristian Dumitrescu
  2017-10-13  6:32               ` Wu, Jingjing
  4 siblings, 1 reply; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-06 14:45 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, hemant.agrawal,
	jerin.jacob, jasvinder.singh

Add CLI commands to exercise the ethdev Traffic Metering and Policing
(MTR) API.

Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
Changes in v3:
- Added newline at the end of cmdline_mtr.h

 app/test-pmd/Makefile       |    1 +
 app/test-pmd/cmdline.c      |   10 +
 app/test-pmd/cmdline_flow.c |   24 +
 app/test-pmd/cmdline_mtr.c  | 1013 +++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/cmdline_mtr.h  |   49 +++
 5 files changed, 1097 insertions(+)
 create mode 100644 app/test-pmd/cmdline_mtr.c
 create mode 100644 app/test-pmd/cmdline_mtr.h

diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile
index c36be19..8fb6491 100644
--- a/app/test-pmd/Makefile
+++ b/app/test-pmd/Makefile
@@ -48,6 +48,7 @@ SRCS-y := testpmd.c
 SRCS-y += parameters.c
 SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline.c
 SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_flow.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_mtr.c
 SRCS-y += config.c
 SRCS-y += iofwd.c
 SRCS-y += macfwd.c
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index ccdf239..8338b5c 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -99,6 +99,7 @@
 #include <rte_pmd_bnxt.h>
 #endif
 #include "testpmd.h"
+#include "cmdline_mtr.h"
 
 static struct cmdline *testpmd_cl;
 
@@ -14334,6 +14335,15 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_hash_input_set,
 	(cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
 	(cmdline_parse_inst_t *)&cmd_flow,
+	(cmdline_parse_inst_t *)&cmd_add_port_meter_profile_srtcm,
+	(cmdline_parse_inst_t *)&cmd_add_port_meter_profile_trtcm,
+	(cmdline_parse_inst_t *)&cmd_del_port_meter_profile,
+	(cmdline_parse_inst_t *)&cmd_set_port_meter,
+	(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_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,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index a17a004..f210ce5 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -194,6 +194,8 @@ enum index {
 	ACTION_VF,
 	ACTION_VF_ORIGINAL,
 	ACTION_VF_ID,
+	ACTION_METER,
+	ACTION_METER_ID,
 };
 
 /** Size of pattern[] field in struct rte_flow_item_raw. */
@@ -601,6 +603,7 @@ static const enum index next_action[] = {
 	ACTION_RSS,
 	ACTION_PF,
 	ACTION_VF,
+	ACTION_METER,
 	ZERO,
 };
 
@@ -635,6 +638,12 @@ static const enum index action_vf[] = {
 	ZERO,
 };
 
+static const enum index action_meter[] = {
+	ACTION_METER_ID,
+	ACTION_NEXT,
+	ZERO,
+};
+
 static int parse_init(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
@@ -1566,6 +1575,21 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
 		.call = parse_vc_conf,
 	},
+	[ACTION_METER] = {
+		.name = "meter",
+		.help = "meter the directed packets at given id",
+		.priv = PRIV_ACTION(METER,
+				    sizeof(struct rte_flow_action_meter)),
+		.next = NEXT(action_meter),
+		.call = parse_vc,
+	},
+	[ACTION_METER_ID] = {
+		.name = "mtr_id",
+		.help = "meter id to use",
+		.next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
+		.call = parse_vc_conf,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
diff --git a/app/test-pmd/cmdline_mtr.c b/app/test-pmd/cmdline_mtr.c
new file mode 100644
index 0000000..58feee5
--- /dev/null
+++ b/app/test-pmd/cmdline_mtr.c
@@ -0,0 +1,1013 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+
+#include <rte_ethdev.h>
+#include <rte_flow.h>
+#include <rte_mtr.h>
+
+#include "testpmd.h"
+#include "cmdline_mtr.h"
+
+/** Display Meter Error Message */
+static void
+print_err_msg(struct rte_mtr_error *error)
+{
+	static const char *const errstrlist[] = {
+		[RTE_MTR_ERROR_TYPE_NONE] = "no error",
+		[RTE_MTR_ERROR_TYPE_UNSPECIFIED] = "cause unspecified",
+		[RTE_MTR_ERROR_TYPE_METER_PROFILE_ID] = "meter profile id",
+		[RTE_MTR_ERROR_TYPE_METER_PROFILE] = "meter profile null",
+		[RTE_MTR_ERROR_TYPE_MTR_ID]	= "meter id",
+		[RTE_MTR_ERROR_TYPE_MTR_PARAMS] = "meter params null",
+		[RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN]
+			= "policer action(green)",
+		[RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW]
+			= "policer action(yellow)",
+		[RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED]
+			= "policer action(red)",
+		[RTE_MTR_ERROR_TYPE_STATS_MASK] = "stats mask",
+		[RTE_MTR_ERROR_TYPE_STATS] = "stats",
+		[RTE_MTR_ERROR_TYPE_SHARED]
+			= "shared meter",
+	};
+
+	const char *errstr;
+	char buf[64];
+
+	if ((unsigned int)error->type >= RTE_DIM(errstrlist) ||
+		!errstrlist[error->type])
+		errstr = "unknown type";
+	else
+		errstr = errstrlist[error->type];
+
+	if (error->cause)
+		snprintf(buf, sizeof(buf), "cause: %p, ", error->cause);
+
+	printf("%s: %s%s (error %d)\n", errstr, error->cause ? buf : "",
+		error->message ? error->message : "(no stated reason)",
+		error->type);
+}
+
+static int
+string_to_policer_action(char *s)
+{
+	if (strcmp(s, "G") == 0)
+		return MTR_POLICER_ACTION_COLOR_GREEN;
+
+	if (strcmp(s, "Y") == 0)
+		return MTR_POLICER_ACTION_COLOR_YELLOW;
+
+	if (strcmp(s, "R") == 0)
+		return MTR_POLICER_ACTION_COLOR_RED;
+
+	if (strcmp(s, "D") == 0)
+		return MTR_POLICER_ACTION_DROP;
+
+	return -1;
+}
+
+/* *** Add Port Meter Profile srtcm_rfc2697 *** */
+struct cmd_add_port_meter_profile_srtcm_result {
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	cmdline_fixed_string_t srtcm_rfc2697;
+	uint8_t port_id;
+	uint32_t profile_id;
+	uint64_t cir;
+	uint64_t cbs;
+	uint64_t ebs;
+	uint8_t color_aware;
+};
+
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_add =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result, add, "add");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			port, "port");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			meter, "meter");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			profile, "profile");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_srtcm_rfc2697 =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			srtcm_rfc2697, "srtcm_rfc2697");
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			port_id, UINT8);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			profile_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_cir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			cir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_cbs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			cbs, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_ebs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			ebs, UINT64);
+
+static void cmd_add_port_meter_profile_srtcm_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_add_port_meter_profile_srtcm_result *res = parsed_result;
+	struct rte_mtr_meter_profile mp;
+	struct rte_mtr_error error;
+	uint32_t profile_id = res->profile_id;
+	uint8_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Private shaper profile params */
+	memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
+	mp.alg = 0;
+	mp.srtcm_rfc2697.cir = res->cir;
+	mp.srtcm_rfc2697.cbs = res->cbs;
+	mp.srtcm_rfc2697.ebs = res->ebs;
+
+	ret = rte_mtr_meter_profile_add(port_id, profile_id, &mp, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_add_port_meter_profile_srtcm = {
+	.f = cmd_add_port_meter_profile_srtcm_parsed,
+	.data = NULL,
+	.help_str = "Add port meter profile srtcm (rfc2697)",
+	.tokens = {
+		(void *)&cmd_add_port_meter_profile_srtcm_add,
+		(void *)&cmd_add_port_meter_profile_srtcm_port,
+		(void *)&cmd_add_port_meter_profile_srtcm_meter,
+		(void *)&cmd_add_port_meter_profile_srtcm_profile,
+		(void *)&cmd_add_port_meter_profile_srtcm_port_id,
+		(void *)&cmd_add_port_meter_profile_srtcm_profile_id,
+		(void *)&cmd_add_port_meter_profile_srtcm_srtcm_rfc2697,
+		(void *)&cmd_add_port_meter_profile_srtcm_cir,
+		(void *)&cmd_add_port_meter_profile_srtcm_cbs,
+		(void *)&cmd_add_port_meter_profile_srtcm_ebs,
+		NULL,
+	},
+};
+
+/* *** Add Port Meter Profile trtcm_rfc2698 *** */
+struct cmd_add_port_meter_profile_trtcm_result {
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	cmdline_fixed_string_t trtcm_rfc2698;
+	uint8_t port_id;
+	uint32_t profile_id;
+	uint64_t cir;
+	uint64_t pir;
+	uint64_t cbs;
+	uint64_t pbs;
+};
+
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_add =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result, add, "add");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			port, "port");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			meter, "meter");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			profile, "profile");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_trtcm_rfc2698 =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			trtcm_rfc2698, "trtcm_rfc2698");
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			port_id, UINT8);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			profile_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_cir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			cir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_pir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			pir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_cbs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			cbs, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_pbs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			pbs, UINT64);
+
+static void cmd_add_port_meter_profile_trtcm_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_add_port_meter_profile_trtcm_result *res = parsed_result;
+	struct rte_mtr_meter_profile mp;
+	struct rte_mtr_error error;
+	uint32_t profile_id = res->profile_id;
+	uint8_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Private shaper profile params */
+	memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
+	mp.alg = 0;
+	mp.trtcm_rfc2698.cir = res->cir;
+	mp.trtcm_rfc2698.pir = res->pir;
+	mp.trtcm_rfc2698.cbs = res->cbs;
+	mp.trtcm_rfc2698.pbs = res->pbs;
+
+	ret = rte_mtr_meter_profile_add(port_id, profile_id, &mp, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm = {
+	.f = cmd_add_port_meter_profile_trtcm_parsed,
+	.data = NULL,
+	.help_str = "Add port meter profile trtcm (rfc2698)",
+	.tokens = {
+		(void *)&cmd_add_port_meter_profile_trtcm_add,
+		(void *)&cmd_add_port_meter_profile_trtcm_port,
+		(void *)&cmd_add_port_meter_profile_trtcm_meter,
+		(void *)&cmd_add_port_meter_profile_trtcm_profile,
+		(void *)&cmd_add_port_meter_profile_trtcm_port_id,
+		(void *)&cmd_add_port_meter_profile_trtcm_profile_id,
+		(void *)&cmd_add_port_meter_profile_trtcm_trtcm_rfc2698,
+		(void *)&cmd_add_port_meter_profile_trtcm_cir,
+		(void *)&cmd_add_port_meter_profile_trtcm_pir,
+		(void *)&cmd_add_port_meter_profile_trtcm_cbs,
+		(void *)&cmd_add_port_meter_profile_trtcm_pbs,
+		NULL,
+	},
+};
+
+/* *** Add Port Meter Profile trtcm_rfc4115 *** */
+struct cmd_add_port_meter_profile_trtcm_rfc4115_result {
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	cmdline_fixed_string_t trtcm_rfc4115;
+	uint8_t port_id;
+	uint32_t profile_id;
+	uint64_t cir;
+	uint64_t eir;
+	uint64_t cbs;
+	uint64_t ebs;
+};
+
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_add =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result, add,
+		"add");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			port, "port");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			meter, "meter");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			profile, "profile");
+cmdline_parse_token_string_t
+	cmd_add_port_meter_profile_trtcm_rfc4115_trtcm_rfc4115 =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			trtcm_rfc4115, "trtcm_rfc4115");
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			port_id, UINT8);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			profile_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_cir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			cir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_eir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			eir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_cbs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			cbs, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_ebs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			ebs, UINT64);
+
+static void cmd_add_port_meter_profile_trtcm_rfc4115_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_add_port_meter_profile_trtcm_rfc4115_result *res =
+		parsed_result;
+	struct rte_mtr_meter_profile mp;
+	struct rte_mtr_error error;
+	uint32_t profile_id = res->profile_id;
+	uint8_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Private shaper profile params */
+	memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
+	mp.alg = 0;
+	mp.trtcm_rfc4115.cir = res->cir;
+	mp.trtcm_rfc4115.eir = res->eir;
+	mp.trtcm_rfc4115.cbs = res->cbs;
+	mp.trtcm_rfc4115.ebs = res->ebs;
+
+	ret = rte_mtr_meter_profile_add(port_id, profile_id, &mp, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm_rfc4115 = {
+	.f = cmd_add_port_meter_profile_trtcm_rfc4115_parsed,
+	.data = NULL,
+	.help_str = "Add port meter profile trtcm (rfc4115)",
+	.tokens = {
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_add,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_port,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_meter,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_profile,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_port_id,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_profile_id,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_trtcm_rfc4115,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_cir,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_eir,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_cbs,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_ebs,
+		NULL,
+	},
+};
+
+/* *** Delete Port Meter Profile *** */
+struct cmd_del_port_meter_profile_result {
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	uint8_t port_id;
+	uint32_t profile_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_meter_profile_del =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_profile_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_meter_profile_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			port, "port");
+cmdline_parse_token_string_t cmd_del_port_meter_profile_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			meter, "meter");
+cmdline_parse_token_string_t cmd_del_port_meter_profile_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			profile, "profile");
+cmdline_parse_token_num_t cmd_del_port_meter_profile_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			port_id, UINT8);
+cmdline_parse_token_num_t cmd_del_port_meter_profile_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			profile_id, UINT32);
+
+static void cmd_del_port_meter_profile_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_del_port_meter_profile_result *res = parsed_result;
+	struct rte_mtr_error error;
+	uint32_t profile_id = res->profile_id;
+	uint8_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Delete meter profile */
+	ret = rte_mtr_meter_profile_delete(port_id, profile_id, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_del_port_meter_profile = {
+	.f = cmd_del_port_meter_profile_parsed,
+	.data = NULL,
+	.help_str = "Delete port meter profile",
+	.tokens = {
+		(void *)&cmd_del_port_meter_profile_del,
+		(void *)&cmd_del_port_meter_profile_port,
+		(void *)&cmd_del_port_meter_profile_meter,
+		(void *)&cmd_del_port_meter_profile_profile,
+		(void *)&cmd_del_port_meter_profile_port_id,
+		(void *)&cmd_del_port_meter_profile_profile_id,
+		NULL,
+	},
+};
+
+/* *** Create Port Meter Object *** */
+struct cmd_set_port_meter_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	uint8_t port_id;
+	uint32_t mtr_id;
+	uint32_t profile_id;
+	cmdline_fixed_string_t g_action;
+	cmdline_fixed_string_t y_action;
+	cmdline_fixed_string_t r_action;
+	uint64_t statistics_mask;
+	uint32_t shared;
+};
+
+cmdline_parse_token_string_t cmd_set_port_meter_set =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_meter_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_meter_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_result, meter, "meter");
+cmdline_parse_token_num_t cmd_set_port_meter_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_port_meter_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_set_port_meter_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_result, profile_id, UINT32);
+cmdline_parse_token_string_t cmd_set_port_meter_g_action =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_port_meter_result,
+		g_action, "R#Y#G#D");
+cmdline_parse_token_string_t cmd_set_port_meter_y_action =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_port_meter_result,
+		y_action, "R#Y#G#D");
+cmdline_parse_token_string_t cmd_set_port_meter_r_action =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_port_meter_result,
+		r_action, "R#Y#G#D");
+cmdline_parse_token_num_t cmd_set_port_meter_statistics_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_port_meter_result,
+		statistics_mask, UINT64);
+cmdline_parse_token_num_t cmd_set_port_meter_shared =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_port_meter_result,
+		shared, UINT32);
+
+static void cmd_set_port_meter_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_port_meter_result *res = parsed_result;
+	struct rte_mtr_error error;
+	struct rte_mtr_params params;
+	uint32_t mtr_id = res->mtr_id;
+	uint32_t shared = res->shared;
+	uint8_t port_id = res->port_id;
+	
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Meter params */
+	memset(&params, 0, sizeof(struct rte_mtr_params));
+	params.meter_profile_id = res->profile_id;
+	params.use_prev_mtr_color = 1;
+	params.dscp_table = NULL;
+	params.meter_enable = 1;
+	params.action[RTE_MTR_GREEN] =
+		string_to_policer_action(res->g_action);
+	params.action[RTE_MTR_YELLOW] =
+		string_to_policer_action(res->y_action);
+	params.action[RTE_MTR_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);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_port_meter = {
+	.f = cmd_set_port_meter_parsed,
+	.data = NULL,
+	.help_str = "Set port meter",
+	.tokens = {
+		(void *)&cmd_set_port_meter_set,
+		(void *)&cmd_set_port_meter_port,
+		(void *)&cmd_set_port_meter_meter,
+		(void *)&cmd_set_port_meter_port_id,
+		(void *)&cmd_set_port_meter_mtr_id,
+		(void *)&cmd_set_port_meter_profile_id,
+		(void *)&cmd_set_port_meter_g_action,
+		(void *)&cmd_set_port_meter_y_action,
+		(void *)&cmd_set_port_meter_r_action,
+		(void *)&cmd_set_port_meter_statistics_mask,
+		(void *)&cmd_set_port_meter_shared,	
+		NULL,
+	},
+};
+
+/* *** Delete Port Meter Object *** */
+struct cmd_del_port_meter_result {
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	uint8_t port_id;
+	uint32_t mtr_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_meter_del =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_meter_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_result, port, "port");
+cmdline_parse_token_string_t cmd_del_port_meter_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_result, meter, "meter");
+cmdline_parse_token_num_t cmd_del_port_meter_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_del_port_meter_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_result, mtr_id, UINT32);
+
+static void cmd_del_port_meter_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_del_port_meter_result *res = parsed_result;
+	struct rte_mtr_error error;
+	uint32_t mtr_id = res->mtr_id;
+	uint8_t port_id = res->port_id;
+	
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Destroy Meter */
+	ret = rte_mtr_destroy(port_id, mtr_id, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_del_port_meter = {
+	.f = cmd_del_port_meter_parsed,
+	.data = NULL,
+	.help_str = "Delete port meter",
+	.tokens = {
+		(void *)&cmd_del_port_meter_del,
+		(void *)&cmd_del_port_meter_port,
+		(void *)&cmd_del_port_meter_meter,
+		(void *)&cmd_del_port_meter_port_id,
+		(void *)&cmd_del_port_meter_mtr_id,
+		NULL,
+	},
+};
+
+/* *** Set Port Meter Profile *** */
+struct cmd_set_port_meter_profile_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	uint8_t port_id;
+	uint32_t mtr_id;
+	uint32_t profile_id;
+};
+
+cmdline_parse_token_string_t cmd_set_port_meter_profile_set =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_meter_profile_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_meter_profile_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, meter, "meter");
+cmdline_parse_token_string_t cmd_set_port_meter_profile_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, profile, "profile");
+cmdline_parse_token_num_t cmd_set_port_meter_profile_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_port_meter_profile_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_set_port_meter_profile_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, profile_id, UINT32);
+
+static void cmd_set_port_meter_profile_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_port_meter_profile_result *res = parsed_result;
+	struct rte_mtr_error error;
+	uint32_t mtr_id = res->mtr_id;
+	uint32_t profile_id = res->profile_id;
+	uint8_t port_id = res->port_id;
+	
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Set meter profile */
+	ret = rte_mtr_meter_profile_update(port_id, mtr_id,
+		profile_id, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_port_meter_profile = {
+	.f = cmd_set_port_meter_profile_parsed,
+	.data = NULL,
+	.help_str = "Set port meter profile",
+	.tokens = {
+		(void *)&cmd_set_port_meter_profile_set,
+		(void *)&cmd_set_port_meter_profile_port,
+		(void *)&cmd_set_port_meter_profile_meter,
+		(void *)&cmd_set_port_meter_profile_profile,
+		(void *)&cmd_set_port_meter_profile_port_id,
+		(void *)&cmd_set_port_meter_profile_mtr_id,
+		(void *)&cmd_set_port_meter_profile_profile_id,
+		NULL,
+	},
+};
+
+/* *** 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;
+	uint8_t port_id;
+	uint32_t mtr_id;
+	cmdline_fixed_string_t color;
+	cmdline_fixed_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, UINT8);
+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, UINT32);
+cmdline_parse_token_string_t cmd_set_port_meter_policer_action_color =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_policer_action_result, color, "G#Y#R");
+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, "G#Y#R#D");
+
+static void cmd_set_port_meter_policer_action_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_port_meter_policer_action_result *res = parsed_result;
+	enum rte_mtr_color color;
+	enum rte_mtr_policer_action action[RTE_MTR_COLORS];
+	struct rte_mtr_error error;
+	uint32_t mtr_id = res->mtr_id;
+	uint8_t port_id = res->port_id;
+	char *c = res->color;
+	char *a = res->policer_action;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Color */
+	if (strcmp(c, "G") == 0)
+		color = RTE_MTR_GREEN;
+	else if (strcmp(c, "Y") == 0)
+		color = RTE_MTR_YELLOW;
+	else if (strcmp(c, "Y") == 0)
+		color = RTE_MTR_RED;
+	else
+		color = RTE_MTR_COLORS;
+
+	/* Action */
+	if (strcmp(a, "G") == 0)
+		action[color] = MTR_POLICER_ACTION_COLOR_GREEN;
+	else if (strcmp(a, "Y") == 0)
+		action[color] = MTR_POLICER_ACTION_COLOR_YELLOW;
+	else if (strcmp(a, "Y") == 0)
+		action[color] = MTR_POLICER_ACTION_COLOR_RED;
+	else
+		action[color] = MTR_POLICER_ACTION_DROP;
+
+	ret = rte_mtr_policer_actions_update(port_id, mtr_id,
+		1 << color, action, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+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",
+	.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_color,
+		(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;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t stats;
+	cmdline_fixed_string_t mask;
+	uint8_t port_id;
+	uint32_t mtr_id;
+	uint64_t stats_mask;
+};
+
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_set =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, meter, "meter");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_stats =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, stats, "stats");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_mask =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, mask, "mask");
+cmdline_parse_token_num_t cmd_set_port_meter_stats_mask_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_port_meter_stats_mask_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_set_port_meter_stats_mask_stats_mask =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, stats_mask, UINT64);
+
+static void cmd_set_port_meter_stats_mask_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_port_meter_stats_mask_result *res = parsed_result;
+	struct rte_mtr_error error;
+	uint64_t stats_mask = res->stats_mask;
+	uint32_t mtr_id = res->mtr_id;
+	uint8_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	ret = rte_mtr_stats_update(port_id, mtr_id, stats_mask, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_port_meter_stats_mask = {
+	.f = cmd_set_port_meter_stats_mask_parsed,
+	.data = NULL,
+	.help_str = "Set port meter stats mask",
+	.tokens = {
+		(void *)&cmd_set_port_meter_stats_mask_set,
+		(void *)&cmd_set_port_meter_stats_mask_port,
+		(void *)&cmd_set_port_meter_stats_mask_meter,
+		(void *)&cmd_set_port_meter_stats_mask_stats,
+		(void *)&cmd_set_port_meter_stats_mask_mask,
+		(void *)&cmd_set_port_meter_stats_mask_port_id,
+		(void *)&cmd_set_port_meter_stats_mask_mtr_id,
+		(void *)&cmd_set_port_meter_stats_mask_stats_mask,
+		NULL,
+	},
+};
+
+/* *** Show Port Meter Stats *** */
+struct cmd_show_port_meter_stats_result {
+	cmdline_fixed_string_t show;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t stats;
+	uint8_t port_id;
+	uint32_t mtr_id;
+	uint32_t clear;
+};
+
+cmdline_parse_token_string_t cmd_show_port_meter_stats_show =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, show, "show");
+cmdline_parse_token_string_t cmd_show_port_meter_stats_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, port, "port");
+cmdline_parse_token_string_t cmd_show_port_meter_stats_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, meter, "meter");
+cmdline_parse_token_string_t cmd_show_port_meter_stats_stats =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, stats, "stats");
+cmdline_parse_token_num_t cmd_show_port_meter_stats_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_show_port_meter_stats_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_show_port_meter_stats_clear =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, clear, UINT32);
+
+static void cmd_show_port_meter_stats_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_show_port_meter_stats_result *res = parsed_result;
+	struct rte_mtr_stats stats;
+	uint64_t stats_mask = 0;
+	struct rte_mtr_error error;
+	uint32_t mtr_id = res->mtr_id;
+	uint32_t clear = res->clear;
+	uint8_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	memset(&stats, 0, sizeof(struct rte_mtr_stats));
+	ret = rte_mtr_stats_read(port_id, mtr_id, &stats,
+		&stats_mask, clear, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+
+	/* Display stats */
+	if (stats_mask & RTE_MTR_STATS_N_PKTS_GREEN)
+		printf("\tPkts G: %" PRIu64 "\n",
+			stats.n_pkts[RTE_MTR_GREEN]);
+	if (stats_mask & RTE_MTR_STATS_N_BYTES_GREEN)
+		printf("\tBytes G: %" PRIu64 "\n",
+			stats.n_bytes[RTE_MTR_GREEN]);
+	if (stats_mask & RTE_MTR_STATS_N_PKTS_YELLOW)
+		printf("\tPkts Y: %" PRIu64 "\n",
+			stats.n_pkts[RTE_MTR_YELLOW]);
+	if (stats_mask & RTE_MTR_STATS_N_BYTES_YELLOW)
+		printf("\tBytes Y: %" PRIu64 "\n",
+			stats.n_bytes[RTE_MTR_YELLOW]);
+	if (stats_mask & RTE_MTR_STATS_N_PKTS_RED)
+		printf("\tPkts R: %" PRIu64 "\n",
+			stats.n_pkts[RTE_MTR_RED]);
+	if (stats_mask & RTE_MTR_STATS_N_BYTES_RED)
+		printf("\tBytes Y: %" PRIu64 "\n",
+			stats.n_bytes[RTE_MTR_RED]);
+	if (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED)
+		printf("\tPkts DROPPED: %" PRIu64 "\n",
+			stats.n_pkts_dropped);
+	if (stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED)
+		printf("\tBytes DROPPED: %" PRIu64 "\n",
+			stats.n_bytes_dropped);
+}
+
+cmdline_parse_inst_t cmd_show_port_meter_stats = {
+	.f = cmd_show_port_meter_stats_parsed,
+	.data = NULL,
+	.help_str = "Show port meter stats",
+	.tokens = {
+		(void *)&cmd_show_port_meter_stats_show,
+		(void *)&cmd_show_port_meter_stats_port,
+		(void *)&cmd_show_port_meter_stats_meter,
+		(void *)&cmd_show_port_meter_stats_stats,
+		(void *)&cmd_show_port_meter_stats_port_id,
+		(void *)&cmd_show_port_meter_stats_mtr_id,
+		(void *)&cmd_show_port_meter_stats_clear,
+		NULL,
+	},
+};
diff --git a/app/test-pmd/cmdline_mtr.h b/app/test-pmd/cmdline_mtr.h
new file mode 100644
index 0000000..5d599ef
--- /dev/null
+++ b/app/test-pmd/cmdline_mtr.h
@@ -0,0 +1,49 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CMDLINE_MTR_H_
+#define _CMDLINE_MTR_H_
+
+/* Traffic Metering and Policing */
+extern cmdline_parse_inst_t cmd_add_port_meter_profile_srtcm;
+extern cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm;
+extern cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm_rfc4115;
+extern cmdline_parse_inst_t cmd_del_port_meter_profile;
+extern cmdline_parse_inst_t cmd_set_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_policer_action;
+extern cmdline_parse_inst_t cmd_set_port_meter_stats_mask;
+extern cmdline_parse_inst_t cmd_show_port_meter_stats;
+
+#endif /* _CMDLINE_MTR_H_ */
-- 
2.7.4

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

* Re: [PATCH V2 1/5] ethdev: add new flow action for metering and policing
  2017-10-06 13:57           ` Adrien Mazarguil
@ 2017-10-06 14:50             ` Dumitrescu, Cristian
  0 siblings, 0 replies; 64+ messages in thread
From: Dumitrescu, Cristian @ 2017-10-06 14:50 UTC (permalink / raw)
  To: Adrien Mazarguil
  Cc: dev, thomas, Wu, Jingjing, hemant.agrawal, jerin.jacob, Singh, Jasvinder



> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Friday, October 6, 2017 2:58 PM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Cc: dev@dpdk.org; thomas@monjalon.net; Wu, Jingjing
> <jingjing.wu@intel.com>; hemant.agrawal@nxp.com;
> jerin.jacob@caviumnetworks.com; Singh, Jasvinder
> <jasvinder.singh@intel.com>
> Subject: Re: [PATCH V2 1/5] ethdev: add new flow action for metering and
> policing
> 
> On Thu, Oct 05, 2017 at 02:09:30PM +0100, Cristian Dumitrescu wrote:
> > Metering and policing action typically sits on top of flow classification,
> > which is why MTR objects are enabled through a newly introduced flow
> > action.
> >
> > The configuration of MTR objects is done in their own namespace (rte_mtr)
> > within the librte_ether library. The MTR object is hooked into ethdev RX
> > processing path using the "meter" flow action.
> >
> > Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> 
> Looks good, one minor comment about the METER action semantics before
> acking
> this patch, see below.
> 
> > ---
> >  doc/guides/prog_guide/rte_flow.rst | 24 ++++++++++++++++++++++++
> >  lib/librte_ether/rte_flow.h        | 22 ++++++++++++++++++++++
> >  2 files changed, 46 insertions(+)
> >
> > diff --git a/doc/guides/prog_guide/rte_flow.rst
> b/doc/guides/prog_guide/rte_flow.rst
> > index 662a912..6b9cdc2 100644
> > --- a/doc/guides/prog_guide/rte_flow.rst
> > +++ b/doc/guides/prog_guide/rte_flow.rst
> > @@ -1354,6 +1354,30 @@ rule or if packets are not addressed to a VF in
> the first place.
> >     | ``vf``       | VF ID to redirect packets to   |
> >     +--------------+--------------------------------+
> >
> > +Action: ``METER``
> > +^^^^^^^^^^^^^^^^^
> > +
> > +Applies a stage of metering and policing.
> > +
> > +The metering and policing (MTR) object has to be first created using the
> > +rte_mtr_create() API function. The ID of the MTR object is specified as
> > +action parameter. One or several meter actions can be added to the same
> > +flow. More than one flow can use the same MTR object through the
> meter
> > +action. The MTR object can be further updated or queried using the
> > +rte_mtr* API.
> 
> rte_flow is currently documented [1] as ignoring several actions of the same
> kind in a given rule, in which case only the last one is taken into
> account. It's a deliberate design choice to simplify implementation, which
> I now think wasn't such a good idea after all.
> 
> I'm therefore not opposed to remove this restriction globally, however in
> that case rte_flow documentation must be modified and PMDs reworked to
> implement the new behavior (failing by default when encountering multiple
> actions of the same time instead of ignoring them). It's probably a little
> late to do this now though.
> 
> So my suggestion for the time being is to not describe what happens when
> several MTR actions are provided. We'll keep this for the next overhaul of
> rte_flow (some other changes are already planned).


Hi Adrian,

Done in V3 just sent.

Thanks,
Cristian

> 
> [1] http://dpdk.org/doc/guides/prog_guide/rte_flow.html#actions
> 
> --
> Adrien Mazarguil
> 6WIND

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

* Re: [PATCH V3 1/5] ethdev: add new flow action for metering and policing
  2017-10-06 14:45             ` [PATCH V3 1/5] ethdev: add new flow action " Cristian Dumitrescu
@ 2017-10-06 14:55               ` Adrien Mazarguil
  2017-10-13 12:22               ` [PATCH V4 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
  1 sibling, 0 replies; 64+ messages in thread
From: Adrien Mazarguil @ 2017-10-06 14:55 UTC (permalink / raw)
  To: Cristian Dumitrescu
  Cc: dev, thomas, jingjing.wu, hemant.agrawal, jerin.jacob, jasvinder.singh

On Fri, Oct 06, 2017 at 03:45:32PM +0100, Cristian Dumitrescu wrote:
> Metering and policing action typically sits on top of flow classification,
> which is why MTR objects are enabled through a newly introduced flow
> action.
> 
> The configuration of MTR objects is done in their own namespace (rte_mtr)
> within the librte_ether library. The MTR object is hooked into ethdev RX
> processing path using the "meter" flow action.
> 
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> ---
> Changes in v3:
> - Implemented input from Adrien:
>      - Removed doc mention on multiple MTR objects for same flow.

Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>

-- 
Adrien Mazarguil
6WIND

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

* Re: [PATCH V3 3/5] ethdev: add new api for traffic metering and policing
  2017-10-06 14:45             ` [PATCH V3 3/5] ethdev: add new api for traffic metering and policing Cristian Dumitrescu
@ 2017-10-12 10:48               ` Hemant Agrawal
  2017-10-12 10:54                 ` Hemant Agrawal
  2017-10-13 12:29                 ` Dumitrescu, Cristian
  0 siblings, 2 replies; 64+ messages in thread
From: Hemant Agrawal @ 2017-10-12 10:48 UTC (permalink / raw)
  To: Cristian Dumitrescu, dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, jerin.jacob, jasvinder.singh

On 10/6/2017 8:15 PM, Cristian Dumitrescu wrote:

Overall the patch looks ok. Few small comments.

> diff --git a/lib/librte_ether/rte_mtr.h b/lib/librte_ether/rte_mtr.h
> new file mode 100644
> index 0000000..f0f897f
> --- /dev/null
> +++ b/lib/librte_ether/rte_mtr.h
> @@ -0,0 +1,723 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2017 Intel Corporation.
> + *   Copyright(c) 2017 NXP.

can you make it "Copyright 2017 NXP"
> + *   Copyright(c) 2017 Cavium.
> + *   All rights reserved.
> + *

<snip>...

> +/**
> + * Statistics counter type
> + */
> +enum rte_mtr_stats_type {
> +	/** Number of packets passed as green by the policer. */
> +	RTE_MTR_STATS_N_PKTS_GREEN = 1 << 0,
> +
> +	/** Number of bytes passed as green by the policer. */
> +	RTE_MTR_STATS_N_BYTES_GREEN = 1 << 1,
> +
> +	/** Number of packets passed as yellow by the policer. */
> +	RTE_MTR_STATS_N_PKTS_YELLOW = 1 << 2,
> +
> +	/** Number of bytes passed as yellow by the policer. */
> +	RTE_MTR_STATS_N_BYTES_YELLOW = 1 << 3,
> +
> +	/** Number of packets passed as red by the policer. */
> +	RTE_MTR_STATS_N_PKTS_RED = 1 << 4,
> +
> +	/** Number of bytes passed as red by the policer. */
> +	RTE_MTR_STATS_N_BYTES_RED = 1 << 5,
> +
> +	/** Number of packets dropped by the policer. */
> +	RTE_MTR_STATS_N_PKTS_DROPPED = 1 << 6,
> +
> +	/** Number of bytes dropped by the policer. */
> +	RTE_MTR_STATS_N_BYTES_DROPPED = 1 << 7,

Trivial one.
do you want to group the pkts and bytes in separate group respectively?

> +};
> +
> +/**
> + * Statistics counters
> + */
> +struct rte_mtr_stats {
> +	/** Number of packets passed by the policer (per color). */
> +	uint64_t n_pkts[RTE_MTR_COLORS];
> +
> +	/** Number of bytes passed by the policer (per color). */
> +	uint64_t n_bytes[RTE_MTR_COLORS];
> +
> +	/** Number of packets dropped by the policer. */
> +	uint64_t n_pkts_dropped;
> +
> +	/** Number of bytes passed by the policer. */
> +	uint64_t n_bytes_dropped;
> +};
> +
> +/**
> + * Traffic metering algorithms
> + */
> +enum rte_mtr_algorithm {
> +	/** Single Rate Three Color Marker (srTCM) - IETF RFC 2697. */
> +	RTE_MTR_SRTCM_RFC2697,
> +
> +	/** Two Rate Three Color Marker (trTCM) - IETF RFC 2698. */
> +	RTE_MTR_TRTCM_RFC2698,
> +
> +	/** Two Rate Three Color Marker (trTCM) - IETF RFC 4115. */
> +	RTE_MTR_TRTCM_RFC4115,

I will still prefer if you still add "PASS_THROUGH" as explicit algo.

> +};
> +
> +/**
> + * Meter profile
> + */

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

* Re: [PATCH V3 3/5] ethdev: add new api for traffic metering and policing
  2017-10-12 10:48               ` Hemant Agrawal
@ 2017-10-12 10:54                 ` Hemant Agrawal
  2017-10-13 12:29                 ` Dumitrescu, Cristian
  1 sibling, 0 replies; 64+ messages in thread
From: Hemant Agrawal @ 2017-10-12 10:54 UTC (permalink / raw)
  To: Cristian Dumitrescu, dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, jerin.jacob, jasvinder.singh

On 10/12/2017 4:18 PM, Hemant Agrawal wrote:
> On 10/6/2017 8:15 PM, Cristian Dumitrescu wrote:
>
> Overall the patch looks ok. Few small comments.
>
>> diff --git a/lib/librte_ether/rte_mtr.h b/lib/librte_ether/rte_mtr.h
>> new file mode 100644
>> index 0000000..f0f897f
>> --- /dev/null
>> +++ b/lib/librte_ether/rte_mtr.h
>> @@ -0,0 +1,723 @@
>> +/*-
>> + *   BSD LICENSE
>> + *
>> + *   Copyright(c) 2017 Intel Corporation.
>> + *   Copyright(c) 2017 NXP.
>
> can you make it "Copyright 2017 NXP"
>> + *   Copyright(c) 2017 Cavium.
>> + *   All rights reserved.
>> + *
>
> <snip>...
>
>> +/**
>> + * Statistics counter type
>> + */
>> +enum rte_mtr_stats_type {
>> +    /** Number of packets passed as green by the policer. */
>> +    RTE_MTR_STATS_N_PKTS_GREEN = 1 << 0,
>> +
>> +    /** Number of bytes passed as green by the policer. */
>> +    RTE_MTR_STATS_N_BYTES_GREEN = 1 << 1,
>> +
>> +    /** Number of packets passed as yellow by the policer. */
>> +    RTE_MTR_STATS_N_PKTS_YELLOW = 1 << 2,
>> +
>> +    /** Number of bytes passed as yellow by the policer. */
>> +    RTE_MTR_STATS_N_BYTES_YELLOW = 1 << 3,
>> +
>> +    /** Number of packets passed as red by the policer. */
>> +    RTE_MTR_STATS_N_PKTS_RED = 1 << 4,
>> +
>> +    /** Number of bytes passed as red by the policer. */
>> +    RTE_MTR_STATS_N_BYTES_RED = 1 << 5,
>> +
>> +    /** Number of packets dropped by the policer. */
>> +    RTE_MTR_STATS_N_PKTS_DROPPED = 1 << 6,
>> +
>> +    /** Number of bytes dropped by the policer. */
>> +    RTE_MTR_STATS_N_BYTES_DROPPED = 1 << 7,
>
> Trivial one.
> do you want to group the pkts and bytes in separate group respectively?
>
>> +};
>> +
>> +/**
>> + * Statistics counters
>> + */
>> +struct rte_mtr_stats {
>> +    /** Number of packets passed by the policer (per color). */
>> +    uint64_t n_pkts[RTE_MTR_COLORS];
>> +
>> +    /** Number of bytes passed by the policer (per color). */
>> +    uint64_t n_bytes[RTE_MTR_COLORS];
>> +
>> +    /** Number of packets dropped by the policer. */
>> +    uint64_t n_pkts_dropped;
>> +
>> +    /** Number of bytes passed by the policer. */
>> +    uint64_t n_bytes_dropped;
>> +};
>> +
>> +/**
>> + * Traffic metering algorithms
>> + */
>> +enum rte_mtr_algorithm {
>> +    /** Single Rate Three Color Marker (srTCM) - IETF RFC 2697. */
>> +    RTE_MTR_SRTCM_RFC2697,
>> +
>> +    /** Two Rate Three Color Marker (trTCM) - IETF RFC 2698. */
>> +    RTE_MTR_TRTCM_RFC2698,
>> +
>> +    /** Two Rate Three Color Marker (trTCM) - IETF RFC 4115. */
>> +    RTE_MTR_TRTCM_RFC4115,
>
> I will still prefer if you still add "PASS_THROUGH" as explicit algo.
>
>> +};
>> +
>> +/**
>> + * Meter profile
>> + */
>
>
>
Reviewed-by:  Hemant Agrawal <hemant.agrawal@nxp.com>

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

* Re: [PATCH V3 2/5] ethdev: add new eth_dev_ops function for mtr ops get
  2017-10-06 14:45             ` [PATCH V3 2/5] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
@ 2017-10-12 10:58               ` Hemant Agrawal
  0 siblings, 0 replies; 64+ messages in thread
From: Hemant Agrawal @ 2017-10-12 10:58 UTC (permalink / raw)
  To: Cristian Dumitrescu, dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, jerin.jacob, jasvinder.singh

On 10/6/2017 8:15 PM, Cristian Dumitrescu wrote:
> Following similar approach as rte_flow and rte_tm for modularity reasons,
> the ops for the new rte_mtr API are retrieved through a new eth_dev_ops
> function.
>
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> ---
> Changes in v3:
> - None
>
> Changes in v2:
> -None
>
> Changes in v1 (from RFC [1]):
> - Removed ethdev API function to get the MTR ops, as it is not needed
>   (input from Thomas)
>
> [1] RFC: http://www.dpdk.org/ml/archives/dev/2017-May/066888.html
>
>  lib/librte_ether/rte_ethdev.h | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> index 99cdd54..a5802b0 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -1424,6 +1424,9 @@ typedef int (*eth_filter_ctrl_t)(struct rte_eth_dev *dev,
>  typedef int (*eth_tm_ops_get_t)(struct rte_eth_dev *dev, void *ops);
>  /**< @internal Get Traffic Management (TM) operations on an Ethernet device */
>
> +typedef int (*eth_mtr_ops_get_t)(struct rte_eth_dev *dev, void *ops);
> +/**< @internal Get Trafffic Metering and Policing (MTR) operations */
> +
>  typedef int (*eth_get_dcb_info)(struct rte_eth_dev *dev,
>  				 struct rte_eth_dcb_info *dcb_info);
>  /**< @internal Get dcb information on an Ethernet device */
> @@ -1548,6 +1551,9 @@ struct eth_dev_ops {
>
>  	eth_tm_ops_get_t tm_ops_get;
>  	/**< Get Traffic Management (TM) operations. */
> +
> +	eth_mtr_ops_get_t mtr_ops_get;
> +	/**< Get Traffic Metering and Policing (MTR) operations. */
>  };
>
>  /**
>
Reviewed-by:  Hemant Agrawal <hemant.agrawal@nxp.com>

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

* Re: [PATCH V3 4/5] doc: ethdev traffic metering and policing api
  2017-10-06 14:45             ` [PATCH V3 4/5] doc: ethdev traffic metering and policing api Cristian Dumitrescu
@ 2017-10-12 14:59               ` Mcnamara, John
  2017-10-13 12:26                 ` Dumitrescu, Cristian
  2017-10-12 15:01               ` Mcnamara, John
  1 sibling, 1 reply; 64+ messages in thread
From: Mcnamara, John @ 2017-10-12 14:59 UTC (permalink / raw)
  To: Dumitrescu, Cristian, dev
  Cc: thomas, adrien.mazarguil, Wu, Jingjing, hemant.agrawal,
	jerin.jacob, Singh, Jasvinder



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Cristian Dumitrescu
> Sent: Friday, October 6, 2017 3:46 PM
> To: dev@dpdk.org
> Cc: thomas@monjalon.net; adrien.mazarguil@6wind.com; Wu, Jingjing
> <jingjing.wu@intel.com>; hemant.agrawal@nxp.com;
> jerin.jacob@caviumnetworks.com; Singh, Jasvinder
> <jasvinder.singh@intel.com>
> Subject: [dpdk-dev] [PATCH V3 4/5] doc: ethdev traffic metering and
> policing api
> 
> Add new section in the Programmer Guide for the ethdev traffic metering
> and policing (MTR) API.
> 
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>


Thanks for the well written doc. Some comments below.


> ---
> +Traffic Metering and Policing (MTR) API
> +=======================================

Leave out the acronym from the title. It is explained in the overview.

> +The processing done for each input packet hitting an MTR object is:
> +* Traffic metering: The packet is assigned a color (the meter output
> +  color) based on the previous traffic history reflected in the
> +  current state of the MTR object, according to the specific traffic
> +  metering algorithm. The traffic metering algorithm can typically work
> +  in color aware mode, in which case the input packet already has an
> +  initial color (the input color), or in 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

This section throws several doc build errors. Bullet lists need to have
a blank line before them and the second level indentation isn't correct here.

It should be something like this:


The processing done for each input packet hitting an MTR object is:

* Traffic metering: The packet is assigned a color (the meter output color)
  based on the previous traffic history reflected in the current state of the
  MTR object, according to the specific traffic metering algorithm. The
  traffic metering algorithm can typically work in color aware mode, in which
  case the input packet already has an initial color (the input color), or in
  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``).

* Statistics: The set of counters maintained for each MTR object is
  configurable and subject to the implementation support. This set includes
  the number of packets and bytes dropped or passed for each output color.

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

* Re: [PATCH V3 4/5] doc: ethdev traffic metering and policing api
  2017-10-06 14:45             ` [PATCH V3 4/5] doc: ethdev traffic metering and policing api Cristian Dumitrescu
  2017-10-12 14:59               ` Mcnamara, John
@ 2017-10-12 15:01               ` Mcnamara, John
  1 sibling, 0 replies; 64+ messages in thread
From: Mcnamara, John @ 2017-10-12 15:01 UTC (permalink / raw)
  To: Dumitrescu, Cristian, dev
  Cc: thomas, adrien.mazarguil, Wu, Jingjing, hemant.agrawal,
	jerin.jacob, Singh, Jasvinder

Reviewed-by: John McNamara <john.mcnamara@intel.com>

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

* Re: [PATCH V3 5/5] app/testpmd: cli for traffic metering and policing
  2017-10-06 14:45             ` [PATCH V3 5/5] app/testpmd: cli for traffic metering and policing Cristian Dumitrescu
@ 2017-10-13  6:32               ` Wu, Jingjing
  2017-10-13 12:30                 ` Dumitrescu, Cristian
  0 siblings, 1 reply; 64+ messages in thread
From: Wu, Jingjing @ 2017-10-13  6:32 UTC (permalink / raw)
  To: Dumitrescu, Cristian, dev
  Cc: thomas, adrien.mazarguil, hemant.agrawal, jerin.jacob, Singh, Jasvinder



> -----Original Message-----
> From: Dumitrescu, Cristian
> Sent: Friday, October 6, 2017 10:46 PM
> To: dev@dpdk.org
> Cc: thomas@monjalon.net; adrien.mazarguil@6wind.com; Wu, Jingjing
> <jingjing.wu@intel.com>; hemant.agrawal@nxp.com;
> jerin.jacob@caviumnetworks.com; Singh, Jasvinder <jasvinder.singh@intel.com>
> Subject: [PATCH V3 5/5] app/testpmd: cli for traffic metering and policing
> 
> Add CLI commands to exercise the ethdev Traffic Metering and Policing
> (MTR) API.
> 
> Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
> Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
> ---
> Changes in v3:
> - Added newline at the end of cmdline_mtr.h
> 
>  app/test-pmd/Makefile       |    1 +
>  app/test-pmd/cmdline.c      |   10 +
>  app/test-pmd/cmdline_flow.c |   24 +
>  app/test-pmd/cmdline_mtr.c  | 1013
> +++++++++++++++++++++++++++++++++++++++++++
>  app/test-pmd/cmdline_mtr.h  |   49 +++
>  5 files changed, 1097 insertions(+)
>  create mode 100644 app/test-pmd/cmdline_mtr.c  create mode 100644
> app/test-pmd/cmdline_mtr.h
> 
> diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile index
> c36be19..8fb6491 100644
> --- a/app/test-pmd/Makefile
> +++ b/app/test-pmd/Makefile
> @@ -48,6 +48,7 @@ SRCS-y := testpmd.c
>  SRCS-y += parameters.c
>  SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline.c
>  SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_flow.c
> +SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_mtr.c
>  SRCS-y += config.c
>  SRCS-y += iofwd.c
>  SRCS-y += macfwd.c
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> ccdf239..8338b5c 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -99,6 +99,7 @@
>  #include <rte_pmd_bnxt.h>
>  #endif
>  #include "testpmd.h"
> +#include "cmdline_mtr.h"
> 
>  static struct cmdline *testpmd_cl;
> 
> @@ -14334,6 +14335,15 @@ cmdline_parse_ctx_t main_ctx[] = {
>  	(cmdline_parse_inst_t *)&cmd_set_hash_input_set,
>  	(cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
>  	(cmdline_parse_inst_t *)&cmd_flow,
> +	(cmdline_parse_inst_t *)&cmd_add_port_meter_profile_srtcm,
> +	(cmdline_parse_inst_t *)&cmd_add_port_meter_profile_trtcm,
> +	(cmdline_parse_inst_t *)&cmd_del_port_meter_profile,
> +	(cmdline_parse_inst_t *)&cmd_set_port_meter,
> +	(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_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,
>  	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
>  	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,

You need to add the command description in cmd_help_long_parsed.
And doc for new commands.

[......]

> +cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_port_id =
> +	TOKEN_NUM_INITIALIZER(
> +		struct cmd_add_port_meter_profile_srtcm_result,
> +			port_id, UINT8);

Would you update the UINT8 to UINT16?  The same to all the port_id.


Thanks
Jingjing

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

* [PATCH V4 0/5] rte_mtr: generic ethdev api for metering and policing
  2017-10-06 14:45             ` [PATCH V3 1/5] ethdev: add new flow action " Cristian Dumitrescu
  2017-10-06 14:55               ` Adrien Mazarguil
@ 2017-10-13 12:22               ` Cristian Dumitrescu
  2017-10-13 12:22                 ` [PATCH V4 1/5] ethdev: add new flow action " Cristian Dumitrescu
                                   ` (5 more replies)
  1 sibling, 6 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-13 12:22 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, john.mcnamara,
	hemant.agrawal, jerin.jacob, jasvinder.singh

Metering and Policing (MTR), which is yet another standard RX offload for
Ethernet devices.

Similar to rte_flow and rte_tm APIs, the configuration of MTR objects is
done in their own namespace (rte_mtr) within the librte_ether library.
Metering and policing action typically sits on top of flow classification,
which is why MTR objects are enabled through a newly introduced flow
action, which is the only impact to flow API.

Q1: Why introduce ethdev-based traffic metering ad policing API?
A1: Traffic metering and policing is a standard RX offload for Ethernet
devices present in NICs, SoCs and NPUs across the industry.

Q2: What's the connection between the new rte_mtr API and the existing
librte_meter library?
A2: The existing librte_meter library provides a SW implementation for a
subset of the features exposed by this API. The rte_mtr API is agnostic to
whether the implementation is HW, SW or mixed HW-SW.

Q3: What's the connection between the new rte_mtr API and the existing
flow API?
A3: The MTR object is hooked into ethdev RX processing path using a newly
introduced flow action, which is the only impact to the flow API.
The configuration of MTR objects is done in separate namespace (rte_mtr)
outside of flow API.

Q4: Can the new flow API meter action drop packets? Is this a terminating
action or not?
A4: Although packets can be dropped by the newly introduced flow API meter
action, this action is non-terminating, i.e. the action list typically
contains at least one more action, which is a terminating action.
Depending on the policer actions configured for the MTR object, some
packets might be dropped while some packets passed to the next flow action
with their color set in the packet mbuf. For example, a typical policer
configuration is to drop the red packets while passing the green packets,
therefore a subsequent flow action needs to be configured to determine the
final destination of green packets.

Q5: Which are the main operations exposed for the MTR object?
A5: Traffic metering, policing and statistics update. Traffic metering
determines the color for the current packet (green, yellow, red) based on
the previous history for this flow as maintained by the MTR object.
The policer can do nothing, recolor or drop the packet. Stats are
maintained for MTR object, as configured.

Q6: Where is the output color stored for the current packet.
A6: struct rte_mbuf::sched::color.

Q7: Which are the supported metering algorithms?
A7: srTCM (RFC 2697), trTCM (RFC 2698 and RFC 4115).

Q8: Which are the supported policer actions?
A8: Recolor the packet (keep or change the color determined by metering)
or drop the packet.

Cristian Dumitrescu (5):
  ethdev: add new flow action for metering and policing
  ethdev: add new eth_dev_ops function for mtr ops get
  ethdev: add new api for traffic metering and policing
  doc: ethdev traffic metering and policing api
  app/testpmd: cli for traffic metering and policing

 MAINTAINERS                                        |    4 +
 app/test-pmd/Makefile                              |    1 +
 app/test-pmd/cmdline.c                             |   39 +
 app/test-pmd/cmdline_flow.c                        |   24 +
 app/test-pmd/cmdline_mtr.c                         | 1020 ++++++++++++++++++++
 app/test-pmd/cmdline_mtr.h                         |   49 +
 doc/api/doxy-api-index.md                          |    1 +
 doc/guides/prog_guide/index.rst                    |    1 +
 doc/guides/prog_guide/rte_flow.rst                 |   23 +
 .../prog_guide/traffic_metering_and_policing.rst   |  102 ++
 lib/librte_ether/Makefile                          |    3 +
 lib/librte_ether/rte_ethdev.h                      |    7 +
 lib/librte_ether/rte_ethdev_version.map            |   18 +
 lib/librte_ether/rte_flow.h                        |   22 +
 lib/librte_ether/rte_mtr.c                         |  229 +++++
 lib/librte_ether/rte_mtr.h                         |  730 ++++++++++++++
 lib/librte_ether/rte_mtr_driver.h                  |  221 +++++
 17 files changed, 2494 insertions(+)
 create mode 100644 app/test-pmd/cmdline_mtr.c
 create mode 100644 app/test-pmd/cmdline_mtr.h
 create mode 100644 doc/guides/prog_guide/traffic_metering_and_policing.rst
 create mode 100644 lib/librte_ether/rte_mtr.c
 create mode 100644 lib/librte_ether/rte_mtr.h
 create mode 100644 lib/librte_ether/rte_mtr_driver.h

-- 
2.7.4

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

* [PATCH V4 1/5] ethdev: add new flow action for metering and policing
  2017-10-13 12:22               ` [PATCH V4 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
@ 2017-10-13 12:22                 ` Cristian Dumitrescu
  2017-10-18  2:55                   ` Jerin Jacob
  2017-10-13 12:22                 ` [PATCH V4 2/5] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
                                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-13 12:22 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, john.mcnamara,
	hemant.agrawal, jerin.jacob, jasvinder.singh

Metering and policing action typically sits on top of flow classification,
which is why MTR objects are enabled through a newly introduced flow
action.

The configuration of MTR objects is done in their own namespace (rte_mtr)
within the librte_ether library. The MTR object is hooked into ethdev RX
processing path using the "meter" flow action.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
Changes in v4:
- None

Changes in v3:
- Implemented input from Adrien:
     - Removed doc mention on multiple MTR objects for same flow.

 doc/guides/prog_guide/rte_flow.rst | 23 +++++++++++++++++++++++
 lib/librte_ether/rte_flow.h        | 22 ++++++++++++++++++++++
 2 files changed, 45 insertions(+)

diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 3113881..5289350 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1371,6 +1371,29 @@ rule or if packets are not addressed to a VF in the first place.
    | ``vf``       | VF ID to redirect packets to   |
    +--------------+--------------------------------+
 
+Action: ``METER``
+^^^^^^^^^^^^^^^^^
+
+Applies a stage of metering and policing.
+
+The metering and policing (MTR) object has to be first created using the
+rte_mtr_create() API function. The ID of the MTR object is specified as
+action parameter. More than one flow can use the same MTR object through
+the meter action. The MTR object can be further updated or queried using
+the rte_mtr* API.
+
+- Non-terminating by default.
+
+.. _table_rte_flow_action_meter:
+
+.. table:: METER
+
+   +--------------+---------------+
+   | Field        | Value         |
+   +==============+===============+
+   | ``mtr_id``   | MTR object ID |
+   +--------------+---------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index a0ffb71..062e3ac 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -967,6 +967,14 @@ enum rte_flow_action_type {
 	 * See struct rte_flow_action_vf.
 	 */
 	RTE_FLOW_ACTION_TYPE_VF,
+
+	/**
+	 * Traffic metering and policing (MTR).
+	 *
+	 * See struct rte_flow_action_meter.
+	 * See file rte_mtr.h for MTR object configuration.
+	 */
+	RTE_FLOW_ACTION_TYPE_METER,
 };
 
 /**
@@ -1060,6 +1068,20 @@ struct rte_flow_action_vf {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_METER
+ *
+ * Traffic metering and policing (MTR).
+ *
+ * Packets matched by items of this type can be either dropped or passed to the
+ * next item with their color set by the MTR object.
+ *
+ * Non-terminating by default.
+ */
+struct rte_flow_action_meter {
+	uint32_t mtr_id; /**< MTR object ID created with rte_mtr_create(). */
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.7.4

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

* [PATCH V4 2/5] ethdev: add new eth_dev_ops function for mtr ops get
  2017-10-13 12:22               ` [PATCH V4 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
  2017-10-13 12:22                 ` [PATCH V4 1/5] ethdev: add new flow action " Cristian Dumitrescu
@ 2017-10-13 12:22                 ` Cristian Dumitrescu
  2017-10-17 12:40                   ` Hemant Agrawal
  2017-10-13 12:22                 ` [PATCH V4 3/5] ethdev: add new api for traffic metering and policing Cristian Dumitrescu
                                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-13 12:22 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, john.mcnamara,
	hemant.agrawal, jerin.jacob, jasvinder.singh

Following similar approach as rte_flow and rte_tm for modularity reasons,
the ops for the new rte_mtr API are retrieved through a new eth_dev_ops
function.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
Changes in v4:
- None

Changes in v3:
- None

Changes in v2:
-None

Changes in v1 (from RFC [1]):
- Removed ethdev API function to get the MTR ops, as it is not needed
  (input from Thomas)

[1] RFC: http://www.dpdk.org/ml/archives/dev/2017-May/066888.html

 lib/librte_ether/rte_ethdev.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index aaf02b3..b773589 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1499,6 +1499,9 @@ typedef int (*eth_filter_ctrl_t)(struct rte_eth_dev *dev,
 typedef int (*eth_tm_ops_get_t)(struct rte_eth_dev *dev, void *ops);
 /**< @internal Get Traffic Management (TM) operations on an Ethernet device */
 
+typedef int (*eth_mtr_ops_get_t)(struct rte_eth_dev *dev, void *ops);
+/**< @internal Get Trafffic Metering and Policing (MTR) operations */
+
 typedef int (*eth_get_dcb_info)(struct rte_eth_dev *dev,
 				 struct rte_eth_dcb_info *dcb_info);
 /**< @internal Get dcb information on an Ethernet device */
@@ -1627,6 +1630,10 @@ struct eth_dev_ops {
 
 	eth_tm_ops_get_t tm_ops_get;
 	/**< Get Traffic Management (TM) operations. */
+
+	eth_mtr_ops_get_t mtr_ops_get;
+	/**< Get Traffic Metering and Policing (MTR) operations. */
+
 	eth_pool_ops_supported_t pool_ops_supported;
 	/**< Test if a port supports specific mempool ops */
 };
-- 
2.7.4

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

* [PATCH V4 3/5] ethdev: add new api for traffic metering and policing
  2017-10-13 12:22               ` [PATCH V4 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
  2017-10-13 12:22                 ` [PATCH V4 1/5] ethdev: add new flow action " Cristian Dumitrescu
  2017-10-13 12:22                 ` [PATCH V4 2/5] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
@ 2017-10-13 12:22                 ` Cristian Dumitrescu
  2017-10-17 12:39                   ` Hemant Agrawal
  2017-10-18  2:58                   ` Jerin Jacob
  2017-10-13 12:22                 ` [PATCH V4 4/5] doc: ethdev traffic metering and policing api Cristian Dumitrescu
                                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-13 12:22 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, john.mcnamara,
	hemant.agrawal, jerin.jacob, jasvinder.singh

This patch introduces new ethdev generic API for Traffic Metering and
Policing (MTR), which is yet another standard RX offload for Ethernet
devices.

Similar to rte_flow and rte_tm APIs, the configuration of MTR objects is
done in their own namespace (rte_mtr) within the librte_ether library.

Main features:
1. Traffic metering: determine the color for the current packet (green,
   yellow, red) based on history maintained by the MTR object. Supported
   algorithms: srTCM (RFC 2697), trTCM (RFC 2698 and RFC 4115).
2. Policing (per meter output color actions): re-color the packet (keep
   or change the meter output color) or drop the packet.
3. Statistics
4. Capability API

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
Changes in v4:
- Input from Hemant:
	- Added the NONE metering algorithm for meter pass-through mode
	- Reordered stats counter types per pkt and per byte
	- Copyright cosmetics
- Updated ethdev port_id from uint8_t to uint16_t

Changes in v3:
- None

Changes in v2:
- Implemented input from Hemant:
     - Added support for RFC 4115 trTCM algorithm
     - Added support for meter pass-through mode: see API functions
       rte_mtr_meter_enable() and rte_mtr_meter_disable()
- Implemented input from Jerin:
     - Added capability API
- Implemented input from Thomas:
     - Added new API functions under the EXPERIMENTAL section in map file
- Improved the mechanism for MTR object chaining: each MTR object can be
  configured whther to read input color from a previous MTR object in the
  same flow (if any) of from DSCP traslation table
- Improved run-time update functions
- Doxygen: added more descriptions, small fixes

Changes in v1 (from RFC [1]):
- Implemented input from Thomas:
     - Added EXPERIMENTAL tag in rte_mtr.h and MANTAINERS for this new API
- Implemented input from Adrien:
     - Added more Doxygen comments to re-inforce relationship between MTR and
       flow
- Doxygen: added hook in doxy-api-index.md

[1] RFC: http://www.dpdk.org/ml/archives/dev/2017-May/066888.html

 MAINTAINERS                             |   4 +
 doc/api/doxy-api-index.md               |   1 +
 lib/librte_ether/Makefile               |   3 +
 lib/librte_ether/rte_ethdev_version.map |  18 +
 lib/librte_ether/rte_mtr.c              | 229 ++++++++++
 lib/librte_ether/rte_mtr.h              | 730 ++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_mtr_driver.h       | 221 ++++++++++
 7 files changed, 1206 insertions(+)
 create mode 100644 lib/librte_ether/rte_mtr.c
 create mode 100644 lib/librte_ether/rte_mtr.h
 create mode 100644 lib/librte_ether/rte_mtr_driver.h

diff --git a/MAINTAINERS b/MAINTAINERS
index c00d6d8..464ebac 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -255,6 +255,10 @@ M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
 T: git://dpdk.org/next/dpdk-next-tm
 F: lib/librte_ether/rte_tm*
 
+Traffic Metering and Policing API - EXPERIMENTAL
+M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
+F: lib/librte_ether/rte_mtr*
+
 Crypto API
 M: Declan Doherty <declan.doherty@intel.com>
 F: lib/librte_cryptodev/
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 990815f..07d6f4a 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -41,6 +41,7 @@ The public API headers are grouped by topics:
   [ethctrl]            (@ref rte_eth_ctrl.h),
   [rte_flow]           (@ref rte_flow.h),
   [rte_tm]             (@ref rte_tm.h),
+  [rte_mtr]            (@ref rte_mtr.h),
   [cryptodev]          (@ref rte_cryptodev.h),
   [eventdev]           (@ref rte_eventdev.h),
   [event_eth_rx_adapter]   (@ref rte_event_eth_rx_adapter.h),
diff --git a/lib/librte_ether/Makefile b/lib/librte_ether/Makefile
index edcddf7..b2a93bf 100644
--- a/lib/librte_ether/Makefile
+++ b/lib/librte_ether/Makefile
@@ -46,6 +46,7 @@ LIBABIVER := 8
 SRCS-y += rte_ethdev.c
 SRCS-y += rte_flow.c
 SRCS-y += rte_tm.c
+SRCS-y += rte_mtr.c
 SRCS-y += ethdev_profile.c
 
 #
@@ -60,5 +61,7 @@ SYMLINK-y-include += rte_flow.h
 SYMLINK-y-include += rte_flow_driver.h
 SYMLINK-y-include += rte_tm.h
 SYMLINK-y-include += rte_tm_driver.h
+SYMLINK-y-include += rte_mtr.h
+SYMLINK-y-include += rte_mtr_driver.h
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_ether/rte_ethdev_version.map b/lib/librte_ether/rte_ethdev_version.map
index e27f596..bc0bbc5 100644
--- a/lib/librte_ether/rte_ethdev_version.map
+++ b/lib/librte_ether/rte_ethdev_version.map
@@ -196,3 +196,21 @@ DPDK_17.11 {
 	rte_flow_error_set;
 
 } DPDK_17.08;
+
+EXPERIMENTAL {
+	global:
+
+	rte_mtr_capabilities_get;
+	rte_mtr_meter_profile_add;
+	rte_mtr_meter_profile_delete;
+	rte_mtr_create;
+	rte_mtr_destroy;
+	rte_mtr_meter_enable;
+	rte_mtr_meter_disable;
+	rte_mtr_meter_profile_update;
+	rte_mtr_meter_dscp_table_update;
+	rte_mtr_policer_actions_update;
+	rte_mtr_stats_update;
+	rte_mtr_stats_read;
+
+} DPDK_17.11;
diff --git a/lib/librte_ether/rte_mtr.c b/lib/librte_ether/rte_mtr.c
new file mode 100644
index 0000000..4f56f87
--- /dev/null
+++ b/lib/librte_ether/rte_mtr.c
@@ -0,0 +1,229 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+
+#include <rte_errno.h>
+#include "rte_ethdev.h"
+#include "rte_mtr_driver.h"
+#include "rte_mtr.h"
+
+/* Get generic traffic metering & policing operations structure from a port. */
+const struct rte_mtr_ops *
+rte_mtr_ops_get(uint16_t port_id, struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	const struct rte_mtr_ops *ops;
+
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		rte_mtr_error_set(error,
+			ENODEV,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			rte_strerror(ENODEV));
+		return NULL;
+	}
+
+	if ((dev->dev_ops->mtr_ops_get == NULL) ||
+		(dev->dev_ops->mtr_ops_get(dev, &ops) != 0) ||
+		(ops == NULL)) {
+		rte_mtr_error_set(error,
+			ENOSYS,
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			rte_strerror(ENOSYS));
+		return NULL;
+	}
+
+	return ops;
+}
+
+#define RTE_MTR_FUNC(port_id, func)			\
+({							\
+	const struct rte_mtr_ops *ops =			\
+		rte_mtr_ops_get(port_id, error);		\
+	if (ops == NULL)					\
+		return -rte_errno;			\
+							\
+	if (ops->func == NULL)				\
+		return -rte_mtr_error_set(error,		\
+			ENOSYS,				\
+			RTE_MTR_ERROR_TYPE_UNSPECIFIED,	\
+			NULL,				\
+			rte_strerror(ENOSYS));		\
+							\
+	ops->func;					\
+})
+
+/* MTR capabilities get */
+int
+rte_mtr_capabilities_get(uint16_t port_id,
+	struct rte_mtr_capabilities *cap,
+	struct rte_mtr_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	return RTE_MTR_FUNC(port_id, capabilities_get)(dev,
+		cap, error);
+}
+
+/* MTR meter profile add */
+int
+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);
+}
+
+/** MTR meter profile delete */
+int
+rte_mtr_meter_profile_delete(uint16_t port_id,
+	uint32_t meter_profile_id,
+	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);
+}
+
+/** MTR object create */
+int
+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);
+}
+
+/** MTR object destroy */
+int
+rte_mtr_destroy(uint16_t port_id,
+	uint32_t mtr_id,
+	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 object meter enable */
+int
+rte_mtr_meter_enable(uint16_t port_id,
+	uint32_t mtr_id,
+	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 object meter disable */
+int
+rte_mtr_meter_disable(uint16_t port_id,
+	uint32_t mtr_id,
+	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 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_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 object meter DSCP table update */
+int
+rte_mtr_meter_dscp_table_update(uint16_t port_id,
+	uint32_t mtr_id,
+	enum rte_mtr_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 object policer action update */
+int
+rte_mtr_policer_actions_update(uint16_t port_id,
+	uint32_t mtr_id,
+	uint32_t action_mask,
+	enum rte_mtr_policer_action *actions,
+	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);
+}
+
+/** MTR object enabled stats update */
+int
+rte_mtr_stats_update(uint16_t port_id,
+	uint32_t mtr_id,
+	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 object stats read */
+int
+rte_mtr_stats_read(uint16_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error)
+{
+	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);
+}
diff --git a/lib/librte_ether/rte_mtr.h b/lib/librte_ether/rte_mtr.h
new file mode 100644
index 0000000..f6b6ef3
--- /dev/null
+++ b/lib/librte_ether/rte_mtr.h
@@ -0,0 +1,730 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright 2017 Intel Corporation
+ *   Copyright 2017 NXP
+ *   Copyright 2017 Cavium
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __INCLUDE_RTE_MTR_H__
+#define __INCLUDE_RTE_MTR_H__
+
+/**
+ * @file
+ * RTE Generic Traffic Metering and Policing API
+ *
+ * This interface provides the ability to configure the traffic metering and
+ * policing (MTR) in a generic way.
+ *
+ * The processing done for each input packet hitting a MTR object is:
+ *    A) Traffic metering: The packet is assigned a color (the meter output
+ *       color), based on the previous history of the flow reflected in the
+ *       current state of the MTR object, according to the specific traffic
+ *       metering algorithm. The traffic metering algorithm can typically work
+ *       in color aware mode, in which case the input packet already has an
+ *       initial color (the input color), or in color blind mode, which is
+ *       equivalent to considering all input packets initially colored as green.
+ *    B) Policing: There is a separate policer action configured for each meter
+ *       output color, which can:
+ *          a) Drop the packet.
+ *          b) Keep the same packet color: the policer output color matches the
+ *             meter output color (essentially a no-op action).
+ *          c) Recolor the packet: the policer output color is different 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).
+ *    C) Statistics: The set of counters maintained for each MTR object is
+ *       configurable and subject to the implementation support. This set
+ *       includes the number of packets and bytes dropped or passed for each
+ *       output color.
+ *
+ * Once successfully created, an MTR object is linked to one or several flows
+ * through the meter action of the flow API.
+ *    A) Whether an MTR object is private to a flow or potentially shared by
+ *       several flows has to be specified at creation time.
+ *    B) Several meter actions can be potentially registered for the same flow.
+ *
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ */
+#include <stdint.h>
+
+#include <rte_common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Color
+ */
+enum rte_mtr_color {
+	RTE_MTR_GREEN = 0, /**< Green */
+	RTE_MTR_YELLOW, /**< Yellow */
+	RTE_MTR_RED, /**< Red */
+	RTE_MTR_COLORS /**< Number of colors. */
+};
+
+/**
+ * Statistics counter type
+ */
+enum rte_mtr_stats_type {
+	/** Number of packets passed as green by the policer. */
+	RTE_MTR_STATS_N_PKTS_GREEN = 1 << 0,
+
+	/** Number of packets passed as yellow by the policer. */
+	RTE_MTR_STATS_N_PKTS_YELLOW = 1 << 1,
+
+	/** Number of packets passed as red by the policer. */
+	RTE_MTR_STATS_N_PKTS_RED = 1 << 2,
+
+	/** Number of packets dropped by the policer. */
+	RTE_MTR_STATS_N_PKTS_DROPPED = 1 << 3,
+
+	/** Number of bytes passed as green by the policer. */
+	RTE_MTR_STATS_N_BYTES_GREEN = 1 << 4,
+
+	/** Number of bytes passed as yellow by the policer. */
+	RTE_MTR_STATS_N_BYTES_YELLOW = 1 << 5,
+
+	/** Number of bytes passed as red by the policer. */
+	RTE_MTR_STATS_N_BYTES_RED = 1 << 6,
+
+	/** Number of bytes dropped by the policer. */
+	RTE_MTR_STATS_N_BYTES_DROPPED = 1 << 7,
+};
+
+/**
+ * Statistics counters
+ */
+struct rte_mtr_stats {
+	/** Number of packets passed by the policer (per color). */
+	uint64_t n_pkts[RTE_MTR_COLORS];
+
+	/** Number of bytes passed by the policer (per color). */
+	uint64_t n_bytes[RTE_MTR_COLORS];
+
+	/** Number of packets dropped by the policer. */
+	uint64_t n_pkts_dropped;
+
+	/** Number of bytes passed by the policer. */
+	uint64_t n_bytes_dropped;
+};
+
+/**
+ * Traffic metering algorithms
+ */
+enum rte_mtr_algorithm {
+	/** No traffic metering performed, the output color is the same as the
+	 * input color for every input packet. The meter of the MTR object is
+	 * working in pass-through mode, having same effect as meter disable.
+	 * @see rte_mtr_meter_disable()
+	 */
+	RTE_MTR_NONE = 0,
+
+	/** Single Rate Three Color Marker (srTCM) - IETF RFC 2697. */
+	RTE_MTR_SRTCM_RFC2697,
+
+	/** Two Rate Three Color Marker (trTCM) - IETF RFC 2698. */
+	RTE_MTR_TRTCM_RFC2698,
+
+	/** Two Rate Three Color Marker (trTCM) - IETF RFC 4115. */
+	RTE_MTR_TRTCM_RFC4115,
+};
+
+/**
+ * Meter profile
+ */
+struct rte_mtr_meter_profile {
+	/** Traffic metering algorithm. */
+	enum rte_mtr_algorithm alg;
+
+	RTE_STD_C11
+	union {
+		/** Items only valid when *alg* is set to srTCM - RFC 2697. */
+		struct {
+			/** Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/** Committed Burst Size (CBS) (bytes). */
+			uint64_t cbs;
+
+			/** Excess Burst Size (EBS) (bytes). */
+			uint64_t ebs;
+		} srtcm_rfc2697;
+
+		/** Items only valid when *alg* is set to trTCM - RFC 2698. */
+		struct {
+			/** Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/** Peak Information Rate (PIR) (bytes/second). */
+			uint64_t pir;
+
+			/** Committed Burst Size (CBS) (byes). */
+			uint64_t cbs;
+
+			/** Peak Burst Size (PBS) (bytes). */
+			uint64_t pbs;
+		} trtcm_rfc2698;
+
+		/** Items only valid when *alg* is set to trTCM - RFC 4115. */
+		struct {
+			/** Committed Information Rate (CIR) (bytes/second). */
+			uint64_t cir;
+
+			/** Excess Information Rate (EIR) (bytes/second). */
+			uint64_t eir;
+
+			/** Committed Burst Size (CBS) (byes). */
+			uint64_t cbs;
+
+			/** Excess Burst Size (EBS) (bytes). */
+			uint64_t ebs;
+		} trtcm_rfc4115;
+	};
+};
+
+/**
+ * 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
+ *
+ * @see enum rte_mtr_stats_type
+ */
+struct rte_mtr_params {
+	/** Meter profile ID. */
+	uint32_t meter_profile_id;
+
+	/** 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
+	 * determined by the latest MTR object in the same flow is used as the
+	 * input color by the current MTR object, otherwise the current MTR
+	 * object uses the *dscp_table* to determine the input color. When zero:
+	 * the color determined by any previous MTR object in same flow is
+	 * ignored by the current MTR object, which uses the *dscp_table* to
+	 * determine the input color.
+	 */
+	int use_prev_mtr_color;
+
+	/** Meter input color. 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). The color blind mode
+	 * is configured by setting *use_prev_mtr_color* to 0 and *dscp_table*
+	 * to either NULL or to an all-green populated table. When
+	 * *use_prev_mtr_color* is non-zero value or when *dscp_table* contains
+	 * at least one yellow or red color element, then the color aware mode
+	 * is configured.
+	 */
+	enum rte_mtr_color *dscp_table;
+
+	/** Non-zero to enable the meter, zero to disable the meter at the time
+	 * of MTR object creation. Ignored when the meter profile indicated by
+	 * *meter_profile_id* is set to NONE.
+	 * @see rte_mtr_meter_disable()
+	 */
+	int meter_enable;
+
+	/** Policer actions (per meter output color). */
+	enum rte_mtr_policer_action action[RTE_MTR_COLORS];
+
+	/** Set of stats counters to be enabled.
+	 * @see enum rte_mtr_stats_type
+	 */
+	uint64_t stats_mask;
+};
+
+/**
+ * MTR capabilities
+ */
+struct rte_mtr_capabilities {
+	/** Maximum number of MTR objects. */
+	uint32_t n_max;
+
+	/** Maximum number of MTR objects that can be shared by multiple flows.
+	 * The value of zero indicates that shared MTR objects are not
+	 * supported. The maximum value is *n_max*.
+	 */
+	uint32_t n_shared_max;
+
+	/** When non-zero, this flag indicates that all the MTR objects that
+	 * cannot be shared by multiple flows have identical capability set.
+	 */
+	int identical;
+
+	/** When non-zero, this flag indicates that all the MTR objects that
+	 * can be shared by multiple flows have identical capability set.
+	 */
+	int shared_identical;
+
+	/** Maximum number of flows that can share the same MTR object. The
+	 * value of zero is invalid. The value of 1 means that shared MTR
+	 * objects not supported.
+	 */
+	uint32_t shared_n_flows_per_mtr_max;
+
+	/** Maximum number of MTR objects that can be part of the same flow. The
+	 * value of zero is invalid. The value of 1 indicates that MTR object
+	 * chaining is not supported. The maximum value is *n_max*.
+	 */
+	uint32_t chaining_n_mtrs_per_flow_max;
+
+	/**
+	 * When non-zero, it indicates that the packet color identified by one
+	 * MTR object can be used as the packet input color by any subsequent
+	 * MTR object from the same flow. When zero, it indicates that the color
+	 * determined by one MTR object is always ignored by any subsequent MTR
+	 * object from the same flow. Only valid when MTR chaining is supported,
+	 * i.e. *chaining_n_mtrs_per_flow_max* is greater than 1. When non-zero,
+	 * it also means that the color aware mode is supported by at least one
+	 * metering algorithm.
+	 */
+	int chaining_use_prev_mtr_color_supported;
+
+	/**
+	 * When non-zero, it indicates that the packet color identified by one
+	 * MTR object is always used as the packet input color by any subsequent
+	 * MTR object that is part of the same flow. When zero, it indicates
+	 * that whether the color determined by one MTR object is either ignored
+	 * or used as the packet input color by any subsequent MTR object from
+	 * the same flow is individually configurable for each MTR object. Only
+	 * valid when *chaining_use_prev_mtr_color_supported* is non-zero.
+	 */
+	int chaining_use_prev_mtr_color_enforced;
+
+	/** Maximum number of MTR objects that can have their meter configured
+	 * to run the srTCM RFC 2697 algorithm. The value of 0 indicates this
+	 * metering algorithm is not supported. The maximum value is *n_max*.
+	 */
+	uint32_t meter_srtcm_rfc2697_n_max;
+
+	/** Maximum number of MTR objects that can have their meter configured
+	 * to run the trTCM RFC 2698 algorithm. The value of 0 indicates this
+	 * metering algorithm is not supported. The maximum value is *n_max*.
+	 */
+	uint32_t meter_trtcm_rfc2698_n_max;
+
+	/** Maximum number of MTR objects that can have their meter configured
+	 * to run the trTCM RFC 4115 algorithm. The value of 0 indicates this
+	 * metering algorithm is not supported. The maximum value is *n_max*.
+	 */
+	uint32_t meter_trtcm_rfc4115_n_max;
+
+	/** Maximum traffic rate that can be metered by a single MTR object. For
+	 * srTCM RFC 2697, this is the maximum CIR rate. For trTCM RFC 2698,
+	 * this is the maximum PIR rate. For trTCM RFC 4115, this is the maximum
+	 * value for the sum of PIR and EIR rates.
+	 */
+	uint64_t meter_rate_max;
+
+	/**
+	 * When non-zero, it indicates that color aware mode is supported for
+	 * the srTCM RFC 2697 metering algorithm.
+	 */
+	int color_aware_srtcm_rfc2697_supported;
+
+	/**
+	 * When non-zero, it indicates that color aware mode is supported for
+	 * the trTCM RFC 2698 metering algorithm.
+	 */
+	int color_aware_trtcm_rfc2698_supported;
+
+	/**
+	 * When non-zero, it indicates that color aware mode is supported for
+	 * the trTCM RFC 4115 metering algorithm.
+	 */
+	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
+	 */
+	uint64_t stats_mask;
+};
+
+/**
+ * Verbose error types.
+ *
+ * Most of them provide the type of the object referenced by struct
+ * rte_mtr_error::cause.
+ */
+enum rte_mtr_error_type {
+	RTE_MTR_ERROR_TYPE_NONE, /**< No error. */
+	RTE_MTR_ERROR_TYPE_UNSPECIFIED, /**< Cause unspecified. */
+	RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+	RTE_MTR_ERROR_TYPE_METER_PROFILE,
+	RTE_MTR_ERROR_TYPE_MTR_ID,
+	RTE_MTR_ERROR_TYPE_MTR_PARAMS,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW,
+	RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED,
+	RTE_MTR_ERROR_TYPE_STATS_MASK,
+	RTE_MTR_ERROR_TYPE_STATS,
+	RTE_MTR_ERROR_TYPE_SHARED,
+};
+
+/**
+ * Verbose error structure definition.
+ *
+ * This object is normally allocated by applications and set by PMDs, the
+ * message points to a constant string which does not need to be freed by
+ * the application, however its pointer can be considered valid only as long
+ * as its associated DPDK port remains configured. Closing the underlying
+ * device or unloading the PMD invalidates it.
+ *
+ * Both cause and message may be NULL regardless of the error type.
+ */
+struct rte_mtr_error {
+	enum rte_mtr_error_type type; /**< Cause field and error type. */
+	const void *cause; /**< Object responsible for the error. */
+	const char *message; /**< Human-readable error message. */
+};
+
+/**
+ * MTR capabilities get
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[out] cap
+ *   MTR capabilities. 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.
+ */
+int
+rte_mtr_capabilities_get(uint16_t port_id,
+	struct rte_mtr_capabilities *cap,
+	struct rte_mtr_error *error);
+
+/**
+ * Meter profile add
+ *
+ * Create a new meter profile with ID set to *meter_profile_id*. 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.
+ */
+int
+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);
+
+/**
+ * Meter profile delete
+ *
+ * Delete an existing meter profile. This operation fails when there is
+ * currently at least one user (i.e. MTR object) of this profile.
+ *
+ * @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[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_profile_delete(uint16_t port_id,
+	uint32_t meter_profile_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
+ * associated flow action for traffic metering and policing.
+ *
+ * @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
+ *   Non-zero when this MTR object can be shared by multiple flows, zero when
+ *   this MTR object can be used by a single flow.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_flow_action_type::RTE_FLOW_ACTION_TYPE_METER
+ */
+int
+rte_mtr_create(uint16_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_params *params,
+	int shared,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object destroy
+ *
+ * Delete an existing MTR object. This operation fails when there is currently
+ * at least one user (i.e. flow) of this MTR object.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be valid.
+ *   created for the current port.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_destroy(uint16_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object meter disable
+ *
+ * Disable the meter of an existing MTR object. In disabled state, the meter of
+ * the current MTR object works in pass-through mode, meaning that for each
+ * input packet the meter output color is always the same as the input color. In
+ * particular, when the meter of the current MTR object is configured in color
+ * blind mode, the input color is always green, so the meter output color is
+ * also always green. Note that the policer and the statistics of the current
+ * MTR object are working as usual while the meter is disabled. No action is
+ * taken and this function returns successfully when the meter of the current
+ * MTR object is already disabled.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_disable(uint16_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object meter enable
+ *
+ * Enable the meter of an existing MTR object. If the MTR object has its meter
+ * already enabled, then no action is taken and this function returns
+ * successfully.
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_enable(uint16_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object meter profile 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] meter_profile_id
+ *   Meter profile ID for the current MTR object. Needs to be valid.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_profile_update(uint16_t port_id,
+	uint32_t mtr_id,
+	uint32_t meter_profile_id,
+	struct rte_mtr_error *error);
+
+/**
+ * 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] 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
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_meter_dscp_table_update(uint16_t port_id,
+	uint32_t mtr_id,
+	enum rte_mtr_color *dscp_table,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object policer actions 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[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ */
+int
+rte_mtr_policer_actions_update(uint16_t port_id,
+	uint32_t mtr_id,
+	uint32_t action_mask,
+	enum rte_mtr_policer_action *actions,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object enabled statistics counters 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] stats_mask
+ *   Mask of statistics counter types to be enabled for the current MTR object.
+ *   Any statistics counter type not included in this set is to be disabled for
+ *   the current MTR object.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_mtr_stats_type
+ */
+int
+rte_mtr_stats_update(uint16_t port_id,
+	uint32_t mtr_id,
+	uint64_t stats_mask,
+	struct rte_mtr_error *error);
+
+/**
+ * MTR object statistics counters read
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[in] mtr_id
+ *   MTR object ID. Needs to be valid.
+ * @param[out] stats
+ *   When non-NULL, it contains the current value for the statistics counters
+ *   enabled for the current MTR object.
+ * @param[out] stats_mask
+ *   When non-NULL, it contains the mask of statistics counter types that are
+ *   currently enabled for this MTR object, indicating which of the counters
+ *   retrieved with the *stats* structure are valid.
+ * @param[in] clear
+ *   When this parameter has a non-zero value, the statistics counters are
+ *   cleared (i.e. set to zero) immediately after they have been read,
+ *   otherwise the statistics counters are left untouched.
+ * @param[out] error
+ *   Error details. Filled in only on error, when not NULL.
+ * @return
+ *   0 on success, non-zero error code otherwise.
+ *
+ * @see enum rte_mtr_stats_type
+ */
+int
+rte_mtr_stats_read(uint16_t port_id,
+	uint32_t mtr_id,
+	struct rte_mtr_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_RTE_MTR_H__ */
diff --git a/lib/librte_ether/rte_mtr_driver.h b/lib/librte_ether/rte_mtr_driver.h
new file mode 100644
index 0000000..6a289ef
--- /dev/null
+++ b/lib/librte_ether/rte_mtr_driver.h
@@ -0,0 +1,221 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __INCLUDE_RTE_MTR_DRIVER_H__
+#define __INCLUDE_RTE_MTR_DRIVER_H__
+
+/**
+ * @file
+ * RTE Generic Traffic Metering and Policing API (Driver Side)
+ *
+ * This file provides implementation helpers for internal use by PMDs, they
+ * are not intended to be exposed to applications and are not subject to ABI
+ * versioning.
+ */
+
+#include <stdint.h>
+
+#include <rte_errno.h>
+#include "rte_ethdev.h"
+#include "rte_mtr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int (*rte_mtr_capabilities_get_t)(struct rte_eth_dev *dev,
+	struct rte_mtr_capabilities *cap,
+	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,
+	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_error *error);
+/**< @internal MTR meter profile delete */
+
+typedef int (*rte_mtr_create_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	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_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_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_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_error *error);
+/**< @internal MTR object meter profile update */
+
+typedef int (*rte_mtr_meter_dscp_table_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	enum rte_mtr_color *dscp_table,
+	struct rte_mtr_error *error);
+/**< @internal MTR object meter DSCP table update */
+
+typedef int (*rte_mtr_policer_actions_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	uint32_t action_mask,
+	enum rte_mtr_policer_action *actions,
+	struct rte_mtr_error *error);
+/**< @internal MTR object policer action update*/
+
+typedef int (*rte_mtr_stats_update_t)(struct rte_eth_dev *dev,
+	uint32_t mtr_id,
+	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_stats *stats,
+	uint64_t *stats_mask,
+	int clear,
+	struct rte_mtr_error *error);
+/**< @internal MTR object stats read */
+
+struct rte_mtr_ops {
+	/** MTR capabilities get */
+	rte_mtr_capabilities_get_t capabilities_get;
+
+	/** MTR meter profile add */
+	rte_mtr_meter_profile_add_t meter_profile_add;
+
+	/** MTR meter profile delete */
+	rte_mtr_meter_profile_delete_t meter_profile_delete;
+
+	/** MTR object create */
+	rte_mtr_create_t create;
+
+	/** MTR object destroy */
+	rte_mtr_destroy_t destroy;
+
+	/** MTR object meter enable */
+	rte_mtr_meter_enable_t meter_enable;
+
+	/** MTR object meter disable */
+	rte_mtr_meter_disable_t meter_disable;
+
+	/** MTR object meter profile update */
+	rte_mtr_meter_profile_update_t meter_profile_update;
+
+	/** 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;
+};
+
+/**
+ * Initialize generic error structure.
+ *
+ * This function also sets rte_errno to a given value.
+ *
+ * @param[out] error
+ *   Pointer to error structure (may be NULL).
+ * @param[in] code
+ *   Related error code (rte_errno).
+ * @param[in] type
+ *   Cause field and error type.
+ * @param[in] cause
+ *   Object responsible for the error.
+ * @param[in] message
+ *   Human-readable error message.
+ *
+ * @return
+ *   Error code.
+ */
+static inline int
+rte_mtr_error_set(struct rte_mtr_error *error,
+		   int code,
+		   enum rte_mtr_error_type type,
+		   const void *cause,
+		   const char *message)
+{
+	if (error) {
+		*error = (struct rte_mtr_error){
+			.type = type,
+			.cause = cause,
+			.message = message,
+		};
+	}
+	rte_errno = code;
+	return code;
+}
+
+/**
+ * Get generic traffic metering and policing operations structure from a port
+ *
+ * @param[in] port_id
+ *   The port identifier of the Ethernet device.
+ * @param[out] error
+ *   Error details
+ *
+ * @return
+ *   The traffic metering and policing operations structure associated with
+ *   port_id on success, NULL otherwise.
+ */
+const struct rte_mtr_ops *
+rte_mtr_ops_get(uint16_t port_id, struct rte_mtr_error *error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_RTE_MTR_DRIVER_H__ */
-- 
2.7.4

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

* [PATCH V4 4/5] doc: ethdev traffic metering and policing api
  2017-10-13 12:22               ` [PATCH V4 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
                                   ` (2 preceding siblings ...)
  2017-10-13 12:22                 ` [PATCH V4 3/5] ethdev: add new api for traffic metering and policing Cristian Dumitrescu
@ 2017-10-13 12:22                 ` Cristian Dumitrescu
  2017-10-13 15:43                   ` Mcnamara, John
  2017-10-13 12:22                 ` [PATCH V4 5/5] app/testpmd: cli for traffic metering and policing Cristian Dumitrescu
  2017-10-20 12:15                 ` [PATCH V4 0/5] rte_mtr: generic ethdev api for " Dumitrescu, Cristian
  5 siblings, 1 reply; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-13 12:22 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, john.mcnamara,
	hemant.agrawal, jerin.jacob, jasvinder.singh

Add new section in the Programmer Guide for the ethdev traffic metering
and policing (MTR) API.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
Changes in v4:
-Improvements from John McNamara on RST formatting

 doc/guides/prog_guide/index.rst                    |   1 +
 .../prog_guide/traffic_metering_and_policing.rst   | 102 +++++++++++++++++++++
 2 files changed, 103 insertions(+)
 create mode 100644 doc/guides/prog_guide/traffic_metering_and_policing.rst

diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index b5ad6b8..fbd2a72 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -44,6 +44,7 @@ Programmer's Guide
     mbuf_lib
     poll_mode_drv
     rte_flow
+    traffic_metering_and_policing
     traffic_management
     cryptodev_lib
     link_bonding_poll_mode_drv_lib
diff --git a/doc/guides/prog_guide/traffic_metering_and_policing.rst b/doc/guides/prog_guide/traffic_metering_and_policing.rst
new file mode 100644
index 0000000..89f0e68
--- /dev/null
+++ b/doc/guides/prog_guide/traffic_metering_and_policing.rst
@@ -0,0 +1,102 @@
+..  BSD LICENSE
+    Copyright(c) 2017 Intel Corporation. All rights reserved.
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+    * Neither the name of Intel Corporation nor the names of its
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Traffic Metering and Policing API
+=================================
+
+
+Overview
+--------
+
+This is the generic API for the Quality of Service (QoS) Traffic Metering and
+Policing (MTR) of Ethernet devices. This API is agnostic of the underlying HW,
+SW or mixed HW-SW implementation.
+
+The main features are:
+
+* Part of DPDK rte_ethdev API
+* Capability query API
+* Metering algorithms: RFC 2697 Single Rate Three Color Marker (srTCM), RFC 2698
+  and RFC 4115 Two Rate Three Color Marker (trTCM)
+* Policer actions (per meter output color): recolor, drop
+* Statistics (per policer output color)
+
+Configuration steps
+-------------------
+
+The metering and policing stage typically sits on top of flow classification,
+which is why the MTR objects are enabled through a special "meter" action.
+
+The MTR objects are created and updated in their own name space (``rte_mtr``)
+within the ``librte_ether`` library. Whether an MTR object is private to a
+flow or potentially shared by several flows has to be specified at its
+creation time.
+
+Once successfully created, an MTR object is hooked into the RX processing path
+of the Ethernet device by linking it to one or several flows through the
+dedicated "meter" flow action. One or several "meter" actions can be registered
+for the same flow. An MTR object can only be destroyed if there are no flows
+using it.
+
+Run-time processing
+-------------------
+
+Traffic metering determines the color for the current packet (green, yellow,
+red) based on the previous history for this flow as maintained by the MTR
+object. The policer can do nothing, override the color the packet or drop the
+packet. Statistics counters are maintained for MTR object, as configured.
+
+The processing done for each input packet hitting an MTR object is:
+
+* Traffic metering: The packet is assigned a color (the meter output color)
+  based on the previous traffic history reflected in the current state of the
+  MTR object, according to the specific traffic metering algorithm. The
+  traffic metering algorithm can typically work in color aware mode, in which
+  case the input packet already has an initial color (the input color), or in
+  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``).
+
+* Statistics: The set of counters maintained for each MTR object is
+  configurable and subject to the implementation support. This set includes
+  the number of packets and bytes dropped or passed for each output color.
-- 
2.7.4

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

* [PATCH V4 5/5] app/testpmd: cli for traffic metering and policing
  2017-10-13 12:22               ` [PATCH V4 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
                                   ` (3 preceding siblings ...)
  2017-10-13 12:22                 ` [PATCH V4 4/5] doc: ethdev traffic metering and policing api Cristian Dumitrescu
@ 2017-10-13 12:22                 ` Cristian Dumitrescu
  2017-10-16  9:49                   ` Wu, Jingjing
  2017-10-20 12:15                 ` [PATCH V4 0/5] rte_mtr: generic ethdev api for " Dumitrescu, Cristian
  5 siblings, 1 reply; 64+ messages in thread
From: Cristian Dumitrescu @ 2017-10-13 12:22 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, john.mcnamara,
	hemant.agrawal, jerin.jacob, jasvinder.singh

Add CLI commands to exercise the ethdev Traffic Metering and Policing
(MTR) API.

Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
Changes in v4:
-Input from Jingjing
	-Added help for MTR CLI commands
-Updated ethdev port_id from uint8_t to uint16_t
-Removed some trailing white spaces

Changes in v3:
- Added newline at the end of cmdline_mtr.h

 app/test-pmd/Makefile       |    1 +
 app/test-pmd/cmdline.c      |   39 ++
 app/test-pmd/cmdline_flow.c |   24 +
 app/test-pmd/cmdline_mtr.c  | 1020 +++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/cmdline_mtr.h  |   49 +++
 5 files changed, 1133 insertions(+)
 create mode 100644 app/test-pmd/cmdline_mtr.c
 create mode 100644 app/test-pmd/cmdline_mtr.h

diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile
index 2c50f68..b7c0ba6 100644
--- a/app/test-pmd/Makefile
+++ b/app/test-pmd/Makefile
@@ -48,6 +48,7 @@ SRCS-y := testpmd.c
 SRCS-y += parameters.c
 SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline.c
 SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_flow.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_mtr.c
 SRCS-y += config.c
 SRCS-y += iofwd.c
 SRCS-y += macfwd.c
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index bb19d72..a0bad40 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -99,6 +99,7 @@
 #include <rte_pmd_bnxt.h>
 #endif
 #include "testpmd.h"
+#include "cmdline_mtr.h"
 
 static struct cmdline *testpmd_cl;
 
@@ -234,6 +235,8 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"show port (port_id) pctype mapping\n"
 			"    Get flow ptype to pctype mapping on a port\n\n"
 
+			"show port meter stats (port_id) (meter_id) (clear)\n"
+			"    Get meter stats on a port\n\n"
 		);
 	}
 
@@ -675,6 +678,33 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"set port (port_id) queue-region flush (on|off)\n"
 			"    flush all queue region related configuration\n\n"
 
+			"add port meter profile srtcm_rfc2697 (port_id) (profile_id) (cir) (cbs) (ebs) (color_aware)\n"
+			"    meter profile add - srtcm rfc 2697\n\n"
+
+			"add port meter profile trtcm_rfc2698 (port_id) (profile_id) (cir) (pir) (cbs) (pbs)\n"
+			"    meter profile add - trtcm rfc 2698\n\n"
+
+			"add port meter profile trtcm_rfc4115 (port_id) (profile_id) (cir) (eir) (cbs) (ebs)\n"
+			"    meter profile add - trtcm rfc 4115\n\n"
+
+			"del port meter profile (port_id) (profile_id)\n"
+			"    meter profile delete\n\n"
+
+			"set port meter (port_id) (mtr_id) (profile_id) (g_action) (y_action) (r_action) (stats_mask) (shared)\n"
+			"    meter create\n\n"
+
+			"del port meter (port_id) (mtr_id)\n"
+			"    meter delete\n\n"
+
+			"set port meter profile (port_id) (mtr_id) (profile_id)\n"
+			"    meter update meter profile\n\n"
+
+			"set port meter policer action (port_id) (mtr_id) (color) (action)\n"
+			"    meter update policer action\n\n"
+
+			"set port meter stats mask (port_id) (mtr_id) (stats_mask)\n"
+			"    meter update stats\n\n"
+
 			"show port (port_id) queue-region\n"
 			"    show all queue region related configuration info\n\n"
 
@@ -15538,6 +15568,15 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_hash_input_set,
 	(cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
 	(cmdline_parse_inst_t *)&cmd_flow,
+	(cmdline_parse_inst_t *)&cmd_add_port_meter_profile_srtcm,
+	(cmdline_parse_inst_t *)&cmd_add_port_meter_profile_trtcm,
+	(cmdline_parse_inst_t *)&cmd_del_port_meter_profile,
+	(cmdline_parse_inst_t *)&cmd_set_port_meter,
+	(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_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,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index b5d394d..df16d2a 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -198,6 +198,8 @@ enum index {
 	ACTION_VF,
 	ACTION_VF_ORIGINAL,
 	ACTION_VF_ID,
+	ACTION_METER,
+	ACTION_METER_ID,
 };
 
 /** Size of pattern[] field in struct rte_flow_item_raw. */
@@ -614,6 +616,7 @@ static const enum index next_action[] = {
 	ACTION_RSS,
 	ACTION_PF,
 	ACTION_VF,
+	ACTION_METER,
 	ZERO,
 };
 
@@ -648,6 +651,12 @@ static const enum index action_vf[] = {
 	ZERO,
 };
 
+static const enum index action_meter[] = {
+	ACTION_METER_ID,
+	ACTION_NEXT,
+	ZERO,
+};
+
 static int parse_init(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
@@ -1606,6 +1615,21 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
 		.call = parse_vc_conf,
 	},
+	[ACTION_METER] = {
+		.name = "meter",
+		.help = "meter the directed packets at given id",
+		.priv = PRIV_ACTION(METER,
+				    sizeof(struct rte_flow_action_meter)),
+		.next = NEXT(action_meter),
+		.call = parse_vc,
+	},
+	[ACTION_METER_ID] = {
+		.name = "mtr_id",
+		.help = "meter id to use",
+		.next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
+		.call = parse_vc_conf,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
diff --git a/app/test-pmd/cmdline_mtr.c b/app/test-pmd/cmdline_mtr.c
new file mode 100644
index 0000000..82b0ddf
--- /dev/null
+++ b/app/test-pmd/cmdline_mtr.c
@@ -0,0 +1,1020 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+
+#include <rte_ethdev.h>
+#include <rte_flow.h>
+#include <rte_mtr.h>
+
+#include "testpmd.h"
+#include "cmdline_mtr.h"
+
+/** Display Meter Error Message */
+static void
+print_err_msg(struct rte_mtr_error *error)
+{
+	static const char *const errstrlist[] = {
+		[RTE_MTR_ERROR_TYPE_NONE] = "no error",
+		[RTE_MTR_ERROR_TYPE_UNSPECIFIED] = "cause unspecified",
+		[RTE_MTR_ERROR_TYPE_METER_PROFILE_ID] = "meter profile id",
+		[RTE_MTR_ERROR_TYPE_METER_PROFILE] = "meter profile null",
+		[RTE_MTR_ERROR_TYPE_MTR_ID] = "meter id",
+		[RTE_MTR_ERROR_TYPE_MTR_PARAMS] = "meter params null",
+		[RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN]
+			= "policer action(green)",
+		[RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW]
+			= "policer action(yellow)",
+		[RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED]
+			= "policer action(red)",
+		[RTE_MTR_ERROR_TYPE_STATS_MASK] = "stats mask",
+		[RTE_MTR_ERROR_TYPE_STATS] = "stats",
+		[RTE_MTR_ERROR_TYPE_SHARED]
+			= "shared meter",
+	};
+
+	const char *errstr;
+	char buf[64];
+
+	if ((unsigned int)error->type >= RTE_DIM(errstrlist) ||
+		!errstrlist[error->type])
+		errstr = "unknown type";
+	else
+		errstr = errstrlist[error->type];
+
+	if (error->cause)
+		snprintf(buf, sizeof(buf), "cause: %p, ", error->cause);
+
+	printf("%s: %s%s (error %d)\n", errstr, error->cause ? buf : "",
+		error->message ? error->message : "(no stated reason)",
+		error->type);
+}
+
+static int
+string_to_policer_action(char *s)
+{
+	if (strcmp(s, "G") == 0)
+		return MTR_POLICER_ACTION_COLOR_GREEN;
+
+	if (strcmp(s, "Y") == 0)
+		return MTR_POLICER_ACTION_COLOR_YELLOW;
+
+	if (strcmp(s, "R") == 0)
+		return MTR_POLICER_ACTION_COLOR_RED;
+
+	if (strcmp(s, "D") == 0)
+		return MTR_POLICER_ACTION_DROP;
+
+	return -1;
+}
+
+/* *** Add Port Meter Profile srtcm_rfc2697 *** */
+struct cmd_add_port_meter_profile_srtcm_result {
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	cmdline_fixed_string_t srtcm_rfc2697;
+	uint16_t port_id;
+	uint32_t profile_id;
+	uint64_t cir;
+	uint64_t cbs;
+	uint64_t ebs;
+	uint8_t color_aware;
+};
+
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_add =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result, add, "add");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			port, "port");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			meter, "meter");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			profile, "profile");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_srtcm_rfc2697 =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			srtcm_rfc2697, "srtcm_rfc2697");
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			port_id, UINT16);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			profile_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_cir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			cir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_cbs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			cbs, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_ebs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_srtcm_result,
+			ebs, UINT64);
+
+static void cmd_add_port_meter_profile_srtcm_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_add_port_meter_profile_srtcm_result *res = parsed_result;
+	struct rte_mtr_meter_profile mp;
+	struct rte_mtr_error error;
+	uint32_t profile_id = res->profile_id;
+	uint16_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Private shaper profile params */
+	memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
+	mp.alg = 0;
+	mp.srtcm_rfc2697.cir = res->cir;
+	mp.srtcm_rfc2697.cbs = res->cbs;
+	mp.srtcm_rfc2697.ebs = res->ebs;
+
+	ret = rte_mtr_meter_profile_add(port_id, profile_id, &mp, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_add_port_meter_profile_srtcm = {
+	.f = cmd_add_port_meter_profile_srtcm_parsed,
+	.data = NULL,
+	.help_str = "Add port meter profile srtcm (rfc2697)",
+	.tokens = {
+		(void *)&cmd_add_port_meter_profile_srtcm_add,
+		(void *)&cmd_add_port_meter_profile_srtcm_port,
+		(void *)&cmd_add_port_meter_profile_srtcm_meter,
+		(void *)&cmd_add_port_meter_profile_srtcm_profile,
+		(void *)&cmd_add_port_meter_profile_srtcm_port_id,
+		(void *)&cmd_add_port_meter_profile_srtcm_profile_id,
+		(void *)&cmd_add_port_meter_profile_srtcm_srtcm_rfc2697,
+		(void *)&cmd_add_port_meter_profile_srtcm_cir,
+		(void *)&cmd_add_port_meter_profile_srtcm_cbs,
+		(void *)&cmd_add_port_meter_profile_srtcm_ebs,
+		NULL,
+	},
+};
+
+/* *** Add Port Meter Profile trtcm_rfc2698 *** */
+struct cmd_add_port_meter_profile_trtcm_result {
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	cmdline_fixed_string_t trtcm_rfc2698;
+	uint16_t port_id;
+	uint32_t profile_id;
+	uint64_t cir;
+	uint64_t pir;
+	uint64_t cbs;
+	uint64_t pbs;
+};
+
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_add =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result, add, "add");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			port, "port");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			meter, "meter");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			profile, "profile");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_trtcm_rfc2698 =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			trtcm_rfc2698, "trtcm_rfc2698");
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			port_id, UINT16);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			profile_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_cir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			cir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_pir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			pir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_cbs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			cbs, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_pbs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_result,
+			pbs, UINT64);
+
+static void cmd_add_port_meter_profile_trtcm_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_add_port_meter_profile_trtcm_result *res = parsed_result;
+	struct rte_mtr_meter_profile mp;
+	struct rte_mtr_error error;
+	uint32_t profile_id = res->profile_id;
+	uint16_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Private shaper profile params */
+	memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
+	mp.alg = 0;
+	mp.trtcm_rfc2698.cir = res->cir;
+	mp.trtcm_rfc2698.pir = res->pir;
+	mp.trtcm_rfc2698.cbs = res->cbs;
+	mp.trtcm_rfc2698.pbs = res->pbs;
+
+	ret = rte_mtr_meter_profile_add(port_id, profile_id, &mp, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm = {
+	.f = cmd_add_port_meter_profile_trtcm_parsed,
+	.data = NULL,
+	.help_str = "Add port meter profile trtcm (rfc2698)",
+	.tokens = {
+		(void *)&cmd_add_port_meter_profile_trtcm_add,
+		(void *)&cmd_add_port_meter_profile_trtcm_port,
+		(void *)&cmd_add_port_meter_profile_trtcm_meter,
+		(void *)&cmd_add_port_meter_profile_trtcm_profile,
+		(void *)&cmd_add_port_meter_profile_trtcm_port_id,
+		(void *)&cmd_add_port_meter_profile_trtcm_profile_id,
+		(void *)&cmd_add_port_meter_profile_trtcm_trtcm_rfc2698,
+		(void *)&cmd_add_port_meter_profile_trtcm_cir,
+		(void *)&cmd_add_port_meter_profile_trtcm_pir,
+		(void *)&cmd_add_port_meter_profile_trtcm_cbs,
+		(void *)&cmd_add_port_meter_profile_trtcm_pbs,
+		NULL,
+	},
+};
+
+/* *** Add Port Meter Profile trtcm_rfc4115 *** */
+struct cmd_add_port_meter_profile_trtcm_rfc4115_result {
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	cmdline_fixed_string_t trtcm_rfc4115;
+	uint16_t port_id;
+	uint32_t profile_id;
+	uint64_t cir;
+	uint64_t eir;
+	uint64_t cbs;
+	uint64_t ebs;
+};
+
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_add =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result, add,
+		"add");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			port, "port");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			meter, "meter");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			profile, "profile");
+cmdline_parse_token_string_t
+	cmd_add_port_meter_profile_trtcm_rfc4115_trtcm_rfc4115 =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			trtcm_rfc4115, "trtcm_rfc4115");
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			port_id, UINT16);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			profile_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_cir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			cir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_eir =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			eir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_cbs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			cbs, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_ebs =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+			ebs, UINT64);
+
+static void cmd_add_port_meter_profile_trtcm_rfc4115_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_add_port_meter_profile_trtcm_rfc4115_result *res =
+		parsed_result;
+	struct rte_mtr_meter_profile mp;
+	struct rte_mtr_error error;
+	uint32_t profile_id = res->profile_id;
+	uint16_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Private shaper profile params */
+	memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
+	mp.alg = 0;
+	mp.trtcm_rfc4115.cir = res->cir;
+	mp.trtcm_rfc4115.eir = res->eir;
+	mp.trtcm_rfc4115.cbs = res->cbs;
+	mp.trtcm_rfc4115.ebs = res->ebs;
+
+	ret = rte_mtr_meter_profile_add(port_id, profile_id, &mp, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm_rfc4115 = {
+	.f = cmd_add_port_meter_profile_trtcm_rfc4115_parsed,
+	.data = NULL,
+	.help_str = "Add port meter profile trtcm (rfc4115)",
+	.tokens = {
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_add,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_port,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_meter,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_profile,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_port_id,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_profile_id,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_trtcm_rfc4115,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_cir,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_eir,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_cbs,
+		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_ebs,
+		NULL,
+	},
+};
+
+/* *** Delete Port Meter Profile *** */
+struct cmd_del_port_meter_profile_result {
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	uint16_t port_id;
+	uint32_t profile_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_meter_profile_del =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_profile_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_meter_profile_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			port, "port");
+cmdline_parse_token_string_t cmd_del_port_meter_profile_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			meter, "meter");
+cmdline_parse_token_string_t cmd_del_port_meter_profile_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			profile, "profile");
+cmdline_parse_token_num_t cmd_del_port_meter_profile_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			port_id, UINT16);
+cmdline_parse_token_num_t cmd_del_port_meter_profile_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_profile_result,
+			profile_id, UINT32);
+
+static void cmd_del_port_meter_profile_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_del_port_meter_profile_result *res = parsed_result;
+	struct rte_mtr_error error;
+	uint32_t profile_id = res->profile_id;
+	uint16_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Delete meter profile */
+	ret = rte_mtr_meter_profile_delete(port_id, profile_id, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_del_port_meter_profile = {
+	.f = cmd_del_port_meter_profile_parsed,
+	.data = NULL,
+	.help_str = "Delete port meter profile",
+	.tokens = {
+		(void *)&cmd_del_port_meter_profile_del,
+		(void *)&cmd_del_port_meter_profile_port,
+		(void *)&cmd_del_port_meter_profile_meter,
+		(void *)&cmd_del_port_meter_profile_profile,
+		(void *)&cmd_del_port_meter_profile_port_id,
+		(void *)&cmd_del_port_meter_profile_profile_id,
+		NULL,
+	},
+};
+
+/* *** Create Port Meter Object *** */
+struct cmd_set_port_meter_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	uint16_t port_id;
+	uint32_t mtr_id;
+	uint32_t profile_id;
+	cmdline_fixed_string_t g_action;
+	cmdline_fixed_string_t y_action;
+	cmdline_fixed_string_t r_action;
+	uint64_t statistics_mask;
+	uint32_t shared;
+};
+
+cmdline_parse_token_string_t cmd_set_port_meter_set =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_meter_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_meter_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_result, meter, "meter");
+cmdline_parse_token_num_t cmd_set_port_meter_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_set_port_meter_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_set_port_meter_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_result, profile_id, UINT32);
+cmdline_parse_token_string_t cmd_set_port_meter_g_action =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_port_meter_result,
+		g_action, "R#Y#G#D");
+cmdline_parse_token_string_t cmd_set_port_meter_y_action =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_port_meter_result,
+		y_action, "R#Y#G#D");
+cmdline_parse_token_string_t cmd_set_port_meter_r_action =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_port_meter_result,
+		r_action, "R#Y#G#D");
+cmdline_parse_token_num_t cmd_set_port_meter_statistics_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_port_meter_result,
+		statistics_mask, UINT64);
+cmdline_parse_token_num_t cmd_set_port_meter_shared =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_port_meter_result,
+		shared, UINT32);
+
+static void cmd_set_port_meter_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_port_meter_result *res = parsed_result;
+	struct rte_mtr_error error;
+	struct rte_mtr_params params;
+	uint32_t mtr_id = res->mtr_id;
+	uint32_t shared = res->shared;
+	uint16_t port_id = res->port_id;
+
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Meter params */
+	memset(&params, 0, sizeof(struct rte_mtr_params));
+	params.meter_profile_id = res->profile_id;
+	params.use_prev_mtr_color = 1;
+	params.dscp_table = NULL;
+	params.meter_enable = 1;
+	params.action[RTE_MTR_GREEN] =
+		string_to_policer_action(res->g_action);
+	params.action[RTE_MTR_YELLOW] =
+		string_to_policer_action(res->y_action);
+	params.action[RTE_MTR_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);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_port_meter = {
+	.f = cmd_set_port_meter_parsed,
+	.data = NULL,
+	.help_str = "Set port meter",
+	.tokens = {
+		(void *)&cmd_set_port_meter_set,
+		(void *)&cmd_set_port_meter_port,
+		(void *)&cmd_set_port_meter_meter,
+		(void *)&cmd_set_port_meter_port_id,
+		(void *)&cmd_set_port_meter_mtr_id,
+		(void *)&cmd_set_port_meter_profile_id,
+		(void *)&cmd_set_port_meter_g_action,
+		(void *)&cmd_set_port_meter_y_action,
+		(void *)&cmd_set_port_meter_r_action,
+		(void *)&cmd_set_port_meter_statistics_mask,
+		(void *)&cmd_set_port_meter_shared,
+		NULL,
+	},
+};
+
+/* *** Delete Port Meter Object *** */
+struct cmd_del_port_meter_result {
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	uint16_t port_id;
+	uint32_t mtr_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_meter_del =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_meter_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_result, port, "port");
+cmdline_parse_token_string_t cmd_del_port_meter_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_del_port_meter_result, meter, "meter");
+cmdline_parse_token_num_t cmd_del_port_meter_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_del_port_meter_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_del_port_meter_result, mtr_id, UINT32);
+
+static void cmd_del_port_meter_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_del_port_meter_result *res = parsed_result;
+	struct rte_mtr_error error;
+	uint32_t mtr_id = res->mtr_id;
+	uint16_t port_id = res->port_id;
+
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Destroy Meter */
+	ret = rte_mtr_destroy(port_id, mtr_id, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_del_port_meter = {
+	.f = cmd_del_port_meter_parsed,
+	.data = NULL,
+	.help_str = "Delete port meter",
+	.tokens = {
+		(void *)&cmd_del_port_meter_del,
+		(void *)&cmd_del_port_meter_port,
+		(void *)&cmd_del_port_meter_meter,
+		(void *)&cmd_del_port_meter_port_id,
+		(void *)&cmd_del_port_meter_mtr_id,
+		NULL,
+	},
+};
+
+/* *** Set Port Meter Profile *** */
+struct cmd_set_port_meter_profile_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t profile;
+	uint16_t port_id;
+	uint32_t mtr_id;
+	uint32_t profile_id;
+};
+
+cmdline_parse_token_string_t cmd_set_port_meter_profile_set =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_meter_profile_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_meter_profile_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, meter, "meter");
+cmdline_parse_token_string_t cmd_set_port_meter_profile_profile =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, profile, "profile");
+cmdline_parse_token_num_t cmd_set_port_meter_profile_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_set_port_meter_profile_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_set_port_meter_profile_profile_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_profile_result, profile_id, UINT32);
+
+static void cmd_set_port_meter_profile_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_port_meter_profile_result *res = parsed_result;
+	struct rte_mtr_error error;
+	uint32_t mtr_id = res->mtr_id;
+	uint32_t profile_id = res->profile_id;
+	uint16_t port_id = res->port_id;
+
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Set meter profile */
+	ret = rte_mtr_meter_profile_update(port_id, mtr_id,
+		profile_id, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_port_meter_profile = {
+	.f = cmd_set_port_meter_profile_parsed,
+	.data = NULL,
+	.help_str = "Set port meter profile",
+	.tokens = {
+		(void *)&cmd_set_port_meter_profile_set,
+		(void *)&cmd_set_port_meter_profile_port,
+		(void *)&cmd_set_port_meter_profile_meter,
+		(void *)&cmd_set_port_meter_profile_profile,
+		(void *)&cmd_set_port_meter_profile_port_id,
+		(void *)&cmd_set_port_meter_profile_mtr_id,
+		(void *)&cmd_set_port_meter_profile_profile_id,
+		NULL,
+	},
+};
+
+/* *** 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;
+	cmdline_fixed_string_t color;
+	cmdline_fixed_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,
+		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,
+		UINT32);
+cmdline_parse_token_string_t cmd_set_port_meter_policer_action_color =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_policer_action_result, color,
+		"G#Y#R");
+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, "G#Y#R#D");
+
+static void cmd_set_port_meter_policer_action_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_port_meter_policer_action_result *res = parsed_result;
+	enum rte_mtr_color color;
+	enum rte_mtr_policer_action action[RTE_MTR_COLORS];
+	struct rte_mtr_error error;
+	uint32_t mtr_id = res->mtr_id;
+	uint16_t port_id = res->port_id;
+	char *c = res->color;
+	char *a = res->policer_action;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	/* Color */
+	if (strcmp(c, "G") == 0)
+		color = RTE_MTR_GREEN;
+	else if (strcmp(c, "Y") == 0)
+		color = RTE_MTR_YELLOW;
+	else if (strcmp(c, "Y") == 0)
+		color = RTE_MTR_RED;
+	else
+		color = RTE_MTR_COLORS;
+
+	/* Action */
+	if (strcmp(a, "G") == 0)
+		action[color] = MTR_POLICER_ACTION_COLOR_GREEN;
+	else if (strcmp(a, "Y") == 0)
+		action[color] = MTR_POLICER_ACTION_COLOR_YELLOW;
+	else if (strcmp(a, "Y") == 0)
+		action[color] = MTR_POLICER_ACTION_COLOR_RED;
+	else
+		action[color] = MTR_POLICER_ACTION_DROP;
+
+	ret = rte_mtr_policer_actions_update(port_id, mtr_id,
+		1 << color, action, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+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",
+	.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_color,
+		(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;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t stats;
+	cmdline_fixed_string_t mask;
+	uint16_t port_id;
+	uint32_t mtr_id;
+	uint64_t stats_mask;
+};
+
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_set =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, meter, "meter");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_stats =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, stats, "stats");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_mask =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, mask, "mask");
+cmdline_parse_token_num_t cmd_set_port_meter_stats_mask_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_set_port_meter_stats_mask_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_set_port_meter_stats_mask_stats_mask =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_set_port_meter_stats_mask_result, stats_mask,
+		UINT64);
+
+static void cmd_set_port_meter_stats_mask_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_set_port_meter_stats_mask_result *res = parsed_result;
+	struct rte_mtr_error error;
+	uint64_t stats_mask = res->stats_mask;
+	uint32_t mtr_id = res->mtr_id;
+	uint16_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	ret = rte_mtr_stats_update(port_id, mtr_id, stats_mask, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+}
+
+cmdline_parse_inst_t cmd_set_port_meter_stats_mask = {
+	.f = cmd_set_port_meter_stats_mask_parsed,
+	.data = NULL,
+	.help_str = "Set port meter stats mask",
+	.tokens = {
+		(void *)&cmd_set_port_meter_stats_mask_set,
+		(void *)&cmd_set_port_meter_stats_mask_port,
+		(void *)&cmd_set_port_meter_stats_mask_meter,
+		(void *)&cmd_set_port_meter_stats_mask_stats,
+		(void *)&cmd_set_port_meter_stats_mask_mask,
+		(void *)&cmd_set_port_meter_stats_mask_port_id,
+		(void *)&cmd_set_port_meter_stats_mask_mtr_id,
+		(void *)&cmd_set_port_meter_stats_mask_stats_mask,
+		NULL,
+	},
+};
+
+/* *** Show Port Meter Stats *** */
+struct cmd_show_port_meter_stats_result {
+	cmdline_fixed_string_t show;
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t meter;
+	cmdline_fixed_string_t stats;
+	uint16_t port_id;
+	uint32_t mtr_id;
+	uint32_t clear;
+};
+
+cmdline_parse_token_string_t cmd_show_port_meter_stats_show =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, show, "show");
+cmdline_parse_token_string_t cmd_show_port_meter_stats_port =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, port, "port");
+cmdline_parse_token_string_t cmd_show_port_meter_stats_meter =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, meter, "meter");
+cmdline_parse_token_string_t cmd_show_port_meter_stats_stats =
+	TOKEN_STRING_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, stats, "stats");
+cmdline_parse_token_num_t cmd_show_port_meter_stats_port_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_show_port_meter_stats_mtr_id =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_show_port_meter_stats_clear =
+	TOKEN_NUM_INITIALIZER(
+		struct cmd_show_port_meter_stats_result, clear, UINT32);
+
+static void cmd_show_port_meter_stats_parsed(void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_show_port_meter_stats_result *res = parsed_result;
+	struct rte_mtr_stats stats;
+	uint64_t stats_mask = 0;
+	struct rte_mtr_error error;
+	uint32_t mtr_id = res->mtr_id;
+	uint32_t clear = res->clear;
+	uint16_t port_id = res->port_id;
+	int ret;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	memset(&stats, 0, sizeof(struct rte_mtr_stats));
+	ret = rte_mtr_stats_read(port_id, mtr_id, &stats,
+		&stats_mask, clear, &error);
+	if (ret != 0) {
+		print_err_msg(&error);
+		return;
+	}
+
+	/* Display stats */
+	if (stats_mask & RTE_MTR_STATS_N_PKTS_GREEN)
+		printf("\tPkts G: %" PRIu64 "\n",
+			stats.n_pkts[RTE_MTR_GREEN]);
+	if (stats_mask & RTE_MTR_STATS_N_BYTES_GREEN)
+		printf("\tBytes G: %" PRIu64 "\n",
+			stats.n_bytes[RTE_MTR_GREEN]);
+	if (stats_mask & RTE_MTR_STATS_N_PKTS_YELLOW)
+		printf("\tPkts Y: %" PRIu64 "\n",
+			stats.n_pkts[RTE_MTR_YELLOW]);
+	if (stats_mask & RTE_MTR_STATS_N_BYTES_YELLOW)
+		printf("\tBytes Y: %" PRIu64 "\n",
+			stats.n_bytes[RTE_MTR_YELLOW]);
+	if (stats_mask & RTE_MTR_STATS_N_PKTS_RED)
+		printf("\tPkts R: %" PRIu64 "\n",
+			stats.n_pkts[RTE_MTR_RED]);
+	if (stats_mask & RTE_MTR_STATS_N_BYTES_RED)
+		printf("\tBytes Y: %" PRIu64 "\n",
+			stats.n_bytes[RTE_MTR_RED]);
+	if (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED)
+		printf("\tPkts DROPPED: %" PRIu64 "\n",
+			stats.n_pkts_dropped);
+	if (stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED)
+		printf("\tBytes DROPPED: %" PRIu64 "\n",
+			stats.n_bytes_dropped);
+}
+
+cmdline_parse_inst_t cmd_show_port_meter_stats = {
+	.f = cmd_show_port_meter_stats_parsed,
+	.data = NULL,
+	.help_str = "Show port meter stats",
+	.tokens = {
+		(void *)&cmd_show_port_meter_stats_show,
+		(void *)&cmd_show_port_meter_stats_port,
+		(void *)&cmd_show_port_meter_stats_meter,
+		(void *)&cmd_show_port_meter_stats_stats,
+		(void *)&cmd_show_port_meter_stats_port_id,
+		(void *)&cmd_show_port_meter_stats_mtr_id,
+		(void *)&cmd_show_port_meter_stats_clear,
+		NULL,
+	},
+};
diff --git a/app/test-pmd/cmdline_mtr.h b/app/test-pmd/cmdline_mtr.h
new file mode 100644
index 0000000..5d599ef
--- /dev/null
+++ b/app/test-pmd/cmdline_mtr.h
@@ -0,0 +1,49 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CMDLINE_MTR_H_
+#define _CMDLINE_MTR_H_
+
+/* Traffic Metering and Policing */
+extern cmdline_parse_inst_t cmd_add_port_meter_profile_srtcm;
+extern cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm;
+extern cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm_rfc4115;
+extern cmdline_parse_inst_t cmd_del_port_meter_profile;
+extern cmdline_parse_inst_t cmd_set_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_policer_action;
+extern cmdline_parse_inst_t cmd_set_port_meter_stats_mask;
+extern cmdline_parse_inst_t cmd_show_port_meter_stats;
+
+#endif /* _CMDLINE_MTR_H_ */
-- 
2.7.4

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

* Re: [PATCH V3 4/5] doc: ethdev traffic metering and policing api
  2017-10-12 14:59               ` Mcnamara, John
@ 2017-10-13 12:26                 ` Dumitrescu, Cristian
  0 siblings, 0 replies; 64+ messages in thread
From: Dumitrescu, Cristian @ 2017-10-13 12:26 UTC (permalink / raw)
  To: Mcnamara, John, dev
  Cc: thomas, adrien.mazarguil, Wu, Jingjing, hemant.agrawal,
	jerin.jacob, Singh, Jasvinder



> -----Original Message-----
> From: Mcnamara, John
> Sent: Thursday, October 12, 2017 3:59 PM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; dev@dpdk.org
> Cc: thomas@monjalon.net; adrien.mazarguil@6wind.com; Wu, Jingjing
> <jingjing.wu@intel.com>; hemant.agrawal@nxp.com;
> jerin.jacob@caviumnetworks.com; Singh, Jasvinder
> <jasvinder.singh@intel.com>
> Subject: RE: [dpdk-dev] [PATCH V3 4/5] doc: ethdev traffic metering and
> policing api
> 
> 
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Cristian
> Dumitrescu
> > Sent: Friday, October 6, 2017 3:46 PM
> > To: dev@dpdk.org
> > Cc: thomas@monjalon.net; adrien.mazarguil@6wind.com; Wu, Jingjing
> > <jingjing.wu@intel.com>; hemant.agrawal@nxp.com;
> > jerin.jacob@caviumnetworks.com; Singh, Jasvinder
> > <jasvinder.singh@intel.com>
> > Subject: [dpdk-dev] [PATCH V3 4/5] doc: ethdev traffic metering and
> > policing api
> >
> > Add new section in the Programmer Guide for the ethdev traffic metering
> > and policing (MTR) API.
> >
> > Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> 
> 
> Thanks for the well written doc. Some comments below.
> 
> 
> > ---
> > +Traffic Metering and Policing (MTR) API
> > +=======================================
> 
> Leave out the acronym from the title. It is explained in the overview.
> 
> > +The processing done for each input packet hitting an MTR object is:
> > +* Traffic metering: The packet is assigned a color (the meter output
> > +  color) based on the previous traffic history reflected in the
> > +  current state of the MTR object, according to the specific traffic
> > +  metering algorithm. The traffic metering algorithm can typically work
> > +  in color aware mode, in which case the input packet already has an
> > +  initial color (the input color), or in 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
> 
> This section throws several doc build errors. Bullet lists need to have
> a blank line before them and the second level indentation isn't correct here.
> 
> It should be something like this:
> 
> 
> The processing done for each input packet hitting an MTR object is:
> 
> * Traffic metering: The packet is assigned a color (the meter output color)
>   based on the previous traffic history reflected in the current state of the
>   MTR object, according to the specific traffic metering algorithm. The
>   traffic metering algorithm can typically work in color aware mode, in which
>   case the input packet already has an initial color (the input color), or in
>   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``).
> 
> * Statistics: The set of counters maintained for each MTR object is
>   configurable and subject to the implementation support. This set includes
>   the number of packets and bytes dropped or passed for each output color.
> 
> 

Thanks, John, incorporated in V4 just sent.

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

* Re: [PATCH V3 3/5] ethdev: add new api for traffic metering and policing
  2017-10-12 10:48               ` Hemant Agrawal
  2017-10-12 10:54                 ` Hemant Agrawal
@ 2017-10-13 12:29                 ` Dumitrescu, Cristian
  1 sibling, 0 replies; 64+ messages in thread
From: Dumitrescu, Cristian @ 2017-10-13 12:29 UTC (permalink / raw)
  To: Hemant Agrawal, dev
  Cc: thomas, adrien.mazarguil, Wu, Jingjing, jerin.jacob, Singh, Jasvinder



> -----Original Message-----
> From: Hemant Agrawal [mailto:hemant.agrawal@nxp.com]
> Sent: Thursday, October 12, 2017 11:49 AM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; dev@dpdk.org
> Cc: thomas@monjalon.net; adrien.mazarguil@6wind.com; Wu, Jingjing
> <jingjing.wu@intel.com>; jerin.jacob@caviumnetworks.com; Singh,
> Jasvinder <jasvinder.singh@intel.com>
> Subject: Re: [PATCH V3 3/5] ethdev: add new api for traffic metering and
> policing
> 
> On 10/6/2017 8:15 PM, Cristian Dumitrescu wrote:
> 
> Overall the patch looks ok. Few small comments.
> 
> > diff --git a/lib/librte_ether/rte_mtr.h b/lib/librte_ether/rte_mtr.h
> > new file mode 100644
> > index 0000000..f0f897f
> > --- /dev/null
> > +++ b/lib/librte_ether/rte_mtr.h
> > @@ -0,0 +1,723 @@
> > +/*-
> > + *   BSD LICENSE
> > + *
> > + *   Copyright(c) 2017 Intel Corporation.
> > + *   Copyright(c) 2017 NXP.
> 
> can you make it "Copyright 2017 NXP"
> > + *   Copyright(c) 2017 Cavium.
> > + *   All rights reserved.
> > + *
> 

Done as suggested in V4 just sent.

> <snip>...
> 
> > +/**
> > + * Statistics counter type
> > + */
> > +enum rte_mtr_stats_type {
> > +	/** Number of packets passed as green by the policer. */
> > +	RTE_MTR_STATS_N_PKTS_GREEN = 1 << 0,
> > +
> > +	/** Number of bytes passed as green by the policer. */
> > +	RTE_MTR_STATS_N_BYTES_GREEN = 1 << 1,
> > +
> > +	/** Number of packets passed as yellow by the policer. */
> > +	RTE_MTR_STATS_N_PKTS_YELLOW = 1 << 2,
> > +
> > +	/** Number of bytes passed as yellow by the policer. */
> > +	RTE_MTR_STATS_N_BYTES_YELLOW = 1 << 3,
> > +
> > +	/** Number of packets passed as red by the policer. */
> > +	RTE_MTR_STATS_N_PKTS_RED = 1 << 4,
> > +
> > +	/** Number of bytes passed as red by the policer. */
> > +	RTE_MTR_STATS_N_BYTES_RED = 1 << 5,
> > +
> > +	/** Number of packets dropped by the policer. */
> > +	RTE_MTR_STATS_N_PKTS_DROPPED = 1 << 6,
> > +
> > +	/** Number of bytes dropped by the policer. */
> > +	RTE_MTR_STATS_N_BYTES_DROPPED = 1 << 7,
> 
> Trivial one.
> do you want to group the pkts and bytes in separate group respectively?
> 

Done as suggested in V4 just sent.

> > +};
> > +
> > +/**
> > + * Statistics counters
> > + */
> > +struct rte_mtr_stats {
> > +	/** Number of packets passed by the policer (per color). */
> > +	uint64_t n_pkts[RTE_MTR_COLORS];
> > +
> > +	/** Number of bytes passed by the policer (per color). */
> > +	uint64_t n_bytes[RTE_MTR_COLORS];
> > +
> > +	/** Number of packets dropped by the policer. */
> > +	uint64_t n_pkts_dropped;
> > +
> > +	/** Number of bytes passed by the policer. */
> > +	uint64_t n_bytes_dropped;
> > +};
> > +
> > +/**
> > + * Traffic metering algorithms
> > + */
> > +enum rte_mtr_algorithm {
> > +	/** Single Rate Three Color Marker (srTCM) - IETF RFC 2697. */
> > +	RTE_MTR_SRTCM_RFC2697,
> > +
> > +	/** Two Rate Three Color Marker (trTCM) - IETF RFC 2698. */
> > +	RTE_MTR_TRTCM_RFC2698,
> > +
> > +	/** Two Rate Three Color Marker (trTCM) - IETF RFC 4115. */
> > +	RTE_MTR_TRTCM_RFC4115,
> 
> I will still prefer if you still add "PASS_THROUGH" as explicit algo.
> 

Done as suggested in V4 just sent.

> > +};
> > +
> > +/**
> > + * Meter profile
> > + */
> 


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

* Re: [PATCH V3 5/5] app/testpmd: cli for traffic metering and policing
  2017-10-13  6:32               ` Wu, Jingjing
@ 2017-10-13 12:30                 ` Dumitrescu, Cristian
  0 siblings, 0 replies; 64+ messages in thread
From: Dumitrescu, Cristian @ 2017-10-13 12:30 UTC (permalink / raw)
  To: Wu, Jingjing, dev
  Cc: thomas, adrien.mazarguil, hemant.agrawal, jerin.jacob, Singh, Jasvinder



> -----Original Message-----
> From: Wu, Jingjing
> Sent: Friday, October 13, 2017 7:32 AM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; dev@dpdk.org
> Cc: thomas@monjalon.net; adrien.mazarguil@6wind.com;
> hemant.agrawal@nxp.com; jerin.jacob@caviumnetworks.com; Singh,
> Jasvinder <jasvinder.singh@intel.com>
> Subject: RE: [PATCH V3 5/5] app/testpmd: cli for traffic metering and policing
> 
> 
> 
> > -----Original Message-----
> > From: Dumitrescu, Cristian
> > Sent: Friday, October 6, 2017 10:46 PM
> > To: dev@dpdk.org
> > Cc: thomas@monjalon.net; adrien.mazarguil@6wind.com; Wu, Jingjing
> > <jingjing.wu@intel.com>; hemant.agrawal@nxp.com;
> > jerin.jacob@caviumnetworks.com; Singh, Jasvinder
> <jasvinder.singh@intel.com>
> > Subject: [PATCH V3 5/5] app/testpmd: cli for traffic metering and policing
> >
> > Add CLI commands to exercise the ethdev Traffic Metering and Policing
> > (MTR) API.
> >
> > Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
> > Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> > Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
> > ---
> > Changes in v3:
> > - Added newline at the end of cmdline_mtr.h
> >
> >  app/test-pmd/Makefile       |    1 +
> >  app/test-pmd/cmdline.c      |   10 +
> >  app/test-pmd/cmdline_flow.c |   24 +
> >  app/test-pmd/cmdline_mtr.c  | 1013
> > +++++++++++++++++++++++++++++++++++++++++++
> >  app/test-pmd/cmdline_mtr.h  |   49 +++
> >  5 files changed, 1097 insertions(+)
> >  create mode 100644 app/test-pmd/cmdline_mtr.c  create mode 100644
> > app/test-pmd/cmdline_mtr.h
> >
> > diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile index
> > c36be19..8fb6491 100644
> > --- a/app/test-pmd/Makefile
> > +++ b/app/test-pmd/Makefile
> > @@ -48,6 +48,7 @@ SRCS-y := testpmd.c
> >  SRCS-y += parameters.c
> >  SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline.c
> >  SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_flow.c
> > +SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_mtr.c
> >  SRCS-y += config.c
> >  SRCS-y += iofwd.c
> >  SRCS-y += macfwd.c
> > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> > ccdf239..8338b5c 100644
> > --- a/app/test-pmd/cmdline.c
> > +++ b/app/test-pmd/cmdline.c
> > @@ -99,6 +99,7 @@
> >  #include <rte_pmd_bnxt.h>
> >  #endif
> >  #include "testpmd.h"
> > +#include "cmdline_mtr.h"
> >
> >  static struct cmdline *testpmd_cl;
> >
> > @@ -14334,6 +14335,15 @@ cmdline_parse_ctx_t main_ctx[] = {
> >  	(cmdline_parse_inst_t *)&cmd_set_hash_input_set,
> >  	(cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
> >  	(cmdline_parse_inst_t *)&cmd_flow,
> > +	(cmdline_parse_inst_t *)&cmd_add_port_meter_profile_srtcm,
> > +	(cmdline_parse_inst_t *)&cmd_add_port_meter_profile_trtcm,
> > +	(cmdline_parse_inst_t *)&cmd_del_port_meter_profile,
> > +	(cmdline_parse_inst_t *)&cmd_set_port_meter,
> > +	(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_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,
> >  	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
> >  	(cmdline_parse_inst_t
> *)&cmd_config_l2_tunnel_eth_type_specific,
> 
> You need to add the command description in cmd_help_long_parsed.
> And doc for new commands.
> 

Done in V4 just sent.

> [......]
> 
> > +cmdline_parse_token_num_t
> cmd_add_port_meter_profile_srtcm_port_id =
> > +	TOKEN_NUM_INITIALIZER(
> > +		struct cmd_add_port_meter_profile_srtcm_result,
> > +			port_id, UINT8);
> 
> Would you update the UINT8 to UINT16?  The same to all the port_id.
> 

Done in V4 just sent.

> 
> Thanks
> Jingjing

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

* Re: [PATCH V4 4/5] doc: ethdev traffic metering and policing api
  2017-10-13 12:22                 ` [PATCH V4 4/5] doc: ethdev traffic metering and policing api Cristian Dumitrescu
@ 2017-10-13 15:43                   ` Mcnamara, John
  0 siblings, 0 replies; 64+ messages in thread
From: Mcnamara, John @ 2017-10-13 15:43 UTC (permalink / raw)
  To: Dumitrescu, Cristian, dev
  Cc: thomas, adrien.mazarguil, Wu, Jingjing, hemant.agrawal,
	jerin.jacob, Singh, Jasvinder



> -----Original Message-----
> From: Dumitrescu, Cristian
> Sent: Friday, October 13, 2017 1:22 PM
> To: dev@dpdk.org
> Cc: thomas@monjalon.net; adrien.mazarguil@6wind.com; Wu, Jingjing
> <jingjing.wu@intel.com>; Mcnamara, John <john.mcnamara@intel.com>;
> hemant.agrawal@nxp.com; jerin.jacob@caviumnetworks.com; Singh, Jasvinder
> <jasvinder.singh@intel.com>
> Subject: [PATCH V4 4/5] doc: ethdev traffic metering and policing api
> 
> Add new section in the Programmer Guide for the ethdev traffic metering
> and policing (MTR) API.
> 
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>


Acked-by: John McNamara <john.mcnamara@intel.com>

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

* Re: [PATCH V4 5/5] app/testpmd: cli for traffic metering and policing
  2017-10-13 12:22                 ` [PATCH V4 5/5] app/testpmd: cli for traffic metering and policing Cristian Dumitrescu
@ 2017-10-16  9:49                   ` Wu, Jingjing
  2017-10-16 10:10                     ` Wu, Jingjing
  0 siblings, 1 reply; 64+ messages in thread
From: Wu, Jingjing @ 2017-10-16  9:49 UTC (permalink / raw)
  To: Dumitrescu, Cristian, dev
  Cc: thomas, adrien.mazarguil, Mcnamara, John, hemant.agrawal,
	jerin.jacob, Singh, Jasvinder



> -----Original Message-----
> From: Dumitrescu, Cristian
> Sent: Friday, October 13, 2017 8:22 PM
> To: dev@dpdk.org
> Cc: thomas@monjalon.net; adrien.mazarguil@6wind.com; Wu, Jingjing
> <jingjing.wu@intel.com>; Mcnamara, John <john.mcnamara@intel.com>;
> hemant.agrawal@nxp.com; jerin.jacob@caviumnetworks.com; Singh, Jasvinder
> <jasvinder.singh@intel.com>
> Subject: [PATCH V4 5/5] app/testpmd: cli for traffic metering and policing
> 
> Add CLI commands to exercise the ethdev Traffic Metering and Policing
> (MTR) API.
> 
> Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
> Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>


Reviewed-by: Jingjing Wu <jingjing.wu@intel.com>

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

* Re: [PATCH V4 5/5] app/testpmd: cli for traffic metering and policing
  2017-10-16  9:49                   ` Wu, Jingjing
@ 2017-10-16 10:10                     ` Wu, Jingjing
  0 siblings, 0 replies; 64+ messages in thread
From: Wu, Jingjing @ 2017-10-16 10:10 UTC (permalink / raw)
  To: Wu, Jingjing, Dumitrescu, Cristian, dev
  Cc: thomas, adrien.mazarguil, Mcnamara, John, hemant.agrawal,
	jerin.jacob, Singh, Jasvinder



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wu, Jingjing
> Sent: Monday, October 16, 2017 5:50 PM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; dev@dpdk.org
> Cc: thomas@monjalon.net; adrien.mazarguil@6wind.com; Mcnamara, John
> <john.mcnamara@intel.com>; hemant.agrawal@nxp.com;
> jerin.jacob@caviumnetworks.com; Singh, Jasvinder <jasvinder.singh@intel.com>
> Subject: Re: [dpdk-dev] [PATCH V4 5/5] app/testpmd: cli for traffic metering
> and policing
> 
> 
> 
> > -----Original Message-----
> > From: Dumitrescu, Cristian
> > Sent: Friday, October 13, 2017 8:22 PM
> > To: dev@dpdk.org
> > Cc: thomas@monjalon.net; adrien.mazarguil@6wind.com; Wu, Jingjing
> > <jingjing.wu@intel.com>; Mcnamara, John <john.mcnamara@intel.com>;
> > hemant.agrawal@nxp.com; jerin.jacob@caviumnetworks.com; Singh,
> > Jasvinder <jasvinder.singh@intel.com>
> > Subject: [PATCH V4 5/5] app/testpmd: cli for traffic metering and
> > policing
> >
> > Add CLI commands to exercise the ethdev Traffic Metering and Policing
> > (MTR) API.
> >
> > Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
> > Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> > Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>

Acked-by: Jingjing Wu <jingjing.wu@intel.com>

Replaced the Reviewed-by 

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

* Re: [PATCH V4 3/5] ethdev: add new api for traffic metering and policing
  2017-10-13 12:22                 ` [PATCH V4 3/5] ethdev: add new api for traffic metering and policing Cristian Dumitrescu
@ 2017-10-17 12:39                   ` Hemant Agrawal
  2017-10-18  2:58                   ` Jerin Jacob
  1 sibling, 0 replies; 64+ messages in thread
From: Hemant Agrawal @ 2017-10-17 12:39 UTC (permalink / raw)
  To: Cristian Dumitrescu, dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, john.mcnamara,
	jerin.jacob, jasvinder.singh

On 10/13/2017 5:52 PM, Cristian Dumitrescu wrote:
> This patch introduces new ethdev generic API for Traffic Metering and
> Policing (MTR), which is yet another standard RX offload for Ethernet
> devices.
>
> Similar to rte_flow and rte_tm APIs, the configuration of MTR objects is
> done in their own namespace (rte_mtr) within the librte_ether library.
>
> Main features:
> 1. Traffic metering: determine the color for the current packet (green,
>    yellow, red) based on history maintained by the MTR object. Supported
>    algorithms: srTCM (RFC 2697), trTCM (RFC 2698 and RFC 4115).
> 2. Policing (per meter output color actions): re-color the packet (keep
>    or change the meter output color) or drop the packet.
> 3. Statistics
> 4. Capability API
>
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>

Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>

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

* Re: [PATCH V4 2/5] ethdev: add new eth_dev_ops function for mtr ops get
  2017-10-13 12:22                 ` [PATCH V4 2/5] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
@ 2017-10-17 12:40                   ` Hemant Agrawal
  0 siblings, 0 replies; 64+ messages in thread
From: Hemant Agrawal @ 2017-10-17 12:40 UTC (permalink / raw)
  To: Cristian Dumitrescu, dev
  Cc: thomas, adrien.mazarguil, jingjing.wu, john.mcnamara,
	jerin.jacob, jasvinder.singh

On 10/13/2017 5:52 PM, Cristian Dumitrescu wrote:
> Following similar approach as rte_flow and rte_tm for modularity reasons,
> the ops for the new rte_mtr API are retrieved through a new eth_dev_ops
> function.
>
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>

Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>

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

* Re: [PATCH V4 1/5] ethdev: add new flow action for metering and policing
  2017-10-13 12:22                 ` [PATCH V4 1/5] ethdev: add new flow action " Cristian Dumitrescu
@ 2017-10-18  2:55                   ` Jerin Jacob
  0 siblings, 0 replies; 64+ messages in thread
From: Jerin Jacob @ 2017-10-18  2:55 UTC (permalink / raw)
  To: Cristian Dumitrescu
  Cc: dev, thomas, adrien.mazarguil, jingjing.wu, john.mcnamara,
	hemant.agrawal, jasvinder.singh

-----Original Message-----
> Date: Fri, 13 Oct 2017 13:22:14 +0100
> From: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> To: dev@dpdk.org
> CC: thomas@monjalon.net, adrien.mazarguil@6wind.com, jingjing.wu@intel.com,
>  john.mcnamara@intel.com, hemant.agrawal@nxp.com,
>  jerin.jacob@caviumnetworks.com, jasvinder.singh@intel.com
> Subject: [PATCH V4 1/5] ethdev: add new flow action for metering and
>  policing
> X-Mailer: git-send-email 2.7.4
> 
> Metering and policing action typically sits on top of flow classification,
> which is why MTR objects are enabled through a newly introduced flow
> action.
> 
> The configuration of MTR objects is done in their own namespace (rte_mtr)
> within the librte_ether library. The MTR object is hooked into ethdev RX
> processing path using the "meter" flow action.
> 
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>

Acked-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>

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

* Re: [PATCH V4 3/5] ethdev: add new api for traffic metering and policing
  2017-10-13 12:22                 ` [PATCH V4 3/5] ethdev: add new api for traffic metering and policing Cristian Dumitrescu
  2017-10-17 12:39                   ` Hemant Agrawal
@ 2017-10-18  2:58                   ` Jerin Jacob
  1 sibling, 0 replies; 64+ messages in thread
From: Jerin Jacob @ 2017-10-18  2:58 UTC (permalink / raw)
  To: Cristian Dumitrescu
  Cc: dev, thomas, adrien.mazarguil, jingjing.wu, john.mcnamara,
	hemant.agrawal, jasvinder.singh

-----Original Message-----
> Date: Fri, 13 Oct 2017 13:22:16 +0100
> From: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> To: dev@dpdk.org
> CC: thomas@monjalon.net, adrien.mazarguil@6wind.com, jingjing.wu@intel.com,
>  john.mcnamara@intel.com, hemant.agrawal@nxp.com,
>  jerin.jacob@caviumnetworks.com, jasvinder.singh@intel.com
> Subject: [PATCH V4 3/5] ethdev: add new api for traffic metering and
>  policing
> X-Mailer: git-send-email 2.7.4
> 
> This patch introduces new ethdev generic API for Traffic Metering and
> Policing (MTR), which is yet another standard RX offload for Ethernet
> devices.
> 
> Similar to rte_flow and rte_tm APIs, the configuration of MTR objects is
> done in their own namespace (rte_mtr) within the librte_ether library.
> 
> Main features:
> 1. Traffic metering: determine the color for the current packet (green,
>    yellow, red) based on history maintained by the MTR object. Supported
>    algorithms: srTCM (RFC 2697), trTCM (RFC 2698 and RFC 4115).
> 2. Policing (per meter output color actions): re-color the packet (keep
>    or change the meter output color) or drop the packet.
> 3. Statistics
> 4. Capability API
> 
> Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>

Acked-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>

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

* Re: [PATCH V4 0/5] rte_mtr: generic ethdev api for metering and policing
  2017-10-13 12:22               ` [PATCH V4 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
                                   ` (4 preceding siblings ...)
  2017-10-13 12:22                 ` [PATCH V4 5/5] app/testpmd: cli for traffic metering and policing Cristian Dumitrescu
@ 2017-10-20 12:15                 ` Dumitrescu, Cristian
  5 siblings, 0 replies; 64+ messages in thread
From: Dumitrescu, Cristian @ 2017-10-20 12:15 UTC (permalink / raw)
  To: dev
  Cc: thomas, adrien.mazarguil, Wu, Jingjing, Mcnamara, John,
	hemant.agrawal, jerin.jacob, Singh, Jasvinder



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Cristian Dumitrescu
> Sent: Friday, October 13, 2017 1:22 PM
> To: dev@dpdk.org
> Cc: thomas@monjalon.net; adrien.mazarguil@6wind.com; Wu, Jingjing
> <jingjing.wu@intel.com>; Mcnamara, John <john.mcnamara@intel.com>;
> hemant.agrawal@nxp.com; jerin.jacob@caviumnetworks.com; Singh,
> Jasvinder <jasvinder.singh@intel.com>
> Subject: [dpdk-dev] [PATCH V4 0/5] rte_mtr: generic ethdev api for metering
> and policing
> 
> Metering and Policing (MTR), which is yet another standard RX offload for
> Ethernet devices.
> 

Applied to next-tm tree.

Many thanks to all the people that contributed to the development of this API, especially Adrien, Hemant and Jerin!

Regards,
Cristian

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

end of thread, other threads:[~2017-10-20 12:15 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-30 16:44 [RFC 0/3] rte_mtr: generic ethdev API for metering and policing Cristian Dumitrescu
2017-05-30 16:44 ` [RFC 1/3] ethdev: add traffic metering and policing ops get API Cristian Dumitrescu
2017-05-30 16:44 ` [RFC 2/3] ethdev: add new rte_mtr API for traffic metering and policing Cristian Dumitrescu
2017-08-26  0:06   ` [PATCH 0/3] rte_mtr: generic ethdev API for " Cristian Dumitrescu
2017-08-26  0:06     ` [PATCH 1/3] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
2017-09-13  5:50       ` Jerin Jacob
2017-09-19 15:52         ` Dumitrescu, Cristian
2017-10-05 13:09       ` [PATCH V2 0/5] rte_mtr: generic ethdev api for metering and policing Cristian Dumitrescu
2017-10-05 13:09         ` [PATCH V2 1/5] ethdev: add new flow action " Cristian Dumitrescu
2017-10-06 13:57           ` Adrien Mazarguil
2017-10-06 14:50             ` Dumitrescu, Cristian
2017-10-06 14:45           ` [PATCH V3 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
2017-10-06 14:45             ` [PATCH V3 1/5] ethdev: add new flow action " Cristian Dumitrescu
2017-10-06 14:55               ` Adrien Mazarguil
2017-10-13 12:22               ` [PATCH V4 0/5] rte_mtr: generic ethdev api " Cristian Dumitrescu
2017-10-13 12:22                 ` [PATCH V4 1/5] ethdev: add new flow action " Cristian Dumitrescu
2017-10-18  2:55                   ` Jerin Jacob
2017-10-13 12:22                 ` [PATCH V4 2/5] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
2017-10-17 12:40                   ` Hemant Agrawal
2017-10-13 12:22                 ` [PATCH V4 3/5] ethdev: add new api for traffic metering and policing Cristian Dumitrescu
2017-10-17 12:39                   ` Hemant Agrawal
2017-10-18  2:58                   ` Jerin Jacob
2017-10-13 12:22                 ` [PATCH V4 4/5] doc: ethdev traffic metering and policing api Cristian Dumitrescu
2017-10-13 15:43                   ` Mcnamara, John
2017-10-13 12:22                 ` [PATCH V4 5/5] app/testpmd: cli for traffic metering and policing Cristian Dumitrescu
2017-10-16  9:49                   ` Wu, Jingjing
2017-10-16 10:10                     ` Wu, Jingjing
2017-10-20 12:15                 ` [PATCH V4 0/5] rte_mtr: generic ethdev api for " Dumitrescu, Cristian
2017-10-06 14:45             ` [PATCH V3 2/5] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
2017-10-12 10:58               ` Hemant Agrawal
2017-10-06 14:45             ` [PATCH V3 3/5] ethdev: add new api for traffic metering and policing Cristian Dumitrescu
2017-10-12 10:48               ` Hemant Agrawal
2017-10-12 10:54                 ` Hemant Agrawal
2017-10-13 12:29                 ` Dumitrescu, Cristian
2017-10-06 14:45             ` [PATCH V3 4/5] doc: ethdev traffic metering and policing api Cristian Dumitrescu
2017-10-12 14:59               ` Mcnamara, John
2017-10-13 12:26                 ` Dumitrescu, Cristian
2017-10-12 15:01               ` Mcnamara, John
2017-10-06 14:45             ` [PATCH V3 5/5] app/testpmd: cli for traffic metering and policing Cristian Dumitrescu
2017-10-13  6:32               ` Wu, Jingjing
2017-10-13 12:30                 ` Dumitrescu, Cristian
2017-10-05 13:09         ` [PATCH V2 2/5] ethdev: add new eth_dev_ops function for mtr ops get Cristian Dumitrescu
2017-10-05 13:09         ` [PATCH V2 3/5] ethdev: add new api for traffic metering and policing Cristian Dumitrescu
2017-10-05 13:09         ` [PATCH V2 4/5] doc: ethdev traffic metering and policing api Cristian Dumitrescu
2017-10-05 13:09         ` [PATCH V2 5/5] app/testpmd: cli for traffic metering and policing Cristian Dumitrescu
2017-10-06 13:58           ` Adrien Mazarguil
2017-08-26  0:06     ` [PATCH 2/3] ethdev: add new rte_mtr API " Cristian Dumitrescu
2017-09-01  8:09       ` Hemant Agrawal
2017-09-04 14:32         ` Dumitrescu, Cristian
2017-09-06  9:15           ` Hemant Agrawal
2017-09-19 16:14             ` Dumitrescu, Cristian
2017-09-21 13:20       ` Thomas Monjalon
2017-10-06 10:03         ` Dumitrescu, Cristian
2017-08-26  0:06     ` [PATCH 3/3] rte_flow: add new action " Cristian Dumitrescu
2017-09-06 16:23       ` Adrien Mazarguil
2017-09-19 16:36         ` Dumitrescu, Cristian
2017-09-19 17:00           ` Adrien Mazarguil
2017-10-06 10:02             ` Dumitrescu, Cristian
2017-09-21 13:28     ` [PATCH 0/3] rte_mtr: generic ethdev API for " Thomas Monjalon
2017-05-30 16:44 ` [RFC 3/3] rte_flow: add new action for traffic " Cristian Dumitrescu
2017-06-01 15:13   ` Adrien Mazarguil
2017-06-06 18:37     ` Dumitrescu, Cristian
2017-07-10 15:21       ` Adrien Mazarguil
2017-07-12 18:06         ` Dumitrescu, Cristian

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.