All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v1] rte: add bit-rate metrics to xstats
@ 2016-08-24 14:58 Remy Horton
  2016-08-26 13:28 ` Pattan, Reshma
                   ` (2 more replies)
  0 siblings, 3 replies; 115+ messages in thread
From: Remy Horton @ 2016-08-24 14:58 UTC (permalink / raw)
  To: thomas.monjalon; +Cc: dev

This patch adds peak and average data-rate metrics to the extended
statistics. The intervals used to generate the statistics are
controlled by any application wishing to make use of these metrics.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 doc/guides/rel_notes/release_16_11.rst |   5 ++
 lib/librte_ether/rte_ethdev.c          | 107 ++++++++++++++++++++++++++++++++-
 lib/librte_ether/rte_ethdev.h          |  41 +++++++++++++
 lib/librte_ether/rte_ether_version.map |   6 ++
 4 files changed, 157 insertions(+), 2 deletions(-)

diff --git a/doc/guides/rel_notes/release_16_11.rst b/doc/guides/rel_notes/release_16_11.rst
index 0b9022d..b319292 100644
--- a/doc/guides/rel_notes/release_16_11.rst
+++ b/doc/guides/rel_notes/release_16_11.rst
@@ -36,6 +36,11 @@ New Features
 
      This section is a comment. Make sure to start the actual text at the margin.
 
+   * **Added data-rate metrics to the extended statistics.**
+
+     Adds peak and average incoming and outgoing data-rate metrics to the
+     extended statistics, the calculation of which is controlled by
+     applications that wish for these to be derived.
 
 Resolved Issues
 ---------------
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index f62a9ec..71549b4 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -101,6 +101,7 @@ static const struct rte_eth_xstats_name_off rte_stats_strings[] = {
 };
 
 #define RTE_NB_STATS (sizeof(rte_stats_strings) / sizeof(rte_stats_strings[0]))
+#define RTE_NB_DEV_STATS 4
 
 static const struct rte_eth_xstats_name_off rte_rxq_stats_strings[] = {
 	{"packets", offsetof(struct rte_eth_stats, q_ipackets)},
@@ -1499,6 +1500,7 @@ void
 rte_eth_stats_reset(uint8_t port_id)
 {
 	struct rte_eth_dev *dev;
+	struct rte_eth_dev_stats *dev_stats;
 
 	RTE_ETH_VALID_PORTID_OR_RET(port_id);
 	dev = &rte_eth_devices[port_id];
@@ -1506,6 +1508,19 @@ rte_eth_stats_reset(uint8_t port_id)
 	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset);
 	(*dev->dev_ops->stats_reset)(dev);
 	dev->data->rx_mbuf_alloc_failed = 0;
+
+	/* Clear device running stat counts */
+	dev_stats = &dev->data->stats;
+	memset(dev_stats->list_ibuckets, 0,
+		sizeof(uint64_t) * dev_stats->cnt_buckets);
+	memset(dev_stats->list_obuckets, 0,
+		sizeof(uint64_t) * dev_stats->cnt_buckets);
+	dev_stats->last_ibytes = 0;
+	dev_stats->last_obytes = 0;
+	dev_stats->peak_ibytes = 0;
+	dev_stats->peak_obytes = 0;
+	dev_stats->total_ibytes = 0;
+	dev_stats->total_obytes = 0;
 }
 
 static int
@@ -1522,7 +1537,7 @@ get_xstats_count(uint8_t port_id)
 			return count;
 	} else
 		count = 0;
-	count += RTE_NB_STATS;
+	count += RTE_NB_STATS + RTE_NB_DEV_STATS;
 	count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
 	count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
 	return count;
@@ -1574,6 +1589,19 @@ rte_eth_xstats_get_names(uint8_t port_id,
 		}
 	}
 
+	snprintf(xstats_names[cnt_used_entries++].name,
+		sizeof(xstats_names[0].name),
+		"tx_peak_bytes");
+	snprintf(xstats_names[cnt_used_entries++].name,
+		sizeof(xstats_names[0].name),
+		"tx_mean_bytes");
+	snprintf(xstats_names[cnt_used_entries++].name,
+		sizeof(xstats_names[0].name),
+		"rx_peak_bytes");
+	snprintf(xstats_names[cnt_used_entries++].name,
+		sizeof(xstats_names[0].name),
+		"rx_mean_bytes");
+
 	if (dev->dev_ops->xstats_get_names != NULL) {
 		/* If there are any driver-specific xstats, append them
 		 * to end of list.
@@ -1600,14 +1628,16 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats,
 	unsigned count = 0, i, q;
 	signed xcount = 0;
 	uint64_t val, *stats_ptr;
+	struct rte_eth_dev_stats *dev_stats;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
 
 	dev = &rte_eth_devices[port_id];
+	dev_stats = &dev->data->stats;
 
 	/* Return generic statistics */
 	count = RTE_NB_STATS + (dev->data->nb_rx_queues * RTE_NB_RXQ_STATS) +
-		(dev->data->nb_tx_queues * RTE_NB_TXQ_STATS);
+		(dev->data->nb_tx_queues * RTE_NB_TXQ_STATS) + RTE_NB_DEV_STATS;
 
 	/* implemented by the driver */
 	if (dev->dev_ops->xstats_get != NULL) {
@@ -1659,12 +1689,85 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats,
 		}
 	}
 
+	xstats[count++].value = dev_stats->peak_obytes;
+	xstats[count++].value =
+		dev_stats->total_obytes / dev_stats->cnt_buckets;
+	xstats[count++].value = dev_stats->peak_ibytes;
+	xstats[count++].value =
+		dev_stats->total_ibytes / dev_stats->cnt_buckets;
+
 	for (i = 0; i < count + xcount; i++)
 		xstats[i].id = i;
 
 	return count + xcount;
 }
 
+int
+rte_eth_dev_stats_init(uint8_t port_id, uint32_t cnt_buckets)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_stats *stats;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
+	dev = &rte_eth_devices[port_id];
+	stats = &dev->data->stats;
+
+	memset(stats, 0, sizeof(struct rte_eth_dev_stats));
+	stats->list_ibuckets = rte_zmalloc(
+		NULL, sizeof(uint64_t) * cnt_buckets, 0);
+	stats->list_obuckets = rte_zmalloc(
+		NULL, sizeof(uint64_t) * cnt_buckets, 0);
+	if (stats->list_ibuckets == NULL || stats->list_obuckets == NULL)
+		return -ENOMEM;
+	stats->cnt_buckets = cnt_buckets;
+	return 0;
+}
+
+int
+rte_eth_dev_stats_calc(uint8_t port_id)
+{
+	struct rte_eth_dev *dev;
+	uint64_t *metric;
+	uint64_t cnt_bytes_in_bucket;
+	struct rte_eth_dev_stats *stats;
+	struct rte_eth_stats eth_stats;
+	unsigned ret_code;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
+	dev = &rte_eth_devices[port_id];
+	stats = &dev->data->stats;
+
+	ret_code = rte_eth_stats_get(port_id, &eth_stats);
+	if (ret_code != 0)
+		return ret_code;
+
+	/* tx_good_bytes */
+	metric = RTE_PTR_ADD(&eth_stats, rte_stats_strings[3].offset);
+	cnt_bytes_in_bucket = *metric - stats->last_obytes;
+	stats->last_obytes = *metric;
+	if (cnt_bytes_in_bucket > stats->peak_obytes)
+		stats->peak_obytes = cnt_bytes_in_bucket;
+	stats->total_obytes -= stats->list_obuckets[stats->next_bucket];
+	stats->total_obytes += cnt_bytes_in_bucket;
+	stats->list_obuckets[stats->next_bucket] = cnt_bytes_in_bucket;
+
+	/* rx_good_bytes */
+	metric = RTE_PTR_ADD(&eth_stats, rte_stats_strings[2].offset);
+	cnt_bytes_in_bucket = *metric - stats->last_ibytes;
+	stats->last_ibytes = *metric;
+	if (cnt_bytes_in_bucket > stats->peak_ibytes)
+		stats->peak_ibytes = cnt_bytes_in_bucket;
+	stats->total_ibytes -= stats->list_ibuckets[stats->next_bucket];
+	stats->total_ibytes += cnt_bytes_in_bucket;
+	stats->list_ibuckets[stats->next_bucket] = cnt_bytes_in_bucket;
+
+	/* index wraparound */
+	if (++stats->next_bucket == stats->cnt_buckets)
+		stats->next_bucket = 0;
+
+	return 0;
+}
+
 /* reset ethdev extended statistics */
 void
 rte_eth_xstats_reset(uint8_t port_id)
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index b0fe033..4b1b47b 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1656,6 +1656,19 @@ struct rte_eth_dev_sriov {
 
 #define RTE_ETH_NAME_MAX_LEN (32)
 
+struct rte_eth_dev_stats {
+	uint64_t *list_ibuckets;
+	uint64_t *list_obuckets;
+	uint32_t cnt_buckets;
+	uint32_t next_bucket;
+	uint64_t last_ibytes;
+	uint64_t last_obytes;
+	uint64_t peak_ibytes;
+	uint64_t peak_obytes;
+	uint64_t total_ibytes;
+	uint64_t total_obytes;
+};
+
 /**
  * @internal
  * The data part, with no function pointers, associated with each ethernet device.
@@ -1670,6 +1683,7 @@ struct rte_eth_dev_data {
 	void **tx_queues; /**< Array of pointers to TX queues. */
 	uint16_t nb_rx_queues; /**< Number of RX queues. */
 	uint16_t nb_tx_queues; /**< Number of TX queues. */
+	struct rte_eth_dev_stats stats; /**< Device stats metrics */
 
 	struct rte_eth_dev_sriov sriov;    /**< SRIOV data */
 
@@ -2328,6 +2342,33 @@ int rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats,
 		unsigned n);
 
 /**
+ *  Initialise device statistics.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device
+ * @param cnt_buckets
+ *   Number of sampling buckets within sampling window.
+ * @return
+ *   - Zero on success.
+ *   - Negative value on error.
+ */
+int rte_eth_dev_stats_init(uint8_t port_id, uint32_t cnt_buckets);
+
+/**
+ *  Calculate device statistics.
+ *  This function need to be called periodically. The time between each
+ *  invocation is the sampling period of an individual time bucket within
+ *  the sampling window.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device
+ * @return
+ *   - Zero on success.
+ *   - Negative value on error.
+ */
+int rte_eth_dev_stats_calc(uint8_t port_id);
+
+/**
  * Reset extended statistics of 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 45ddf44..bb7d1cf 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -139,3 +139,9 @@ DPDK_16.07 {
 	rte_eth_dev_get_port_by_name;
 	rte_eth_xstats_get_names;
 } DPDK_16.04;
+
+DPDK_16.11 {
+	global:
+
+	rte_eth_dev_stats_calc;
+} DPDK_16.07;
-- 
2.5.5

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

* Re: [RFC PATCH v1] rte: add bit-rate metrics to xstats
  2016-08-24 14:58 [RFC PATCH v1] rte: add bit-rate metrics to xstats Remy Horton
@ 2016-08-26 13:28 ` Pattan, Reshma
  2016-08-29 10:01 ` Pattan, Reshma
  2016-10-28  1:04 ` [PATCH v2 0/3] expanded statistic reporting Remy Horton
  2 siblings, 0 replies; 115+ messages in thread
From: Pattan, Reshma @ 2016-08-26 13:28 UTC (permalink / raw)
  To: Horton, Remy; +Cc: dev, thomas.monjalon

Hi,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Wednesday, August 24, 2016 3:58 PM
> To: thomas.monjalon@6wind.com
> Cc: dev@dpdk.org
> Subject: [dpdk-dev] [RFC PATCH v1] rte: add bit-rate metrics to xstats
> 
> This patch adds peak and average data-rate metrics to the extended statistics.
> The intervals used to generate the statistics are controlled by any application
> wishing to make use of these metrics.
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>
> ---
> +int
> +rte_eth_dev_stats_init(uint8_t port_id, uint32_t cnt_buckets) {
> +	struct rte_eth_dev *dev;
> +	struct rte_eth_dev_stats *stats;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
> +	dev = &rte_eth_devices[port_id];
> +	stats = &dev->data->stats;
> +
> +	memset(stats, 0, sizeof(struct rte_eth_dev_stats));
> +	stats->list_ibuckets = rte_zmalloc(
> +		NULL, sizeof(uint64_t) * cnt_buckets, 0);

We can have the sizeof(uint64_t) * cnt_buckets, calculated on top and use that in both the rte_zmallocs, Instead of performing * operation twice.

> +	stats->list_obuckets = rte_zmalloc(
> +		NULL, sizeof(uint64_t) * cnt_buckets, 0);
> +	if (stats->list_ibuckets == NULL || stats->list_obuckets == NULL)
> +		return -ENOMEM;

If  either of them has valid pointer we should free that before returning.

> +	stats->cnt_buckets = cnt_buckets;
> +	return 0;
> +}
> +

Thanks,
Reshma

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

* Re: [RFC PATCH v1] rte: add bit-rate metrics to xstats
  2016-08-24 14:58 [RFC PATCH v1] rte: add bit-rate metrics to xstats Remy Horton
  2016-08-26 13:28 ` Pattan, Reshma
@ 2016-08-29 10:01 ` Pattan, Reshma
  2016-08-29 11:19   ` Remy Horton
  2016-10-28  1:04 ` [PATCH v2 0/3] expanded statistic reporting Remy Horton
  2 siblings, 1 reply; 115+ messages in thread
From: Pattan, Reshma @ 2016-08-29 10:01 UTC (permalink / raw)
  To: Horton, Remy, thomas.monjalon; +Cc: dev



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Wednesday, August 24, 2016 3:58 PM
> To: thomas.monjalon@6wind.com
> Cc: dev@dpdk.org
> Subject: [dpdk-dev] [RFC PATCH v1] rte: add bit-rate metrics to xstats
> 
> This patch adds peak and average data-rate metrics to the extended statistics.
> The intervals used to generate the statistics are controlled by any application
> wishing to make use of these metrics.
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>
> ---
> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index
> f62a9ec..71549b4 100644
>  static const struct rte_eth_xstats_name_off rte_rxq_stats_strings[] = {
>  	{"packets", offsetof(struct rte_eth_stats, q_ipackets)}, @@ -1499,6
> +1500,7 @@ void  rte_eth_stats_reset(uint8_t port_id)  {
>  	struct rte_eth_dev *dev;
> +	struct rte_eth_dev_stats *dev_stats;
> 
>  	RTE_ETH_VALID_PORTID_OR_RET(port_id);
>  	dev = &rte_eth_devices[port_id];
> @@ -1506,6 +1508,19 @@ rte_eth_stats_reset(uint8_t port_id)
>  	RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset);
>  	(*dev->dev_ops->stats_reset)(dev);
>  	dev->data->rx_mbuf_alloc_failed = 0;
> +
> +	/* Clear device running stat counts */
> +	dev_stats = &dev->data->stats;
> +	memset(dev_stats->list_ibuckets, 0,
> +		sizeof(uint64_t) * dev_stats->cnt_buckets);
> +	memset(dev_stats->list_obuckets, 0,
> +		sizeof(uint64_t) * dev_stats->cnt_buckets);
> +	dev_stats->last_ibytes = 0;
> +	dev_stats->last_obytes = 0;
> +	dev_stats->peak_ibytes = 0;
> +	dev_stats->peak_obytes = 0;
> +	dev_stats->total_ibytes = 0;
> +	dev_stats->total_obytes = 0;
>  }
> 

Should the resetting has to be done inside rte_eth_xstats_reset() instead of rte_eth_stats_reset()?

Thanks,
Reshma

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

* Re: [RFC PATCH v1] rte: add bit-rate metrics to xstats
  2016-08-29 10:01 ` Pattan, Reshma
@ 2016-08-29 11:19   ` Remy Horton
  0 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2016-08-29 11:19 UTC (permalink / raw)
  To: Pattan, Reshma, thomas.monjalon; +Cc: dev


On 29/08/2016 11:01, Pattan, Reshma wrote:
[..]
>> @@ -1506,6 +1508,19 @@ rte_eth_stats_reset(uint8_t port_id)
[..]
>> +	/* Clear device running stat counts */
>> +	dev_stats = &dev->data->stats;
>> +	memset(dev_stats->list_ibuckets, 0,
>> +		sizeof(uint64_t) * dev_stats->cnt_buckets);
>> +	memset(dev_stats->list_obuckets, 0,
>> +		sizeof(uint64_t) * dev_stats->cnt_buckets);
>> +	dev_stats->last_ibytes = 0;
>> +	dev_stats->last_obytes = 0;
>> +	dev_stats->peak_ibytes = 0;
>> +	dev_stats->peak_obytes = 0;
>> +	dev_stats->total_ibytes = 0;
>> +	dev_stats->total_obytes = 0;

> Should the resetting has to be done inside rte_eth_xstats_reset() instead of rte_eth_stats_reset()?

The bit-rate metrics are calculated from rte_eth_stats values rather 
than xstats values, which is why I put the reset here rather than in 
rte_eth_xstats_reset().

However this ought to be a moot point. I think it is a bug that 
rte_eth_xstats_reset() only calls rte_eth_stats_reset() if the driver 
doesn't implement xstats_reset, as the xstats output includes all the 
rte_eth_stats values unconditonally.

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

* [PATCH v2 0/3] expanded statistic reporting
  2016-08-24 14:58 [RFC PATCH v1] rte: add bit-rate metrics to xstats Remy Horton
  2016-08-26 13:28 ` Pattan, Reshma
  2016-08-29 10:01 ` Pattan, Reshma
@ 2016-10-28  1:04 ` Remy Horton
  2016-10-28  1:04   ` [RFC PATCH v2 1/3] lib: add information metrics library Remy Horton
                     ` (3 more replies)
  2 siblings, 4 replies; 115+ messages in thread
From: Remy Horton @ 2016-10-28  1:04 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon

This patchset extends statistics reporting to include peak and
average data-rate metrics. It comes in two parts: a statistics
reporting library, and a bitrate calculation library that uses
it. This structure is intended to seperate statistic reporting
from ethdev and allow more flexible metric registration.

--

v2 changes:
* Uses a new metrics library rather than being part of ethdev

Remy Horton (3):
  lib: add information metrics library
  lib: add bitrate statistics library
  app/test-pmd: add support for bitrate statistics

 app/test-pmd/testpmd.c                             |  30 ++-
 config/common_base                                 |  10 +
 doc/api/doxy-api-index.md                          |   2 +
 doc/api/doxy-api.conf                              |   2 +
 lib/Makefile                                       |   2 +
 lib/librte_bitratestats/Makefile                   |  53 ++++
 lib/librte_bitratestats/rte_bitrate.c              | 126 ++++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 ++++++
 .../rte_bitratestats_version.map                   |   9 +
 lib/librte_metrics/Makefile                        |  51 ++++
 lib/librte_metrics/rte_metrics.c                   | 267 +++++++++++++++++++++
 lib/librte_metrics/rte_metrics.h                   | 200 +++++++++++++++
 lib/librte_metrics/rte_metrics_version.map         |  13 +
 mk/rte.app.mk                                      |   3 +
 14 files changed, 847 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

-- 
2.5.5

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

* [RFC PATCH v2 1/3] lib: add information metrics library
  2016-10-28  1:04 ` [PATCH v2 0/3] expanded statistic reporting Remy Horton
@ 2016-10-28  1:04   ` Remy Horton
  2016-10-28  1:04   ` [RFC PATCH v2 2/3] lib: add bitrate statistics library Remy Horton
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2016-10-28  1:04 UTC (permalink / raw)
  To: dev

This patch adds a new information metric library that allows other
modules to register named metrics and update their values. It is
intended to be independent of ethdev, rather than mixing ethdev
and non-ethdev information in xstats.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 config/common_base                         |   5 +
 doc/api/doxy-api-index.md                  |   1 +
 doc/api/doxy-api.conf                      |   1 +
 lib/Makefile                               |   1 +
 lib/librte_metrics/Makefile                |  51 ++++++
 lib/librte_metrics/rte_metrics.c           | 265 +++++++++++++++++++++++++++++
 lib/librte_metrics/rte_metrics.h           | 200 ++++++++++++++++++++++
 lib/librte_metrics/rte_metrics_version.map |  13 ++
 mk/rte.app.mk                              |   2 +
 9 files changed, 539 insertions(+)
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

diff --git a/config/common_base b/config/common_base
index f5d2eff..c23a632 100644
--- a/config/common_base
+++ b/config/common_base
@@ -592,3 +592,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
 CONFIG_RTE_TEST_PMD=y
 CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
 CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+
+#
+# Compile the device metrics library
+#
+CONFIG_RTE_LIBRTE_METRICS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 6675f96..ca50fa6 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -147,4 +147,5 @@ There are many libraries, so their headers may be grouped by topics:
   [common]             (@ref rte_common.h),
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
+  [Device Metrics]     (@ref rte_metrics.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index 9dc7ae5..fe830eb 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -57,6 +57,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_reorder \
                           lib/librte_ring \
                           lib/librte_sched \
+                          lib/librte_metrics \
                           lib/librte_table \
                           lib/librte_timer \
                           lib/librte_vhost
diff --git a/lib/Makefile b/lib/Makefile
index 990f23a..5d85dcf 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table
 DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
+DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile
new file mode 100644
index 0000000..8d6e23a
--- /dev/null
+++ b/lib/librte_metrics/Makefile
@@ -0,0 +1,51 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_metrics.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_metrics_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c
new file mode 100644
index 0000000..354ba47
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.c
@@ -0,0 +1,265 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <string.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_lcore.h>
+#include <rte_memzone.h>
+
+
+#define RTE_METRICS_MAX_METRICS 256
+
+
+/**
+ * Internal stats metadata and value entry.
+ *
+ * @internal
+ * @param name
+ *   Name of metric
+ * @param value
+ *   Current value for metric
+ * @param idx_next_set
+ *   Index of next root element (zero for none)
+ * @param idx_next_metric
+ *   Index of next metric in set (zero for none)
+ *
+ * Only the root of each set needs idx_next_set but since it has to be
+ * assumed that number of sets could equal total number of metrics,
+ * having a separate set metadata table doesn't save any memory.
+ */
+struct rte_metrics_meta_s {
+	struct rte_stat_name name;
+	uint64_t value[RTE_MAX_ETHPORTS];
+	uint16_t idx_next_set;
+	uint16_t idx_next_stat;
+};
+
+/**
+ * Internal stats info structure.
+ *
+ * @internal
+ * @param idx_last_set
+ *   Index of last metadata entry with valid data. This value is
+ *   not valid if cnt_stats is zero.
+ * @param cnt_stats
+ *   Number of metrics.
+ * @param metadata
+ *   Stat data memory block.
+ *
+ * Offsets into metadata are used instead of pointers because ASLR
+ * means that having the same physical addresses in different
+ * processes is not guaranteed.
+ */
+struct rte_metrics_data_s {
+	uint16_t idx_last_set;
+	uint16_t cnt_stats;
+	struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS];
+};
+
+
+void
+rte_metrics_init(void)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return;
+
+	memzone = rte_memzone_lookup("RTE_STATS");
+	if (memzone != NULL)
+		return;
+	memzone = rte_memzone_reserve("RTE_STATS",
+		sizeof(struct rte_metrics_data_s), rte_socket_id(), 0);
+	if (memzone == NULL)
+		rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
+	stats = memzone->addr;
+	memset(stats, 0, sizeof(struct rte_metrics_data_s));
+}
+
+
+int
+rte_metrics_reg_metric(const char *name)
+{
+	const char *list_names[] = {name};
+
+	return rte_metrics_reg_metrics(list_names, 1);
+}
+
+
+int
+rte_metrics_reg_metrics(const char **names, uint16_t cnt_names)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	uint16_t idx_base;
+
+	/* Some sanity checks */
+	if (cnt_names < 1 || names == NULL)
+		return -EINVAL;
+
+	rte_metrics_init();
+	memzone = rte_memzone_lookup("RTE_STATS");
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS)
+		return -ENOMEM;
+
+	/* Overwritten later if this is actually first set.. */
+	stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats;
+
+	stats->idx_last_set = idx_base = stats->cnt_stats;
+
+	for (idx_name = 0; idx_name < cnt_names; idx_name++) {
+		entry = &stats->metadata[idx_name + stats->cnt_stats];
+		strncpy(entry->name.name, names[idx_name],
+			RTE_METRICS_MAX_NAME_LEN);
+		memset(entry->value, 0, sizeof(entry->value));
+		entry->idx_next_stat = idx_name + stats->cnt_stats + 1;
+	}
+	entry->idx_next_stat = 0;
+	entry->idx_next_set = 0;
+	stats->cnt_stats += cnt_names;
+
+	return idx_base;
+}
+
+
+int
+rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value)
+{
+	return rte_metrics_update_metrics(port_id, key, &value, 1);
+}
+
+
+int
+rte_metrics_update_metrics(int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_metric;
+	uint16_t idx_value;
+	uint16_t cnt_setsize;
+
+	rte_metrics_init();
+	memzone = rte_memzone_lookup("RTE_STATS");
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	idx_metric = key;
+	cnt_setsize = 1;
+	while (idx_metric < stats->cnt_stats) {
+		entry = &stats->metadata[idx_metric];
+		if (entry->idx_next_stat == 0)
+			break;
+		cnt_setsize++;
+		idx_metric++;
+	}
+	/* Check update does not cross set border */
+	if (count > cnt_setsize)
+		return -ERANGE;
+
+	for (idx_value = 0; idx_value < count; idx_value++) {
+		idx_metric = key + idx_value;
+		stats->metadata[idx_metric].value[port_id] = values[idx_value];
+	}
+	return 0;
+}
+
+
+int
+rte_metrics_get_names(struct rte_stat_name *names,
+	uint16_t capacity)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+
+	memzone = rte_memzone_lookup("RTE_STATS");
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+	stats = memzone->addr;
+
+	if (names != NULL) {
+		if (capacity < stats->cnt_stats)
+			return -ERANGE;
+		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
+			strncpy(names[idx_name].name,
+				stats->metadata[idx_name].name.name,
+				RTE_METRICS_MAX_NAME_LEN);
+	}
+	return stats->cnt_stats;
+}
+
+
+int
+rte_metrics_get_values(int port_id,
+	struct rte_stat_value *values,
+	uint16_t capacity)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+
+	memzone = rte_memzone_lookup("RTE_STATS");
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+	stats = memzone->addr;
+
+	if (values != NULL) {
+		if (capacity < stats->cnt_stats)
+			return -ERANGE;
+		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) {
+			entry = &stats->metadata[idx_name];
+			values[idx_name].key = idx_name;
+			values[idx_name].value = entry->value[port_id];
+		}
+	}
+	return stats->cnt_stats;
+}
diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
new file mode 100644
index 0000000..e8888eb
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.h
@@ -0,0 +1,200 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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.
+ */
+
+/**
+ * @file
+ *
+ * RTE Statistics module
+ *
+ * Statistic information is populated using callbacks, each of which
+ * is associated with one or more metric names. When queried, the
+ * callback is used to update all metric in the set at once. Currently
+ * only bulk querying of all metric is supported.
+ *
+ */
+
+#ifndef _RTE_METRICS_H_
+#define _RTE_METRICS_H_
+
+/** Maximum length of statistic name (including null-terminator) */
+#define RTE_METRICS_MAX_NAME_LEN 64
+
+/**
+ * Statistic name
+ */
+struct rte_stat_name {
+	/** String describing statistic */
+	char name[RTE_METRICS_MAX_NAME_LEN];
+};
+
+
+/**
+ * Statistic name.
+ */
+struct rte_stat_value {
+	/** Numeric identifier of statistic */
+	uint16_t key;
+	/** Value for statistic */
+	uint64_t value;
+};
+
+
+/**
+ * Initialises statistic module. This only has to be explicitly called if you
+ * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a
+ * secondary process.
+ */
+void rte_metrics_init(void);
+
+
+/**
+ * Register a statistic and its associated callback.
+ *
+ * @param name
+ *   Statistic name
+ *
+ * @param callback
+ *   Callback to use when fetching statistic
+ *
+ * @param data
+ *   Data pointer to pass to callback
+ *
+ * @return
+ *  - Zero or positive: Success
+ *  - Negative: Failure
+ */
+int rte_metrics_reg_metric(const char *name);
+
+/**
+ * Register a set of statistic and their associated callback.
+ *
+ * @param names
+ *   List of statistic names
+ *
+ * @param cnt_names
+ *   Number of statistics in set
+ *
+ * @param callback
+ *   Callback to use when fetching statsitics
+ *
+ * @param data
+ *   Data pointer to pass to callback
+ *
+ * @return
+ *  - Zero or positive: Success
+ *  - Negative: Failure
+ */
+int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names);
+
+/**
+ * Get statistic name-key lookup table.
+ *
+ * @param names
+ *   Array of names to receive key names
+ *
+ * @param capacity
+ *   Space available in names
+ *
+ * @return
+ *   - Non-negative: Success (number of names)
+ *   - Negative: Failure
+ */
+int rte_metrics_get_names(
+	struct rte_stat_name *names,
+	uint16_t capacity);
+
+/**
+ * Fetch statistics.
+ *
+ * @param port_id
+ *   Port id to query
+ *
+ * @param values
+ *   Array to receive values and their keys
+ *
+ * @param capacity
+ *   Space available in values
+ *
+ * @return
+ *   - Non-negative: Success (number of names)
+ *   - Negative: Failure
+ */
+int rte_metrics_get_values(
+	int port_id,
+	struct rte_stat_value *values,
+	uint16_t capacity);
+
+/**
+ * Updates a statistic metric
+ *
+ * @param port_id
+ *   Port to update statistics for
+ * @param key
+ *   Id of statistic metric to update
+ * @param value
+ *   New value
+ *
+ * @return
+ *   - -EIO if unable to access shared statistics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_metric(
+	int port_id,
+	uint16_t key,
+	const uint64_t value);
+
+/**
+ * Updates a statistic metric set. Note that it is an error to try to
+ * update across a set boundary.
+ *
+ * @param port_id
+ *   Port to update statistics for
+ * @param key
+ *   Base id of statistics set to update
+ * @param values
+ *   Set of new values
+ * @param count
+ *   Number of new values
+ *
+ * @return
+ *   - -ERANGE if count exceeds statistic set size
+ *   - -EIO if upable to access shared statistics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_metrics(
+	int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count);
+
+#endif
diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map
new file mode 100644
index 0000000..a31a80a
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics_version.map
@@ -0,0 +1,13 @@
+DPDK_16.11 {
+	global:
+
+	rte_metrics_get_names;
+	rte_metrics_get_values;
+	rte_metrics_init;
+	rte_metrics_reg_metric;
+	rte_metrics_reg_metrics;
+	rte_metrics_update_metric;
+	rte_metrics_update_metrics;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index ac50a21..11d0c80 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -97,6 +97,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING)           += -lrte_ring
 _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
+_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* [RFC PATCH v2 2/3] lib: add bitrate statistics library
  2016-10-28  1:04 ` [PATCH v2 0/3] expanded statistic reporting Remy Horton
  2016-10-28  1:04   ` [RFC PATCH v2 1/3] lib: add information metrics library Remy Horton
@ 2016-10-28  1:04   ` Remy Horton
  2016-10-28  1:12     ` Stephen Hemminger
  2016-10-28  7:39     ` Morten Brørup
  2016-10-28  1:04   ` [RFC PATCH v2 3/3] app/test-pmd: add support for bitrate statistics Remy Horton
  2016-11-04  3:36   ` [PATCH v3 0/3] Expanded statistics reporting Remy Horton
  3 siblings, 2 replies; 115+ messages in thread
From: Remy Horton @ 2016-10-28  1:04 UTC (permalink / raw)
  To: dev

This patch adds a library that calculates peak and average data-rate
statistics. For ethernet devices. These statistics are reported using
the metrics library.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 lib/Makefile                                       |   1 +
 lib/librte_bitratestats/Makefile                   |  53 +++++++++
 lib/librte_bitratestats/rte_bitrate.c              | 126 +++++++++++++++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++++++++++
 .../rte_bitratestats_version.map                   |   9 ++
 lib/librte_metrics/rte_metrics.c                   |  22 ++--
 lib/librte_metrics/rte_metrics.h                   |   4 +-
 mk/rte.app.mk                                      |   1 +
 11 files changed, 291 insertions(+), 12 deletions(-)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map

diff --git a/config/common_base b/config/common_base
index c23a632..e778c00 100644
--- a/config/common_base
+++ b/config/common_base
@@ -597,3 +597,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
 # Compile the device metrics library
 #
 CONFIG_RTE_LIBRTE_METRICS=y
+
+#
+# Compile the bitrate statistics library
+#
+CONFIG_RTE_LIBRTE_BITRATE=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index ca50fa6..91e8ea6 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -148,4 +148,5 @@ There are many libraries, so their headers may be grouped by topics:
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
   [Device Metrics]     (@ref rte_metrics.h),
+  [Bitrate Statistics] (@ref rte_bitrate.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index fe830eb..8765ddd 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -58,6 +58,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_ring \
                           lib/librte_sched \
                           lib/librte_metrics \
+                          lib/librte_bitratestats \
                           lib/librte_table \
                           lib/librte_timer \
                           lib/librte_vhost
diff --git a/lib/Makefile b/lib/Makefile
index 5d85dcf..e211bc0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
+DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile
new file mode 100644
index 0000000..b725d4e
--- /dev/null
+++ b/lib/librte_bitratestats/Makefile
@@ -0,0 +1,53 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_bitratestats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_bitratestats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c
new file mode 100644
index 0000000..fcdf401
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.c
@@ -0,0 +1,126 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
+
+
+struct rte_stats_bitrate_s {
+	uint64_t last_ibytes;
+	uint64_t last_obytes;
+	uint64_t peak_ibits;
+	uint64_t peak_obits;
+	uint64_t ewma_ibits;
+	uint64_t ewma_obits;
+};
+
+struct rte_stats_bitrates_s {
+	struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS];
+	uint16_t id_stats_set;
+};
+
+
+struct rte_stats_bitrates_s *rte_stats_bitrate_create(void)
+{
+	return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0);
+}
+
+
+int
+rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data)
+{
+	const char *names[] = {
+		"mean_bits_in", "mean_bits_out",
+		"peak_bits_in", "peak_bits_out",
+	};
+	int return_value;
+
+	bitrate_data = rte_stats_bitrate_create();
+	if (bitrate_data == NULL)
+		rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n");
+	return_value = rte_metrics_reg_metrics(&names[0], 4);
+	if (return_value >= 0)
+		bitrate_data->id_stats_set = return_value;
+	return return_value;
+}
+
+
+int
+rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
+	uint8_t port_id)
+{
+	struct rte_stats_bitrate_s *port_data;
+	struct rte_eth_stats eth_stats;
+	int ret_code;
+	uint64_t cnt_bits;
+	int64_t delta;
+	const int64_t alpha_percent = 20;
+	uint64_t values[4];
+
+	ret_code = rte_eth_stats_get(port_id, &eth_stats);
+	if (ret_code != 0)
+		return ret_code;
+
+	port_data = &bitrate_data->port_stats[port_id];
+
+	/* Incoming */
+	cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3;
+	port_data->last_ibytes = eth_stats.ibytes;
+	if (cnt_bits > port_data->peak_ibits)
+		port_data->peak_ibits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_ibits;
+	delta = (delta * alpha_percent) / 100;
+	port_data->ewma_ibits += delta;
+
+	/* Outgoing */
+	cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3;
+	port_data->last_obytes = eth_stats.obytes;
+	if (cnt_bits > port_data->peak_obits)
+		port_data->peak_obits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_obits;
+	delta = (delta * alpha_percent) / 100;
+	port_data->ewma_obits += delta;
+
+	values[0] = port_data->ewma_ibits;
+	values[1] = port_data->ewma_obits;
+	values[2] = port_data->peak_ibits;
+	values[3] = port_data->peak_obits;
+	rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set,
+		values, 4);
+	return 0;
+}
diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h
new file mode 100644
index 0000000..cd566d6
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.h
@@ -0,0 +1,80 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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.
+ */
+
+
+
+/**
+ *  Bitrate statistics data structure
+ */
+struct rte_stats_bitrates_s;
+
+
+/**
+ * Allocate a bitrate statistics structure
+ *
+ * @return
+ *   - Pointer to structure on success
+ *   - NULL on error (zmalloc failure)
+ */
+struct rte_stats_bitrates_s *rte_stats_bitrate_create(void);
+
+
+/**
+ * Register bitrate statistics
+ *
+ * @param bitrate_data
+ *   Pointer allocated by rte_stats_create()
+ *
+ * @return
+ *   Zero on success
+ *   Negative on error
+ */
+int rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data);
+
+
+/**
+ * Calculate statistics for current time window. The period this function
+ * is called should be the intended time window width.
+ *
+ * @param bitrate_data
+ *   Bitrate statistics data pointer
+ *
+ * @param port_id
+ *   Port id to calculate statistics for
+ *
+ * @return
+ *  - Zero on success
+ *  - Negative value on error
+ */
+int rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
+	uint8_t port_id);
diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map
new file mode 100644
index 0000000..9de6be9
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitratestats_version.map
@@ -0,0 +1,9 @@
+DPDK_16.11 {
+	global:
+
+	rte_stats_bitrate_calc;
+	rte_stats_bitrate_create;
+	rte_stats_bitrate_reg;
+
+	local: *;
+};
diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c
index 354ba47..7dce738 100644
--- a/lib/librte_metrics/rte_metrics.c
+++ b/lib/librte_metrics/rte_metrics.c
@@ -44,6 +44,8 @@
 #define RTE_METRICS_MAX_METRICS 256
 
 
+#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS"
+
 /**
  * Internal stats metadata and value entry.
  *
@@ -62,7 +64,7 @@
  * having a separate set metadata table doesn't save any memory.
  */
 struct rte_metrics_meta_s {
-	struct rte_stat_name name;
+	char name[RTE_METRICS_MAX_NAME_LEN];
 	uint64_t value[RTE_MAX_ETHPORTS];
 	uint16_t idx_next_set;
 	uint16_t idx_next_stat;
@@ -100,10 +102,10 @@ rte_metrics_init(void)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return;
 
-	memzone = rte_memzone_lookup("RTE_STATS");
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
 	if (memzone != NULL)
 		return;
-	memzone = rte_memzone_reserve("RTE_STATS",
+	memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME,
 		sizeof(struct rte_metrics_data_s), rte_socket_id(), 0);
 	if (memzone == NULL)
 		rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
@@ -135,7 +137,7 @@ rte_metrics_reg_metrics(const char **names, uint16_t cnt_names)
 		return -EINVAL;
 
 	rte_metrics_init();
-	memzone = rte_memzone_lookup("RTE_STATS");
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
 	if (memzone == NULL)
 		return -EIO;
 	stats = memzone->addr;
@@ -150,7 +152,7 @@ rte_metrics_reg_metrics(const char **names, uint16_t cnt_names)
 
 	for (idx_name = 0; idx_name < cnt_names; idx_name++) {
 		entry = &stats->metadata[idx_name + stats->cnt_stats];
-		strncpy(entry->name.name, names[idx_name],
+		strncpy(entry->name, names[idx_name],
 			RTE_METRICS_MAX_NAME_LEN);
 		memset(entry->value, 0, sizeof(entry->value));
 		entry->idx_next_stat = idx_name + stats->cnt_stats + 1;
@@ -184,7 +186,7 @@ rte_metrics_update_metrics(int port_id,
 	uint16_t cnt_setsize;
 
 	rte_metrics_init();
-	memzone = rte_memzone_lookup("RTE_STATS");
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
 	if (memzone == NULL)
 		return -EIO;
 	stats = memzone->addr;
@@ -211,14 +213,14 @@ rte_metrics_update_metrics(int port_id,
 
 
 int
-rte_metrics_get_names(struct rte_stat_name *names,
+rte_metrics_get_names(struct rte_metric_name *names,
 	uint16_t capacity)
 {
 	struct rte_metrics_data_s *stats;
 	const struct rte_memzone *memzone;
 	uint16_t idx_name;
 
-	memzone = rte_memzone_lookup("RTE_STATS");
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
 	/* If not allocated, fail silently */
 	if (memzone == NULL)
 		return 0;
@@ -229,7 +231,7 @@ rte_metrics_get_names(struct rte_stat_name *names,
 			return -ERANGE;
 		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
 			strncpy(names[idx_name].name,
-				stats->metadata[idx_name].name.name,
+				stats->metadata[idx_name].name,
 				RTE_METRICS_MAX_NAME_LEN);
 	}
 	return stats->cnt_stats;
@@ -246,7 +248,7 @@ rte_metrics_get_values(int port_id,
 	const struct rte_memzone *memzone;
 	uint16_t idx_name;
 
-	memzone = rte_memzone_lookup("RTE_STATS");
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
 	/* If not allocated, fail silently */
 	if (memzone == NULL)
 		return 0;
diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
index e8888eb..348db30 100644
--- a/lib/librte_metrics/rte_metrics.h
+++ b/lib/librte_metrics/rte_metrics.h
@@ -52,7 +52,7 @@
 /**
  * Statistic name
  */
-struct rte_stat_name {
+struct rte_metric_name {
 	/** String describing statistic */
 	char name[RTE_METRICS_MAX_NAME_LEN];
 };
@@ -130,7 +130,7 @@ int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names);
  *   - Negative: Failure
  */
 int rte_metrics_get_names(
-	struct rte_stat_name *names,
+	struct rte_metric_name *names,
 	uint16_t capacity);
 
 /**
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 11d0c80..c499c69 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -98,6 +98,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
 
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
-- 
2.5.5

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

* [RFC PATCH v2 3/3] app/test-pmd: add support for bitrate statistics
  2016-10-28  1:04 ` [PATCH v2 0/3] expanded statistic reporting Remy Horton
  2016-10-28  1:04   ` [RFC PATCH v2 1/3] lib: add information metrics library Remy Horton
  2016-10-28  1:04   ` [RFC PATCH v2 2/3] lib: add bitrate statistics library Remy Horton
@ 2016-10-28  1:04   ` Remy Horton
  2016-11-04  3:36   ` [PATCH v3 0/3] Expanded statistics reporting Remy Horton
  3 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2016-10-28  1:04 UTC (permalink / raw)
  To: dev

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/testpmd.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index e2403c3..940dc3b 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -78,6 +78,8 @@
 #ifdef RTE_LIBRTE_PDUMP
 #include <rte_pdump.h>
 #endif
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
 
 #include "testpmd.h"
 
@@ -322,6 +324,9 @@ uint16_t nb_rx_queue_stats_mappings = 0;
 
 unsigned max_socket = 0;
 
+/* Bitrate statistics */
+struct rte_stats_bitrates_s *bitrate_data;
+
 /* Forward function declarations */
 static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -921,12 +926,26 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
 	struct fwd_stream **fsm;
 	streamid_t nb_fs;
 	streamid_t sm_id;
-
+	uint64_t tics_per_1sec;
+	uint64_t tics_datum;
+	uint64_t tics_current;
+	uint8_t idx_port, cnt_ports;
+
+	cnt_ports = rte_eth_dev_count();
+	tics_datum = rte_rdtsc();
+	tics_per_1sec = rte_get_timer_hz();
 	fsm = &fwd_streams[fc->stream_idx];
 	nb_fs = fc->stream_nb;
 	do {
 		for (sm_id = 0; sm_id < nb_fs; sm_id++)
 			(*pkt_fwd)(fsm[sm_id]);
+		tics_current = rte_rdtsc();
+		if (tics_current - tics_datum >= tics_per_1sec) {
+			/* Periodic bitrate calculation */
+			for (idx_port = 0; idx_port < cnt_ports; idx_port++)
+				rte_stats_bitrate_calc(bitrate_data, idx_port);
+			tics_datum = tics_current;
+		}
 	} while (! fc->stopped);
 }
 
@@ -2119,6 +2138,15 @@ main(int argc, char** argv)
 	FOREACH_PORT(port_id, ports)
 		rte_eth_promiscuous_enable(port_id);
 
+	/* Setup bitrate stats */
+	bitrate_data = rte_stats_bitrate_create();
+	if (bitrate_data == NULL)
+		rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n");
+	rte_stats_bitrate_reg(bitrate_data);
+	int id_const = rte_metrics_reg_metric("constant");
+	rte_metrics_update_metric(55, id_const, 0xdeadbeef);
+
+
 #ifdef RTE_LIBRTE_CMDLINE
 	if (interactive == 1) {
 		if (auto_start) {
-- 
2.5.5

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

* Re: [RFC PATCH v2 2/3] lib: add bitrate statistics library
  2016-10-28  1:04   ` [RFC PATCH v2 2/3] lib: add bitrate statistics library Remy Horton
@ 2016-10-28  1:12     ` Stephen Hemminger
  2016-10-28  7:48       ` Remy Horton
  2016-10-28  7:39     ` Morten Brørup
  1 sibling, 1 reply; 115+ messages in thread
From: Stephen Hemminger @ 2016-10-28  1:12 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev

On Fri, 28 Oct 2016 09:04:30 +0800
Remy Horton <remy.horton@intel.com> wrote:

> +
> +struct rte_stats_bitrate_s {
> +	uint64_t last_ibytes;
> +	uint64_t last_obytes;
> +	uint64_t peak_ibits;
> +	uint64_t peak_obits;
> +	uint64_t ewma_ibits;
> +	uint64_t ewma_obits;
> +};
> +

Reader/write access of 64 bit values is not safe on 32 bit platforms.
I think you need to add a generation counter (see Linux kernel syncp)
to handle 32 bit architecture. If done correctly, it would be a nop
on 64 bit platforms.

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

* Re: [RFC PATCH v2 2/3] lib: add bitrate statistics library
  2016-10-28  1:04   ` [RFC PATCH v2 2/3] lib: add bitrate statistics library Remy Horton
  2016-10-28  1:12     ` Stephen Hemminger
@ 2016-10-28  7:39     ` Morten Brørup
  2016-11-01  1:53       ` Remy Horton
  1 sibling, 1 reply; 115+ messages in thread
From: Morten Brørup @ 2016-10-28  7:39 UTC (permalink / raw)
  To: Remy Horton, dev

Comments below.

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Friday, October 28, 2016 3:05 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [RFC PATCH v2 2/3] lib: add bitrate statistics
> library
> 
> This patch adds a library that calculates peak and average data-rate
> statistics. For ethernet devices. These statistics are reported using
> the metrics library.
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>


> diff --git a/lib/librte_bitratestats/rte_bitrate.c
> b/lib/librte_bitratestats/rte_bitrate.c
> new file mode 100644
> index 0000000..fcdf401
> --- /dev/null
> +++ b/lib/librte_bitratestats/rte_bitrate.c
> @@ -0,0 +1,126 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2016 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 <rte_common.h>
> +#include <rte_ethdev.h>
> +#include <rte_malloc.h>
> +#include <rte_metrics.h>
> +#include <rte_bitrate.h>
> +
> +
> +struct rte_stats_bitrate_s {
> +	uint64_t last_ibytes;
> +	uint64_t last_obytes;
> +	uint64_t peak_ibits;
> +	uint64_t peak_obits;
> +	uint64_t ewma_ibits;
> +	uint64_t ewma_obits;
> +};
> +
> +struct rte_stats_bitrates_s {
> +	struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS];
> +	uint16_t id_stats_set;
> +};
> +
> +
> +struct rte_stats_bitrates_s *rte_stats_bitrate_create(void) {
> +	return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0);
> }
> +
> +
> +int
> +rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data)
> +{
> +	const char *names[] = {
> +		"mean_bits_in", "mean_bits_out",
> +		"peak_bits_in", "peak_bits_out",
> +	};
> +	int return_value;
> +
> +	bitrate_data = rte_stats_bitrate_create();
> +	if (bitrate_data == NULL)
> +		rte_exit(EXIT_FAILURE, "Could not allocate bitrate
> data.\n");
> +	return_value = rte_metrics_reg_metrics(&names[0], 4);
> +	if (return_value >= 0)
> +		bitrate_data->id_stats_set = return_value;
> +	return return_value;
> +}
> +
> +
> +int
> +rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
> +	uint8_t port_id)
> +{
> +	struct rte_stats_bitrate_s *port_data;
> +	struct rte_eth_stats eth_stats;
> +	int ret_code;
> +	uint64_t cnt_bits;
> +	int64_t delta;
> +	const int64_t alpha_percent = 20;
> +	uint64_t values[4];
> +
> +	ret_code = rte_eth_stats_get(port_id, &eth_stats);
> +	if (ret_code != 0)
> +		return ret_code;
> +
> +	port_data = &bitrate_data->port_stats[port_id];
> +
> +	/* Incoming */
> +	cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3;
> +	port_data->last_ibytes = eth_stats.ibytes;
> +	if (cnt_bits > port_data->peak_ibits)
> +		port_data->peak_ibits = cnt_bits;
> +	delta = cnt_bits;
> +	delta -= port_data->ewma_ibits;
> +	delta = (delta * alpha_percent) / 100;
> +	port_data->ewma_ibits += delta;
> +
> +	/* Outgoing */
> +	cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3;
> +	port_data->last_obytes = eth_stats.obytes;
> +	if (cnt_bits > port_data->peak_obits)
> +		port_data->peak_obits = cnt_bits;
> +	delta = cnt_bits;
> +	delta -= port_data->ewma_obits;
> +	delta = (delta * alpha_percent) / 100;
> +	port_data->ewma_obits += delta;
> +
> +	values[0] = port_data->ewma_ibits;
> +	values[1] = port_data->ewma_obits;
> +	values[2] = port_data->peak_ibits;
> +	values[3] = port_data->peak_obits;
> +	rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set,
> +		values, 4);
> +	return 0;
> +}

When working with statistical calculations using integer arithmetic, you should round off the integer result by adding 0.5 to the result, which you do by adding half of the divisor to the dividend, like this:

delta = (delta * alpha_percent + 50) / 100;

The numbers in this particular case are probably very big, so not rounding off doesn't affect the result a lot; but then you should add a comment about why rounding down is acceptable.


Med venlig hilsen / kind regards
- Morten Brørup

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

* Re: [RFC PATCH v2 2/3] lib: add bitrate statistics library
  2016-10-28  1:12     ` Stephen Hemminger
@ 2016-10-28  7:48       ` Remy Horton
  0 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2016-10-28  7:48 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev


On 28/10/2016 09:12, Stephen Hemminger wrote:
> On Fri, 28 Oct 2016 09:04:30 +0800
> Remy Horton <remy.horton@intel.com> wrote:
>
>> +
>> +struct rte_stats_bitrate_s {
>> +	uint64_t last_ibytes;
>> +	uint64_t last_obytes;
>> +	uint64_t peak_ibits;
>> +	uint64_t peak_obits;
>> +	uint64_t ewma_ibits;
>> +	uint64_t ewma_obits;
>> +};
>> +
>
> Reader/write access of 64 bit values is not safe on 32 bit platforms.
> I think you need to add a generation counter (see Linux kernel syncp)
> to handle 32 bit architecture. If done correctly, it would be a nop
> on 64 bit platforms.

I don't see a problem since this is private persistent data that is only 
read/written from rte_stats_bitrate_calc(), and once calculated it 
pushes them into the metrics library using rte_metrics_update_metrics(). 
The idea is that downstream consumers get the values using 
rte_metrics_get_values() rather than reading rte_stats_bitrate_s directly.

Having said that, what you mention quite likley affects the metrics 
library itself.. :)

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

* Re: [RFC PATCH v2 2/3] lib: add bitrate statistics library
  2016-10-28  7:39     ` Morten Brørup
@ 2016-11-01  1:53       ` Remy Horton
  0 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2016-11-01  1:53 UTC (permalink / raw)
  To: dev; +Cc: Morten Brørup


On 28/10/2016 15:39, Morten Brørup wrote:
> Comments below.
[..]
> When working with statistical calculations using integer arithmetic,
> you should round off the integer result by adding 0.5 to the result,
> which you do by adding half of the divisor to the dividend, like
> this:
>
> delta = (delta * alpha_percent + 50) / 100;
>
> The numbers in this particular case are probably very big, so not
> rounding off doesn't affect the result a lot; but then you should add
> a comment about why rounding down is acceptable.

A minor point, but will roll it into the next patchset.

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

* [PATCH v3 0/3] Expanded statistics reporting
  2016-10-28  1:04 ` [PATCH v2 0/3] expanded statistic reporting Remy Horton
                     ` (2 preceding siblings ...)
  2016-10-28  1:04   ` [RFC PATCH v2 3/3] app/test-pmd: add support for bitrate statistics Remy Horton
@ 2016-11-04  3:36   ` Remy Horton
  2016-11-04  3:36     ` [PATCH v3 1/3] lib: add information metrics library Remy Horton
                       ` (3 more replies)
  3 siblings, 4 replies; 115+ messages in thread
From: Remy Horton @ 2016-11-04  3:36 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patchset extends statistics reporting to include peak and
average data-rate metrics. It comes in two parts: a statistics
reporting library, and a bitrate calculation library that uses
it. This structure is intended to seperate statistic reporting
from ethdev and allow more flexible metric registration.

--

v3 changes:
* Marked rte_stats_bitrate_s as internal
* Minor integer roundoff correction
* Coding style corrections
* Removed spurious object allocation
* Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3.
* Reintroduced non-port values (RTE_METRICS_NONPORT)
* Added spinlocks to metric library
* Removed spurious test registration/update
* Added release notes entries

v2 changes:
* Uses a new metrics library rather than being part of ethdev


Remy Horton (3):
  lib: add information metrics library
  lib: add bitrate statistics library
  app/test-pmd: add support for bitrate statistics

 app/test-pmd/testpmd.c                             |  28 +-
 config/common_base                                 |  10 +
 doc/api/doxy-api-index.md                          |   2 +
 doc/api/doxy-api.conf                              |   2 +
 doc/guides/rel_notes/release_16_11.rst             |  11 +
 lib/Makefile                                       |   2 +
 lib/librte_bitratestats/Makefile                   |  53 ++++
 lib/librte_bitratestats/rte_bitrate.c              | 128 +++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 ++++++
 .../rte_bitratestats_version.map                   |   9 +
 lib/librte_metrics/Makefile                        |  51 ++++
 lib/librte_metrics/rte_metrics.c                   | 300 +++++++++++++++++++++
 lib/librte_metrics/rte_metrics.h                   | 204 ++++++++++++++
 lib/librte_metrics/rte_metrics_version.map         |  13 +
 mk/rte.app.mk                                      |   3 +
 15 files changed, 895 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

-- 
2.5.5

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

* [PATCH v3 1/3] lib: add information metrics library
  2016-11-04  3:36   ` [PATCH v3 0/3] Expanded statistics reporting Remy Horton
@ 2016-11-04  3:36     ` Remy Horton
  2016-11-04 16:42       ` Pattan, Reshma
  2016-11-04  3:36     ` [PATCH v3 2/3] lib: add bitrate statistics library Remy Horton
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2016-11-04  3:36 UTC (permalink / raw)
  To: dev

This patch adds a new information metric library that allows other
modules to register named metrics and update their values. It is
intended to be independent of ethdev, rather than mixing ethdev
and non-ethdev information in xstats.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 config/common_base                         |   5 +
 doc/api/doxy-api-index.md                  |   1 +
 doc/api/doxy-api.conf                      |   1 +
 doc/guides/rel_notes/release_16_11.rst     |   6 +
 lib/Makefile                               |   1 +
 lib/librte_metrics/Makefile                |  51 +++++
 lib/librte_metrics/rte_metrics.c           | 300 +++++++++++++++++++++++++++++
 lib/librte_metrics/rte_metrics.h           | 204 ++++++++++++++++++++
 lib/librte_metrics/rte_metrics_version.map |  13 ++
 mk/rte.app.mk                              |   2 +
 10 files changed, 584 insertions(+)
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

diff --git a/config/common_base b/config/common_base
index 21d18f8..2277727 100644
--- a/config/common_base
+++ b/config/common_base
@@ -589,3 +589,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
 CONFIG_RTE_TEST_PMD=y
 CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
 CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+
+#
+# Compile the device metrics library
+#
+CONFIG_RTE_LIBRTE_METRICS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 6675f96..ca50fa6 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -147,4 +147,5 @@ There are many libraries, so their headers may be grouped by topics:
   [common]             (@ref rte_common.h),
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
+  [Device Metrics]     (@ref rte_metrics.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index 9dc7ae5..fe830eb 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -57,6 +57,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_reorder \
                           lib/librte_ring \
                           lib/librte_sched \
+                          lib/librte_metrics \
                           lib/librte_table \
                           lib/librte_timer \
                           lib/librte_vhost
diff --git a/doc/guides/rel_notes/release_16_11.rst b/doc/guides/rel_notes/release_16_11.rst
index aa0c09a..507f715 100644
--- a/doc/guides/rel_notes/release_16_11.rst
+++ b/doc/guides/rel_notes/release_16_11.rst
@@ -131,6 +131,12 @@ New Features
   The GCC 4.9 ``-march`` option supports the Intel processor code names.
   The config option ``RTE_MACHINE`` can be used to pass code names to the compiler as ``-march`` flag.
 
+* **Added information metric library.**
+
+  A library that allows information metrics to be added and update. It is
+  intended to provide a reporting mechanism that is independent of the
+  ethdev library.
+
 
 Resolved Issues
 ---------------
diff --git a/lib/Makefile b/lib/Makefile
index 990f23a..5d85dcf 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table
 DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
+DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile
new file mode 100644
index 0000000..8d6e23a
--- /dev/null
+++ b/lib/librte_metrics/Makefile
@@ -0,0 +1,51 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_metrics.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_metrics_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c
new file mode 100644
index 0000000..220c2ac
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.c
@@ -0,0 +1,300 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <string.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_lcore.h>
+#include <rte_memzone.h>
+#include <rte_spinlock.h>
+
+#define RTE_METRICS_MAX_METRICS 256
+#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS"
+
+/**
+ * Internal stats metadata and value entry.
+ *
+ * @internal
+ * @param name
+ *   Name of metric
+ * @param value
+ *   Current value for metric
+ * @param idx_next_set
+ *   Index of next root element (zero for none)
+ * @param idx_next_metric
+ *   Index of next metric in set (zero for none)
+ *
+ * Only the root of each set needs idx_next_set but since it has to be
+ * assumed that number of sets could equal total number of metrics,
+ * having a separate set metadata table doesn't save any memory.
+ */
+struct rte_metrics_meta_s {
+	char name[RTE_METRICS_MAX_NAME_LEN];
+	uint64_t value[RTE_MAX_ETHPORTS];
+	uint64_t nonport_value;
+	uint16_t idx_next_set;
+	uint16_t idx_next_stat;
+};
+
+/**
+ * Internal stats info structure.
+ *
+ * @internal
+ * @param idx_last_set
+ *   Index of last metadata entry with valid data. This value is
+ *   not valid if cnt_stats is zero.
+ * @param cnt_stats
+ *   Number of metrics.
+ * @param metadata
+ *   Stat data memory block.
+ *
+ * Offsets into metadata are used instead of pointers because ASLR
+ * means that having the same physical addresses in different
+ * processes is not guaranteed.
+ */
+struct rte_metrics_data_s {
+	uint16_t idx_last_set;
+	uint16_t cnt_stats;
+	struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS];
+	rte_spinlock_t lock;
+};
+
+
+void
+rte_metrics_init(void)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone != NULL)
+		return;
+	memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME,
+		sizeof(struct rte_metrics_data_s), rte_socket_id(), 0);
+	if (memzone == NULL)
+		rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
+	stats = memzone->addr;
+	memset(stats, 0, sizeof(struct rte_metrics_data_s));
+	rte_spinlock_init(&stats->lock);
+}
+
+
+int
+rte_metrics_reg_metric(const char *name)
+{
+	const char *list_names[] = {name};
+
+	return rte_metrics_reg_metrics(list_names, 1);
+}
+
+
+int
+rte_metrics_reg_metrics(const char **names, uint16_t cnt_names)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	uint16_t idx_base;
+
+	/* Some sanity checks */
+	if (cnt_names < 1 || names == NULL)
+		return -EINVAL;
+
+	rte_metrics_init();
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS)
+		return -ENOMEM;
+
+	rte_spinlock_lock(&stats->lock);
+
+	/* Overwritten later if this is actually first set.. */
+	stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats;
+
+	stats->idx_last_set = idx_base = stats->cnt_stats;
+
+	for (idx_name = 0; idx_name < cnt_names; idx_name++) {
+		entry = &stats->metadata[idx_name + stats->cnt_stats];
+		strncpy(entry->name, names[idx_name],
+			RTE_METRICS_MAX_NAME_LEN);
+		memset(entry->value, 0, sizeof(entry->value));
+		entry->idx_next_stat = idx_name + stats->cnt_stats + 1;
+	}
+	entry->idx_next_stat = 0;
+	entry->idx_next_set = 0;
+	stats->cnt_stats += cnt_names;
+
+	rte_spinlock_unlock(&stats->lock);
+
+	return idx_base;
+}
+
+
+int
+rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value)
+{
+	return rte_metrics_update_metrics(port_id, key, &value, 1);
+}
+
+
+int
+rte_metrics_update_metrics(int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_metric;
+	uint16_t idx_value;
+	uint16_t cnt_setsize;
+
+	if (port_id != RTE_METRICS_NONPORT &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	rte_metrics_init();
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	rte_spinlock_lock(&stats->lock);
+	idx_metric = key;
+	cnt_setsize = 1;
+	while (idx_metric < stats->cnt_stats) {
+		entry = &stats->metadata[idx_metric];
+		if (entry->idx_next_stat == 0)
+			break;
+		cnt_setsize++;
+		idx_metric++;
+	}
+	/* Check update does not cross set border */
+	if (count > cnt_setsize) {
+		rte_spinlock_unlock(&stats->lock);
+		return -ERANGE;
+	}
+
+	if (port_id == RTE_METRICS_NONPORT)
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].nonport_value =
+				values[idx_value];
+		}
+	else
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].value[port_id] =
+				values[idx_value];
+		}
+	rte_spinlock_unlock(&stats->lock);
+	return 0;
+}
+
+
+int
+rte_metrics_get_names(struct rte_metric_name *names,
+	uint16_t capacity)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+	if (names != NULL) {
+		if (capacity < stats->cnt_stats) {
+			rte_spinlock_unlock(&stats->lock);
+			return -ERANGE;
+		}
+		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
+			strncpy(names[idx_name].name,
+				stats->metadata[idx_name].name,
+				RTE_METRICS_MAX_NAME_LEN);
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
+
+
+int
+rte_metrics_get_values(int port_id,
+	struct rte_stat_value *values,
+	uint16_t capacity)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+
+	if (values != NULL) {
+		if (capacity < stats->cnt_stats) {
+			rte_spinlock_unlock(&stats->lock);
+			return -ERANGE;
+		}
+		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) {
+			entry = &stats->metadata[idx_name];
+			values[idx_name].key = idx_name;
+			values[idx_name].value = entry->value[port_id];
+		}
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
new file mode 100644
index 0000000..6b75404
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.h
@@ -0,0 +1,204 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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.
+ */
+
+/**
+ * @file
+ *
+ * RTE Statistics module
+ *
+ * Statistic information is populated using callbacks, each of which
+ * is associated with one or more metric names. When queried, the
+ * callback is used to update all metric in the set at once. Currently
+ * only bulk querying of all metric is supported.
+ *
+ */
+
+#ifndef _RTE_METRICS_H_
+#define _RTE_METRICS_H_
+
+/** Maximum length of statistic name (including null-terminator) */
+#define RTE_METRICS_MAX_NAME_LEN 64
+
+/** Used to indicate port-independent information */
+#define RTE_METRICS_NONPORT -1
+
+
+/**
+ * Statistic name
+ */
+struct rte_metric_name {
+	/** String describing statistic */
+	char name[RTE_METRICS_MAX_NAME_LEN];
+};
+
+
+/**
+ * Statistic name.
+ */
+struct rte_stat_value {
+	/** Numeric identifier of statistic */
+	uint16_t key;
+	/** Value for statistic */
+	uint64_t value;
+};
+
+
+/**
+ * Initialises statistic module. This only has to be explicitly called if you
+ * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a
+ * secondary process.
+ */
+void rte_metrics_init(void);
+
+
+/**
+ * Register a statistic and its associated callback.
+ *
+ * @param name
+ *   Statistic name
+ *
+ * @param callback
+ *   Callback to use when fetching statistic
+ *
+ * @param data
+ *   Data pointer to pass to callback
+ *
+ * @return
+ *  - Zero or positive: Success
+ *  - Negative: Failure
+ */
+int rte_metrics_reg_metric(const char *name);
+
+/**
+ * Register a set of statistic and their associated callback.
+ *
+ * @param names
+ *   List of statistic names
+ *
+ * @param cnt_names
+ *   Number of statistics in set
+ *
+ * @param callback
+ *   Callback to use when fetching statsitics
+ *
+ * @param data
+ *   Data pointer to pass to callback
+ *
+ * @return
+ *  - Zero or positive: Success
+ *  - Negative: Failure
+ */
+int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names);
+
+/**
+ * Get statistic name-key lookup table.
+ *
+ * @param names
+ *   Array of names to receive key names
+ *
+ * @param capacity
+ *   Space available in names
+ *
+ * @return
+ *   - Non-negative: Success (number of names)
+ *   - Negative: Failure
+ */
+int rte_metrics_get_names(
+	struct rte_metric_name *names,
+	uint16_t capacity);
+
+/**
+ * Fetch statistics.
+ *
+ * @param port_id
+ *   Port id to query
+ *
+ * @param values
+ *   Array to receive values and their keys
+ *
+ * @param capacity
+ *   Space available in values
+ *
+ * @return
+ *   - Non-negative: Success (number of names)
+ *   - Negative: Failure
+ */
+int rte_metrics_get_values(
+	int port_id,
+	struct rte_stat_value *values,
+	uint16_t capacity);
+
+/**
+ * Updates a statistic metric
+ *
+ * @param port_id
+ *   Port to update statistics for
+ * @param key
+ *   Id of statistic metric to update
+ * @param value
+ *   New value
+ *
+ * @return
+ *   - -EIO if unable to access shared statistics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_metric(
+	int port_id,
+	uint16_t key,
+	const uint64_t value);
+
+/**
+ * Updates a statistic metric set. Note that it is an error to try to
+ * update across a set boundary.
+ *
+ * @param port_id
+ *   Port to update statistics for
+ * @param key
+ *   Base id of statistics set to update
+ * @param values
+ *   Set of new values
+ * @param count
+ *   Number of new values
+ *
+ * @return
+ *   - -ERANGE if count exceeds statistic set size
+ *   - -EIO if upable to access shared statistics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_metrics(
+	int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count);
+
+#endif
diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map
new file mode 100644
index 0000000..a31a80a
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics_version.map
@@ -0,0 +1,13 @@
+DPDK_16.11 {
+	global:
+
+	rte_metrics_get_names;
+	rte_metrics_get_values;
+	rte_metrics_init;
+	rte_metrics_reg_metric;
+	rte_metrics_reg_metrics;
+	rte_metrics_update_metric;
+	rte_metrics_update_metrics;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 51bc3b0..2db5427 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -98,6 +98,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING)           += -lrte_ring
 _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
+_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* [PATCH v3 2/3] lib: add bitrate statistics library
  2016-11-04  3:36   ` [PATCH v3 0/3] Expanded statistics reporting Remy Horton
  2016-11-04  3:36     ` [PATCH v3 1/3] lib: add information metrics library Remy Horton
@ 2016-11-04  3:36     ` Remy Horton
  2016-11-04  3:36     ` [PATCH v3 3/3] app/test-pmd: add support for bitrate statistics Remy Horton
  2016-11-15  7:15     ` [PATCH v4 0/3] Expanded statistics reporting Remy Horton
  3 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2016-11-04  3:36 UTC (permalink / raw)
  To: dev

This patch adds a library that calculates peak and average data-rate
statistics. For ethernet devices. These statistics are reported using
the metrics library.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/rel_notes/release_16_11.rst             |   5 +
 lib/Makefile                                       |   1 +
 lib/librte_bitratestats/Makefile                   |  53 +++++++++
 lib/librte_bitratestats/rte_bitrate.c              | 128 +++++++++++++++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++++++++++
 .../rte_bitratestats_version.map                   |   9 ++
 mk/rte.app.mk                                      |   1 +
 10 files changed, 284 insertions(+)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map

diff --git a/config/common_base b/config/common_base
index 2277727..25c3911 100644
--- a/config/common_base
+++ b/config/common_base
@@ -594,3 +594,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
 # Compile the device metrics library
 #
 CONFIG_RTE_LIBRTE_METRICS=y
+
+#
+# Compile the bitrate statistics library
+#
+CONFIG_RTE_LIBRTE_BITRATE=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index ca50fa6..91e8ea6 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -148,4 +148,5 @@ There are many libraries, so their headers may be grouped by topics:
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
   [Device Metrics]     (@ref rte_metrics.h),
+  [Bitrate Statistics] (@ref rte_bitrate.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index fe830eb..8765ddd 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -58,6 +58,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_ring \
                           lib/librte_sched \
                           lib/librte_metrics \
+                          lib/librte_bitratestats \
                           lib/librte_table \
                           lib/librte_timer \
                           lib/librte_vhost
diff --git a/doc/guides/rel_notes/release_16_11.rst b/doc/guides/rel_notes/release_16_11.rst
index 507f715..b690b72 100644
--- a/doc/guides/rel_notes/release_16_11.rst
+++ b/doc/guides/rel_notes/release_16_11.rst
@@ -137,6 +137,11 @@ New Features
   intended to provide a reporting mechanism that is independent of the
   ethdev library.
 
+* **Added bit-rate calculation library.**
+
+  A library that can be used to calculate device bit-rates. Calculated
+  bitrates are reported using the metrics library.
+
 
 Resolved Issues
 ---------------
diff --git a/lib/Makefile b/lib/Makefile
index 5d85dcf..e211bc0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
+DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile
new file mode 100644
index 0000000..b725d4e
--- /dev/null
+++ b/lib/librte_bitratestats/Makefile
@@ -0,0 +1,53 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_bitratestats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_bitratestats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c
new file mode 100644
index 0000000..d97a526
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.c
@@ -0,0 +1,128 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
+
+/*
+ * Persistent bit-rate data.
+ * @internal
+ */
+struct rte_stats_bitrate_s {
+	uint64_t last_ibytes;
+	uint64_t last_obytes;
+	uint64_t peak_ibits;
+	uint64_t peak_obits;
+	uint64_t ewma_ibits;
+	uint64_t ewma_obits;
+};
+
+struct rte_stats_bitrates_s {
+	struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS];
+	uint16_t id_stats_set;
+};
+
+
+struct rte_stats_bitrates_s *
+rte_stats_bitrate_create(void)
+{
+	return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0);
+}
+
+
+int
+rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data)
+{
+	const char *names[] = {
+		"mean_bits_in", "mean_bits_out",
+		"peak_bits_in", "peak_bits_out",
+	};
+	int return_value;
+
+	return_value = rte_metrics_reg_metrics(&names[0], 4);
+	if (return_value >= 0)
+		bitrate_data->id_stats_set = return_value;
+	return return_value;
+}
+
+
+int
+rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
+	uint8_t port_id)
+{
+	struct rte_stats_bitrate_s *port_data;
+	struct rte_eth_stats eth_stats;
+	int ret_code;
+	uint64_t cnt_bits;
+	int64_t delta;
+	const int64_t alpha_percent = 20;
+	uint64_t values[4];
+
+	ret_code = rte_eth_stats_get(port_id, &eth_stats);
+	if (ret_code != 0)
+		return ret_code;
+
+	port_data = &bitrate_data->port_stats[port_id];
+
+	/* Incoming */
+	cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3;
+	port_data->last_ibytes = eth_stats.ibytes;
+	if (cnt_bits > port_data->peak_ibits)
+		port_data->peak_ibits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_ibits;
+	/* The +50 fixes integer rounding during divison */
+	delta = (delta * alpha_percent + 50) / 100;
+	port_data->ewma_ibits += delta;
+
+	/* Outgoing */
+	cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3;
+	port_data->last_obytes = eth_stats.obytes;
+	if (cnt_bits > port_data->peak_obits)
+		port_data->peak_obits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_obits;
+	delta = (delta * alpha_percent + 50) / 100;
+	port_data->ewma_obits += delta;
+
+	values[0] = port_data->ewma_ibits;
+	values[1] = port_data->ewma_obits;
+	values[2] = port_data->peak_ibits;
+	values[3] = port_data->peak_obits;
+	rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set,
+		values, 4);
+	return 0;
+}
diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h
new file mode 100644
index 0000000..cd566d6
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.h
@@ -0,0 +1,80 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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.
+ */
+
+
+
+/**
+ *  Bitrate statistics data structure
+ */
+struct rte_stats_bitrates_s;
+
+
+/**
+ * Allocate a bitrate statistics structure
+ *
+ * @return
+ *   - Pointer to structure on success
+ *   - NULL on error (zmalloc failure)
+ */
+struct rte_stats_bitrates_s *rte_stats_bitrate_create(void);
+
+
+/**
+ * Register bitrate statistics
+ *
+ * @param bitrate_data
+ *   Pointer allocated by rte_stats_create()
+ *
+ * @return
+ *   Zero on success
+ *   Negative on error
+ */
+int rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data);
+
+
+/**
+ * Calculate statistics for current time window. The period this function
+ * is called should be the intended time window width.
+ *
+ * @param bitrate_data
+ *   Bitrate statistics data pointer
+ *
+ * @param port_id
+ *   Port id to calculate statistics for
+ *
+ * @return
+ *  - Zero on success
+ *  - Negative value on error
+ */
+int rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
+	uint8_t port_id);
diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map
new file mode 100644
index 0000000..9de6be9
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitratestats_version.map
@@ -0,0 +1,9 @@
+DPDK_16.11 {
+	global:
+
+	rte_stats_bitrate_calc;
+	rte_stats_bitrate_create;
+	rte_stats_bitrate_reg;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 2db5427..5b5e547 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -99,6 +99,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
 
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
-- 
2.5.5

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

* [PATCH v3 3/3] app/test-pmd: add support for bitrate statistics
  2016-11-04  3:36   ` [PATCH v3 0/3] Expanded statistics reporting Remy Horton
  2016-11-04  3:36     ` [PATCH v3 1/3] lib: add information metrics library Remy Horton
  2016-11-04  3:36     ` [PATCH v3 2/3] lib: add bitrate statistics library Remy Horton
@ 2016-11-04  3:36     ` Remy Horton
  2016-11-15  7:15     ` [PATCH v4 0/3] Expanded statistics reporting Remy Horton
  3 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2016-11-04  3:36 UTC (permalink / raw)
  To: dev

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/testpmd.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 6185be6..3cf4795 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -78,6 +78,8 @@
 #ifdef RTE_LIBRTE_PDUMP
 #include <rte_pdump.h>
 #endif
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
 
 #include "testpmd.h"
 
@@ -322,6 +324,9 @@ uint16_t nb_rx_queue_stats_mappings = 0;
 
 unsigned max_socket = 0;
 
+/* Bitrate statistics */
+struct rte_stats_bitrates_s *bitrate_data;
+
 /* Forward function declarations */
 static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -921,12 +926,26 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
 	struct fwd_stream **fsm;
 	streamid_t nb_fs;
 	streamid_t sm_id;
-
+	uint64_t tics_per_1sec;
+	uint64_t tics_datum;
+	uint64_t tics_current;
+	uint8_t idx_port, cnt_ports;
+
+	cnt_ports = rte_eth_dev_count();
+	tics_datum = rte_rdtsc();
+	tics_per_1sec = rte_get_timer_hz();
 	fsm = &fwd_streams[fc->stream_idx];
 	nb_fs = fc->stream_nb;
 	do {
 		for (sm_id = 0; sm_id < nb_fs; sm_id++)
 			(*pkt_fwd)(fsm[sm_id]);
+		tics_current = rte_rdtsc();
+		if (tics_current - tics_datum >= tics_per_1sec) {
+			/* Periodic bitrate calculation */
+			for (idx_port = 0; idx_port < cnt_ports; idx_port++)
+				rte_stats_bitrate_calc(bitrate_data, idx_port);
+			tics_datum = tics_current;
+		}
 	} while (! fc->stopped);
 }
 
@@ -2128,6 +2147,13 @@ main(int argc, char** argv)
 	FOREACH_PORT(port_id, ports)
 		rte_eth_promiscuous_enable(port_id);
 
+	/* Setup bitrate stats */
+	bitrate_data = rte_stats_bitrate_create();
+	if (bitrate_data == NULL)
+		rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n");
+	rte_stats_bitrate_reg(bitrate_data);
+
+
 #ifdef RTE_LIBRTE_CMDLINE
 	if (interactive == 1) {
 		if (auto_start) {
-- 
2.5.5

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

* Re: [PATCH v3 1/3] lib: add information metrics library
  2016-11-04  3:36     ` [PATCH v3 1/3] lib: add information metrics library Remy Horton
@ 2016-11-04 16:42       ` Pattan, Reshma
  2016-11-07 15:25         ` Pattan, Reshma
  0 siblings, 1 reply; 115+ messages in thread
From: Pattan, Reshma @ 2016-11-04 16:42 UTC (permalink / raw)
  To: Horton, Remy; +Cc: dev

Hi,

Few comments below.

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Friday, November 4, 2016 3:36 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v3 1/3] lib: add information metrics library
> 
> This patch adds a new information metric library that allows other modules
> to register named metrics and update their values. It is intended to be
> independent of ethdev, rather than mixing ethdev and non-ethdev
> information in xstats.
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>
> ---
> +int
> +
> +int
> +rte_metrics_get_values(int port_id,
> +	struct rte_stat_value *values,
> +	uint16_t capacity)
> +{
> +	struct rte_metrics_meta_s *entry;
> +	struct rte_metrics_data_s *stats;
> +	const struct rte_memzone *memzone;
> +	uint16_t idx_name;
> +	int return_value;
> +
> +	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
> +	/* If not allocated, fail silently */
> +	if (memzone == NULL)
> +		return 0;
> +	stats = memzone->addr;
> +	rte_spinlock_lock(&stats->lock);
> +
> +	if (values != NULL) {
> +		if (capacity < stats->cnt_stats) {
> +			rte_spinlock_unlock(&stats->lock);
> +			return -ERANGE;
> +		}
> +		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
> {
> +			entry = &stats->metadata[idx_name];
> +			values[idx_name].key = idx_name;
> +			values[idx_name].value = entry->value[port_id];
> +		}

Here you also  need to include logic to return values for  port independent metrics.

> diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
> new file mode 100644
> index 0000000..6b75404
> --- /dev/null
> +++ b/lib/librte_metrics/rte_metrics.h
> @@ -0,0 +1,204 @@
> +/**
> + * Statistic name
> + */
> +struct rte_metric_name {
> +	/** String describing statistic */
> +	char name[RTE_METRICS_MAX_NAME_LEN];
> +};
> +
> +
> +/**
> + * Statistic name.
> + */

Need to correct the description to "stats values" or "metric values."

> +struct rte_stat_value {

Need to change the name to rte_metric_value.

> +	/** Numeric identifier of statistic */
> +	uint16_t key;
> +	/** Value for statistic */
> +	uint64_t value;
> +};
> +
> +
> +/**
> + * Initialises statistic module. This only has to be explicitly called

Typo < Initialises>

Thanks,
Reshma

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

* Re: [PATCH v3 1/3] lib: add information metrics library
  2016-11-04 16:42       ` Pattan, Reshma
@ 2016-11-07 15:25         ` Pattan, Reshma
  2016-11-08  3:19           ` Remy Horton
  0 siblings, 1 reply; 115+ messages in thread
From: Pattan, Reshma @ 2016-11-07 15:25 UTC (permalink / raw)
  To: Horton, Remy; +Cc: 'dev@dpdk.org'

Hi,

> -----Original Message-----
> From: Pattan, Reshma
> Sent: Friday, November 4, 2016 4:43 PM
> To: Remy Horton <remy.horton@intel.com>
> Cc: dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH v3 1/3] lib: add information metrics library
> 
> Hi,
> 
> Few comments below.
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> > Sent: Friday, November 4, 2016 3:36 AM
> > To: dev@dpdk.org
> > Subject: [dpdk-dev] [PATCH v3 1/3] lib: add information metrics
> > library
> >
> > This patch adds a new information metric library that allows other
> > modules to register named metrics and update their values. It is
> > intended to be independent of ethdev, rather than mixing ethdev and
> > non-ethdev information in xstats.
> >
> > Signed-off-by: Remy Horton <remy.horton@intel.com>
> > ---
> > +int
> > +
> > +int
> > +rte_metrics_get_values(int port_id,
> > +	struct rte_stat_value *values,
> > +	uint16_t capacity)
> > +{
> > +	struct rte_metrics_meta_s *entry;
> > +	struct rte_metrics_data_s *stats;
> > +	const struct rte_memzone *memzone;
> > +	uint16_t idx_name;
> > +	int return_value;
> > +
> > +	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
> > +	/* If not allocated, fail silently */
> > +	if (memzone == NULL)
> > +		return 0;
> > +	stats = memzone->addr;
> > +	rte_spinlock_lock(&stats->lock);
> > +
> > +	if (values != NULL) {
> > +		if (capacity < stats->cnt_stats) {
> > +			rte_spinlock_unlock(&stats->lock);
> > +			return -ERANGE;
> > +		}
> > +		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
> > {
> > +			entry = &stats->metadata[idx_name];
> > +			values[idx_name].key = idx_name;
> > +			values[idx_name].value = entry->value[port_id];
> > +		}
> 
> Here you also  need to include logic to return values for  port independent
> metrics.
> 
> > diff --git a/lib/librte_metrics/rte_metrics.h
> > b/lib/librte_metrics/rte_metrics.h
> > new file mode 100644
> > index 0000000..6b75404
> > --- /dev/null
> > +++ b/lib/librte_metrics/rte_metrics.h
> > @@ -0,0 +1,204 @@
> > +/**
> > + * Statistic name
> > + */
> > +struct rte_metric_name {
> > +	/** String describing statistic */
> > +	char name[RTE_METRICS_MAX_NAME_LEN]; };
> > +
> > +
> > +/**
> > + * Statistic name.
> > + */
> 
> Need to correct the description to "stats values" or "metric values."
> 
> > +struct rte_stat_value {
> 
> Need to change the name to rte_metric_value.
> 
> > +	/** Numeric identifier of statistic */
> > +	uint16_t key;
> > +	/** Value for statistic */
> > +	uint64_t value;
> > +};
> > +
> > +
> > +/**
> > + * Initialises statistic module. This only has to be explicitly
> > +called
> 
> Typo < Initialises>

To avoid confusion, here I mean to say "Initializes" should be used (i.e. US English) .
Also another non-related comment, you may need to add a comment about EMWA
near the mean bit rate calculation code.

> 
> Thanks,
> Reshma

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

* Re: [PATCH v3 1/3] lib: add information metrics library
  2016-11-07 15:25         ` Pattan, Reshma
@ 2016-11-08  3:19           ` Remy Horton
  0 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2016-11-08  3:19 UTC (permalink / raw)
  To: Pattan, Reshma; +Cc: dev


On 07/11/2016 23:25, Pattan, Reshma wrote:
[..]
>>> + * Initialises statistic module. This only has to be explicitly
>>> +called
>>
>> Typo < Initialises>
>
> To avoid confusion, here I mean to say "Initializes" should be used (i.e. US English) .

Sorta guessed that.. :)


> Also another non-related comment, you may need to add a comment about EMWA
> near the mean bit rate calculation code.

Quite a few comments needed updating. Going to hold off the v5 until 
16.11 is out as I'll also need to change all the references to 17.02..

..Remy

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

* [PATCH v4 0/3] Expanded statistics reporting
  2016-11-04  3:36   ` [PATCH v3 0/3] Expanded statistics reporting Remy Horton
                       ` (2 preceding siblings ...)
  2016-11-04  3:36     ` [PATCH v3 3/3] app/test-pmd: add support for bitrate statistics Remy Horton
@ 2016-11-15  7:15     ` Remy Horton
  2016-11-15  7:15       ` [PATCH v4 1/3] lib: add information metrics library Remy Horton
                         ` (3 more replies)
  3 siblings, 4 replies; 115+ messages in thread
From: Remy Horton @ 2016-11-15  7:15 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon

This patchset extends statistics reporting to include peak and
average data-rate metrics. It comes in two parts: a statistics
reporting library, and a bitrate calculation library that uses
it. This structure is intended to seperate statistic reporting
from ethdev and allow more flexible metric registration.

--

v4 changes:
* References to 16.11 changed to 17.02
* Fetching of non-port values was broken
* Added sanity checks to value fetching
* rte_stat_value renamed to rte_metric_value
* Corrected doxygen descriptions
* Added MAINTAINERS entries
* Added #ifdef directives to bitrate code in test-pmd

v3 changes:
* Marked rte_stats_bitrate_s as internal
* Minor integer roundoff correction
* Coding style corrections
* Removed spurious object allocation
* Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3.
* Reintroduced non-port values (RTE_METRICS_NONPORT)
* Added spinlocks to metric library
* Removed spurious test registration/update
* Added release notes entries

v2 changes:
* Uses a new metrics library rather than being part of ethdev


Remy Horton (3):
  lib: add information metrics library
  lib: add bitrate statistics library
  app/test-pmd: add support for bitrate statistics

 MAINTAINERS                                        |   9 +
 app/test-pmd/testpmd.c                             |  36 +++
 config/common_base                                 |  10 +
 doc/api/doxy-api-index.md                          |   2 +
 doc/api/doxy-api.conf                              |   2 +
 doc/guides/rel_notes/release_17_02.rst             |  11 +
 lib/Makefile                                       |   2 +
 lib/librte_bitratestats/Makefile                   |  53 ++++
 lib/librte_bitratestats/rte_bitrate.c              | 128 +++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 ++++++
 .../rte_bitratestats_version.map                   |   9 +
 lib/librte_metrics/Makefile                        |  51 ++++
 lib/librte_metrics/rte_metrics.c                   | 308 +++++++++++++++++++++
 lib/librte_metrics/rte_metrics.h                   | 190 +++++++++++++
 lib/librte_metrics/rte_metrics_version.map         |  13 +
 mk/rte.app.mk                                      |   3 +
 16 files changed, 907 insertions(+)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

-- 
2.5.5

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

* [PATCH v4 1/3] lib: add information metrics library
  2016-11-15  7:15     ` [PATCH v4 0/3] Expanded statistics reporting Remy Horton
@ 2016-11-15  7:15       ` Remy Horton
  2016-11-15  7:15       ` [PATCH v4 2/3] lib: add bitrate statistics library Remy Horton
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2016-11-15  7:15 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon

This patch adds a new information metric library that allows other
modules to register named metrics and update their values. It is
intended to be independent of ethdev, rather than mixing ethdev
and non-ethdev information in xstats.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                |   5 +
 config/common_base                         |   5 +
 doc/api/doxy-api-index.md                  |   1 +
 doc/api/doxy-api.conf                      |   1 +
 doc/guides/rel_notes/release_17_02.rst     |   6 +
 lib/Makefile                               |   1 +
 lib/librte_metrics/Makefile                |  51 +++++
 lib/librte_metrics/rte_metrics.c           | 308 +++++++++++++++++++++++++++++
 lib/librte_metrics/rte_metrics.h           | 190 ++++++++++++++++++
 lib/librte_metrics/rte_metrics_version.map |  13 ++
 mk/rte.app.mk                              |   2 +
 11 files changed, 583 insertions(+)
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index d6bb8f8..52bd8a9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -595,6 +595,11 @@ F: lib/librte_jobstats/
 F: examples/l2fwd-jobstats/
 F: doc/guides/sample_app_ug/l2_forward_job_stats.rst
 
+Metrics
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_metrics/
+F: doc/guides/sample_app_ug/keep_alive.rst
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index 4bff83a..dedc4c3 100644
--- a/config/common_base
+++ b/config/common_base
@@ -589,3 +589,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
 CONFIG_RTE_TEST_PMD=y
 CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
 CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+
+#
+# Compile the device metrics library
+#
+CONFIG_RTE_LIBRTE_METRICS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 6675f96..ca50fa6 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -147,4 +147,5 @@ There are many libraries, so their headers may be grouped by topics:
   [common]             (@ref rte_common.h),
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
+  [Device Metrics]     (@ref rte_metrics.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index 9dc7ae5..fe830eb 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -57,6 +57,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_reorder \
                           lib/librte_ring \
                           lib/librte_sched \
+                          lib/librte_metrics \
                           lib/librte_table \
                           lib/librte_timer \
                           lib/librte_vhost
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 3b65038..e1b8894 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -34,6 +34,12 @@ New Features
 
      Refer to the previous release notes for examples.
 
+   * **Added information metric library.**
+
+     A library that allows information metrics to be added and update. It is
+     intended to provide a reporting mechanism that is independent of the
+     ethdev library.
+
      This section is a comment. do not overwrite or remove it.
      Also, make sure to start the actual text at the margin.
      =========================================================
diff --git a/lib/Makefile b/lib/Makefile
index 990f23a..5d85dcf 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table
 DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
+DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile
new file mode 100644
index 0000000..8d6e23a
--- /dev/null
+++ b/lib/librte_metrics/Makefile
@@ -0,0 +1,51 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_metrics.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_metrics_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c
new file mode 100644
index 0000000..5edacc6
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.c
@@ -0,0 +1,308 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <string.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_lcore.h>
+#include <rte_memzone.h>
+#include <rte_spinlock.h>
+
+#define RTE_METRICS_MAX_METRICS 256
+#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS"
+
+/**
+ * Internal stats metadata and value entry.
+ *
+ * @internal
+ * @param name
+ *   Name of metric
+ * @param value
+ *   Current value for metric
+ * @param idx_next_set
+ *   Index of next root element (zero for none)
+ * @param idx_next_metric
+ *   Index of next metric in set (zero for none)
+ *
+ * Only the root of each set needs idx_next_set but since it has to be
+ * assumed that number of sets could equal total number of metrics,
+ * having a separate set metadata table doesn't save any memory.
+ */
+struct rte_metrics_meta_s {
+	char name[RTE_METRICS_MAX_NAME_LEN];
+	uint64_t value[RTE_MAX_ETHPORTS];
+	uint64_t nonport_value;
+	uint16_t idx_next_set;
+	uint16_t idx_next_stat;
+};
+
+/**
+ * Internal stats info structure.
+ *
+ * @internal
+ * @param idx_last_set
+ *   Index of last metadata entry with valid data. This value is
+ *   not valid if cnt_stats is zero.
+ * @param cnt_stats
+ *   Number of metrics.
+ * @param metadata
+ *   Stat data memory block.
+ *
+ * Offsets into metadata are used instead of pointers because ASLR
+ * means that having the same physical addresses in different
+ * processes is not guaranteed.
+ */
+struct rte_metrics_data_s {
+	uint16_t idx_last_set;
+	uint16_t cnt_stats;
+	struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS];
+	rte_spinlock_t lock;
+};
+
+void
+rte_metrics_init(void)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone != NULL)
+		return;
+	memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME,
+		sizeof(struct rte_metrics_data_s), rte_socket_id(), 0);
+	if (memzone == NULL)
+		rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
+	stats = memzone->addr;
+	memset(stats, 0, sizeof(struct rte_metrics_data_s));
+	rte_spinlock_init(&stats->lock);
+}
+
+int
+rte_metrics_reg_metric(const char *name)
+{
+	const char *list_names[] = {name};
+
+	return rte_metrics_reg_metrics(list_names, 1);
+}
+
+int
+rte_metrics_reg_metrics(const char **names, uint16_t cnt_names)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	uint16_t idx_base;
+
+	/* Some sanity checks */
+	if (cnt_names < 1 || names == NULL)
+		return -EINVAL;
+
+	rte_metrics_init();
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS)
+		return -ENOMEM;
+
+	rte_spinlock_lock(&stats->lock);
+
+	/* Overwritten later if this is actually first set.. */
+	stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats;
+
+	stats->idx_last_set = idx_base = stats->cnt_stats;
+
+	for (idx_name = 0; idx_name < cnt_names; idx_name++) {
+		entry = &stats->metadata[idx_name + stats->cnt_stats];
+		strncpy(entry->name, names[idx_name],
+			RTE_METRICS_MAX_NAME_LEN);
+		memset(entry->value, 0, sizeof(entry->value));
+		entry->idx_next_stat = idx_name + stats->cnt_stats + 1;
+	}
+	entry->idx_next_stat = 0;
+	entry->idx_next_set = 0;
+	stats->cnt_stats += cnt_names;
+
+	rte_spinlock_unlock(&stats->lock);
+
+	return idx_base;
+}
+
+int
+rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value)
+{
+	return rte_metrics_update_metrics(port_id, key, &value, 1);
+}
+
+int
+rte_metrics_update_metrics(int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_metric;
+	uint16_t idx_value;
+	uint16_t cnt_setsize;
+
+	if (port_id != RTE_METRICS_NONPORT &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	rte_metrics_init();
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	rte_spinlock_lock(&stats->lock);
+	idx_metric = key;
+	cnt_setsize = 1;
+	while (idx_metric < stats->cnt_stats) {
+		entry = &stats->metadata[idx_metric];
+		if (entry->idx_next_stat == 0)
+			break;
+		cnt_setsize++;
+		idx_metric++;
+	}
+	/* Check update does not cross set border */
+	if (count > cnt_setsize) {
+		rte_spinlock_unlock(&stats->lock);
+		return -ERANGE;
+	}
+
+	if (port_id == RTE_METRICS_NONPORT)
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].nonport_value =
+				values[idx_value];
+		}
+	else
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].value[port_id] =
+				values[idx_value];
+		}
+	rte_spinlock_unlock(&stats->lock);
+	return 0;
+}
+
+int
+rte_metrics_get_names(struct rte_metric_name *names,
+	uint16_t capacity)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+	if (names != NULL) {
+		if (capacity < stats->cnt_stats) {
+			rte_spinlock_unlock(&stats->lock);
+			return -ERANGE;
+		}
+		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
+			strncpy(names[idx_name].name,
+				stats->metadata[idx_name].name,
+				RTE_METRICS_MAX_NAME_LEN);
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
+
+int
+rte_metrics_get_values(int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	if (port_id != RTE_METRICS_NONPORT &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+
+	if (values != NULL) {
+		if (capacity < stats->cnt_stats) {
+			rte_spinlock_unlock(&stats->lock);
+			return -ERANGE;
+		}
+		if (port_id == RTE_METRICS_NONPORT)
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->nonport_value;
+			}
+		else
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->value[port_id];
+			}
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
new file mode 100644
index 0000000..c58b366
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.h
@@ -0,0 +1,190 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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.
+ */
+
+/**
+ * @file
+ *
+ * RTE Metrics module
+ *
+ * Metric information is populated using a push model, where the
+ * information provider calls an update function on the relevant
+ * metrics. Currently only bulk querying of metrics is supported.
+ */
+
+#ifndef _RTE_METRICS_H_
+#define _RTE_METRICS_H_
+
+/** Maximum length of metric name (including null-terminator) */
+#define RTE_METRICS_MAX_NAME_LEN 64
+
+/** Used to indicate port-independent information */
+#define RTE_METRICS_NONPORT -1
+
+
+/**
+ * Metric name
+ */
+struct rte_metric_name {
+	/** String describing metric */
+	char name[RTE_METRICS_MAX_NAME_LEN];
+};
+
+
+/**
+ * Metric name.
+ */
+struct rte_metric_value {
+	/** Numeric identifier of metric */
+	uint16_t key;
+	/** Value for metric */
+	uint64_t value;
+};
+
+
+/**
+ * Initializes metric module. This only has to be explicitly called if you
+ * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a
+ * secondary process. This function must be called from a primary process.
+ */
+void rte_metrics_init(void);
+
+
+/**
+ * Register a metric
+ *
+ * @param name
+ *   Metric name
+ *
+ * @return
+ *  - Zero or positive: Success
+ *  - Negative: Failure
+ */
+int rte_metrics_reg_metric(const char *name);
+
+/**
+ * Register a set of metrics
+ *
+ * @param names
+ *   List of metric names
+ *
+ * @param cnt_names
+ *   Number of metrics in set
+ *
+ * @return
+ *  - Zero or positive: Success
+ *  - Negative: Failure
+ */
+int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names);
+
+/**
+ * Get metric name-key lookup table.
+ *
+ * @param names
+ *   Array of names to receive key names
+ *
+ * @param capacity
+ *   Space available in names
+ *
+ * @return
+ *   - Non-negative: Success (number of names)
+ *   - Negative: Failure
+ */
+int rte_metrics_get_names(
+	struct rte_metric_name *names,
+	uint16_t capacity);
+
+/**
+ * Fetch metrics.
+ *
+ * @param port_id
+ *   Port id to query
+ *
+ * @param values
+ *   Array to receive values and their keys
+ *
+ * @param capacity
+ *   Space available in values
+ *
+ * @return
+ *   - Non-negative: Success (number of names)
+ *   - Negative: Failure
+ */
+int rte_metrics_get_values(
+	int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity);
+
+/**
+ * Updates a metric
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Id of metric to update
+ * @param value
+ *   New value
+ *
+ * @return
+ *   - -EIO if unable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_metric(
+	int port_id,
+	uint16_t key,
+	const uint64_t value);
+
+/**
+ * Updates a metric set. Note that it is an error to try to
+ * update across a set boundary.
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Base id of metrics set to update
+ * @param values
+ *   Set of new values
+ * @param count
+ *   Number of new values
+ *
+ * @return
+ *   - -ERANGE if count exceeds metric set size
+ *   - -EIO if upable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_metrics(
+	int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count);
+
+#endif
diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map
new file mode 100644
index 0000000..f904814
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics_version.map
@@ -0,0 +1,13 @@
+DPDK_17.02 {
+	global:
+
+	rte_metrics_get_names;
+	rte_metrics_get_values;
+	rte_metrics_init;
+	rte_metrics_reg_metric;
+	rte_metrics_reg_metrics;
+	rte_metrics_update_metric;
+	rte_metrics_update_metrics;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index f75f0e2..40fcf33 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -98,6 +98,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING)           += -lrte_ring
 _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
+_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* [PATCH v4 2/3] lib: add bitrate statistics library
  2016-11-15  7:15     ` [PATCH v4 0/3] Expanded statistics reporting Remy Horton
  2016-11-15  7:15       ` [PATCH v4 1/3] lib: add information metrics library Remy Horton
@ 2016-11-15  7:15       ` Remy Horton
  2016-11-15 15:17         ` Pattan, Reshma
  2016-11-15  7:15       ` [PATCH v4 3/3] app/test-pmd: add support for bitrate statistics Remy Horton
  2016-11-18  8:00       ` [PATCH v5 0/4] Expanded statistics reporting Remy Horton
  3 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2016-11-15  7:15 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon

This patch adds a library that calculates peak and average data-rate
statistics. For ethernet devices. These statistics are reported using
the metrics library.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                        |   4 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/rel_notes/release_17_02.rst             |   5 +
 lib/Makefile                                       |   1 +
 lib/librte_bitratestats/Makefile                   |  53 +++++++++
 lib/librte_bitratestats/rte_bitrate.c              | 128 +++++++++++++++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++++++++++
 .../rte_bitratestats_version.map                   |   9 ++
 mk/rte.app.mk                                      |   1 +
 11 files changed, 288 insertions(+)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 52bd8a9..d6bbdd5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -600,6 +600,10 @@ M: Remy Horton <remy.horton@intel.com>
 F: lib/librte_metrics/
 F: doc/guides/sample_app_ug/keep_alive.rst
 
+Bit-rate statistica
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_bitratestats/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index dedc4c3..beca7ec 100644
--- a/config/common_base
+++ b/config/common_base
@@ -594,3 +594,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
 # Compile the device metrics library
 #
 CONFIG_RTE_LIBRTE_METRICS=y
+
+#
+# Compile the bitrate statistics library
+#
+CONFIG_RTE_LIBRTE_BITRATE=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index ca50fa6..91e8ea6 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -148,4 +148,5 @@ There are many libraries, so their headers may be grouped by topics:
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
   [Device Metrics]     (@ref rte_metrics.h),
+  [Bitrate Statistics] (@ref rte_bitrate.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index fe830eb..8765ddd 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -58,6 +58,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_ring \
                           lib/librte_sched \
                           lib/librte_metrics \
+                          lib/librte_bitratestats \
                           lib/librte_table \
                           lib/librte_timer \
                           lib/librte_vhost
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index e1b8894..f949e88 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -40,6 +40,11 @@ New Features
      intended to provide a reporting mechanism that is independent of the
      ethdev library.
 
+   * **Added bit-rate calculation library.**
+
+     A library that can be used to calculate device bit-rates. Calculated
+     bitrates are reported using the metrics library.
+
      This section is a comment. do not overwrite or remove it.
      Also, make sure to start the actual text at the margin.
      =========================================================
diff --git a/lib/Makefile b/lib/Makefile
index 5d85dcf..e211bc0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
+DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile
new file mode 100644
index 0000000..b725d4e
--- /dev/null
+++ b/lib/librte_bitratestats/Makefile
@@ -0,0 +1,53 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_bitratestats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_bitratestats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c
new file mode 100644
index 0000000..6346bb1
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.c
@@ -0,0 +1,128 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
+
+/*
+ * Persistent bit-rate data.
+ * @internal
+ */
+struct rte_stats_bitrate_s {
+	uint64_t last_ibytes;
+	uint64_t last_obytes;
+	uint64_t peak_ibits;
+	uint64_t peak_obits;
+	uint64_t ewma_ibits;
+	uint64_t ewma_obits;
+};
+
+struct rte_stats_bitrates_s {
+	struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS];
+	uint16_t id_stats_set;
+};
+
+struct rte_stats_bitrates_s *
+rte_stats_bitrate_create(void)
+{
+	return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0);
+}
+
+int
+rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data)
+{
+	const char *names[] = {
+		"mean_bits_in", "mean_bits_out",
+		"peak_bits_in", "peak_bits_out",
+	};
+	int return_value;
+
+	return_value = rte_metrics_reg_metrics(&names[0], 4);
+	if (return_value >= 0)
+		bitrate_data->id_stats_set = return_value;
+	return return_value;
+}
+
+int
+rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
+	uint8_t port_id)
+{
+	struct rte_stats_bitrate_s *port_data;
+	struct rte_eth_stats eth_stats;
+	int ret_code;
+	uint64_t cnt_bits;
+	int64_t delta;
+	const int64_t alpha_percent = 20;
+	uint64_t values[4];
+
+	ret_code = rte_eth_stats_get(port_id, &eth_stats);
+	if (ret_code != 0)
+		return ret_code;
+
+	port_data = &bitrate_data->port_stats[port_id];
+
+	/* Incoming bitrate. This is an iteratively calculated EWMA
+	 * (Expomentially Weighted Moving Average) that uses a
+	 * weighting factor of alpha_percent.
+	 */
+	cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3;
+	port_data->last_ibytes = eth_stats.ibytes;
+	if (cnt_bits > port_data->peak_ibits)
+		port_data->peak_ibits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_ibits;
+	/* The +50 fixes integer rounding during divison */
+	delta = (delta * alpha_percent + 50) / 100;
+	port_data->ewma_ibits += delta;
+
+	/* Outgoing bitrate (also EWMA) */
+	cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3;
+	port_data->last_obytes = eth_stats.obytes;
+	if (cnt_bits > port_data->peak_obits)
+		port_data->peak_obits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_obits;
+	delta = (delta * alpha_percent + 50) / 100;
+	port_data->ewma_obits += delta;
+
+	values[0] = port_data->ewma_ibits;
+	values[1] = port_data->ewma_obits;
+	values[2] = port_data->peak_ibits;
+	values[3] = port_data->peak_obits;
+	rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set,
+		values, 4);
+	return 0;
+}
diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h
new file mode 100644
index 0000000..bc87c5e
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.h
@@ -0,0 +1,80 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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.
+ */
+
+
+/**
+ *  Bitrate statistics data structure.
+ *  This data structure is intentionally opaque.
+ */
+struct rte_stats_bitrates_s;
+
+
+/**
+ * Allocate a bitrate statistics structure
+ *
+ * @return
+ *   - Pointer to structure on success
+ *   - NULL on error (zmalloc failure)
+ */
+struct rte_stats_bitrates_s *rte_stats_bitrate_create(void);
+
+
+/**
+ * Register bitrate statistics with the metric library.
+ *
+ * @param bitrate_data
+ *   Pointer allocated by rte_stats_create()
+ *
+ * @return
+ *   Zero on success
+ *   Negative on error
+ */
+int rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data);
+
+
+/**
+ * Calculate statistics for current time window. The period with which
+ * this function is called should be the intended sampling window width.
+ *
+ * @param bitrate_data
+ *   Bitrate statistics data pointer
+ *
+ * @param port_id
+ *   Port id to calculate statistics for
+ *
+ * @return
+ *  - Zero on success
+ *  - Negative value on error
+ */
+int rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
+	uint8_t port_id);
diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map
new file mode 100644
index 0000000..66f232f
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitratestats_version.map
@@ -0,0 +1,9 @@
+DPDK_17.02 {
+	global:
+
+	rte_stats_bitrate_calc;
+	rte_stats_bitrate_create;
+	rte_stats_bitrate_reg;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 40fcf33..6aac5ac 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -99,6 +99,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
 
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
-- 
2.5.5

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

* [PATCH v4 3/3] app/test-pmd: add support for bitrate statistics
  2016-11-15  7:15     ` [PATCH v4 0/3] Expanded statistics reporting Remy Horton
  2016-11-15  7:15       ` [PATCH v4 1/3] lib: add information metrics library Remy Horton
  2016-11-15  7:15       ` [PATCH v4 2/3] lib: add bitrate statistics library Remy Horton
@ 2016-11-15  7:15       ` Remy Horton
  2016-11-18  8:00       ` [PATCH v5 0/4] Expanded statistics reporting Remy Horton
  3 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2016-11-15  7:15 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/testpmd.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index a0332c2..60c635f 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -78,6 +78,10 @@
 #ifdef RTE_LIBRTE_PDUMP
 #include <rte_pdump.h>
 #endif
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_BITRATE
+#include <rte_bitrate.h>
+#endif
 
 #include "testpmd.h"
 
@@ -322,6 +326,9 @@ uint16_t nb_rx_queue_stats_mappings = 0;
 
 unsigned max_socket = 0;
 
+/* Bitrate statistics */
+struct rte_stats_bitrates_s *bitrate_data;
+
 /* Forward function declarations */
 static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -921,12 +928,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
 	struct fwd_stream **fsm;
 	streamid_t nb_fs;
 	streamid_t sm_id;
+#ifdef RTE_LIBRTE_BITRATE
+	uint64_t tics_per_1sec;
+	uint64_t tics_datum;
+	uint64_t tics_current;
+	uint8_t idx_port, cnt_ports;
+#endif
 
+#ifdef RTE_LIBRTE_BITRATE
+	cnt_ports = rte_eth_dev_count();
+	tics_datum = rte_rdtsc();
+	tics_per_1sec = rte_get_timer_hz();
+#endif
 	fsm = &fwd_streams[fc->stream_idx];
 	nb_fs = fc->stream_nb;
 	do {
 		for (sm_id = 0; sm_id < nb_fs; sm_id++)
 			(*pkt_fwd)(fsm[sm_id]);
+#ifdef RTE_LIBRTE_BITRATE
+		tics_current = rte_rdtsc();
+		if (tics_current - tics_datum >= tics_per_1sec) {
+			/* Periodic bitrate calculation */
+			for (idx_port = 0; idx_port < cnt_ports; idx_port++)
+				rte_stats_bitrate_calc(bitrate_data, idx_port);
+			tics_datum = tics_current;
+		}
+#endif
 	} while (! fc->stopped);
 }
 
@@ -2133,6 +2160,15 @@ main(int argc, char** argv)
 	FOREACH_PORT(port_id, ports)
 		rte_eth_promiscuous_enable(port_id);
 
+	/* Setup bitrate stats */
+#ifdef RTE_LIBRTE_BITRATE
+	bitrate_data = rte_stats_bitrate_create();
+	if (bitrate_data == NULL)
+		rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n");
+	rte_stats_bitrate_reg(bitrate_data);
+#endif
+
+
 #ifdef RTE_LIBRTE_CMDLINE
 	if (interactive == 1) {
 		if (auto_start) {
-- 
2.5.5

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

* Re: [PATCH v4 2/3] lib: add bitrate statistics library
  2016-11-15  7:15       ` [PATCH v4 2/3] lib: add bitrate statistics library Remy Horton
@ 2016-11-15 15:17         ` Pattan, Reshma
  0 siblings, 0 replies; 115+ messages in thread
From: Pattan, Reshma @ 2016-11-15 15:17 UTC (permalink / raw)
  To: Horton, Remy; +Cc: thomas.monjalon, dev

Hi,

> Signed-off-by: Remy Horton <remy.horton@intel.com>
> ---
> a/doc/guides/rel_notes/release_17_02.rst
> b/doc/guides/rel_notes/release_17_02.rst
> index e1b8894..f949e88 100644
> --- a/doc/guides/rel_notes/release_17_02.rst
> +++ b/doc/guides/rel_notes/release_17_02.rst
> @@ -40,6 +40,11 @@ New Features
>       intended to provide a reporting mechanism that is independent of the
>       ethdev library.
> 
> +   * **Added bit-rate calculation library.**
> +
> +     A library that can be used to calculate device bit-rates. Calculated
> +     bitrates are reported using the metrics library.
> +

Shared Library Versions section also need to be updated for bitrate and metrics libraries.

Thanks,
Reshma

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

* [PATCH v5 0/4] Expanded statistics reporting
  2016-11-15  7:15     ` [PATCH v4 0/3] Expanded statistics reporting Remy Horton
                         ` (2 preceding siblings ...)
  2016-11-15  7:15       ` [PATCH v4 3/3] app/test-pmd: add support for bitrate statistics Remy Horton
@ 2016-11-18  8:00       ` Remy Horton
  2016-11-18  8:00         ` [PATCH v5 1/4] lib: add information metrics library Remy Horton
                           ` (4 more replies)
  3 siblings, 5 replies; 115+ messages in thread
From: Remy Horton @ 2016-11-18  8:00 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patchset extends statistics reporting to include peak and
average data-rate metrics. It comes in two parts: a statistics
reporting library, and a bitrate calculation library that uses
it. This structure is intended to seperate statistic reporting
from ethdev and allow more flexible metric registration.

Due to merge issues Reshma's latency statistics, which depends
on the reporting library, has been merged into this patchset.

--
v5 changes:
* Updated Shared Library Versions in release notes
* Merged in Reshma's latencystats library

v4 changes:
* References to 16.11 changed to 17.02
* Fetching of non-port values was broken
* Added sanity checks to value fetching
* rte_stat_value renamed to rte_metric_value
* Corrected doxygen descriptions
* Added MAINTAINERS entries
* Added #ifdef directives to bitrate code in test-pmd

v3 changes:
* Marked rte_stats_bitrate_s as internal
* Minor integer roundoff correction
* Coding style corrections
* Removed spurious object allocation
* Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3.
* Reintroduced non-port values (RTE_METRICS_NONPORT)
* Added spinlocks to metric library
* Removed spurious test registration/update
* Added release notes entries

v2 changes:
* Uses a new metrics library rather than being part of ethdev


Remy Horton (4):
  lib: add information metrics library
  lib: add bitrate statistics library
  app/test-pmd: add support for bitrate statistics
  latencystats: added new library for latency stats

 MAINTAINERS                                        |  13 +
 app/proc_info/main.c                               |  70 ++++
 app/test-pmd/testpmd.c                             |  46 +++
 config/common_base                                 |  15 +
 doc/api/doxy-api-index.md                          |   3 +
 doc/api/doxy-api.conf                              |   3 +
 doc/guides/rel_notes/release_17_02.rst             |  18 +
 lib/Makefile                                       |   3 +
 lib/librte_bitratestats/Makefile                   |  53 +++
 lib/librte_bitratestats/rte_bitrate.c              | 128 +++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++
 .../rte_bitratestats_version.map                   |   9 +
 lib/librte_latencystats/Makefile                   |  57 +++
 lib/librte_latencystats/rte_latencystats.c         | 389 +++++++++++++++++++++
 lib/librte_latencystats/rte_latencystats.h         | 146 ++++++++
 .../rte_latencystats_version.map                   |  10 +
 lib/librte_mbuf/rte_mbuf.h                         |   3 +
 lib/librte_metrics/Makefile                        |  51 +++
 lib/librte_metrics/rte_metrics.c                   | 308 ++++++++++++++++
 lib/librte_metrics/rte_metrics.h                   | 190 ++++++++++
 lib/librte_metrics/rte_metrics_version.map         |  13 +
 mk/rte.app.mk                                      |   3 +
 22 files changed, 1611 insertions(+)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map
 create mode 100644 lib/librte_latencystats/Makefile
 create mode 100644 lib/librte_latencystats/rte_latencystats.c
 create mode 100644 lib/librte_latencystats/rte_latencystats.h
 create mode 100644 lib/librte_latencystats/rte_latencystats_version.map
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

-- 
2.5.5

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

* [PATCH v5 1/4] lib: add information metrics library
  2016-11-18  8:00       ` [PATCH v5 0/4] Expanded statistics reporting Remy Horton
@ 2016-11-18  8:00         ` Remy Horton
  2016-11-18  8:00         ` [PATCH v5 2/4] lib: add bitrate statistics library Remy Horton
                           ` (3 subsequent siblings)
  4 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2016-11-18  8:00 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patch adds a new information metric library that allows other
modules to register named metrics and update their values. It is
intended to be independent of ethdev, rather than mixing ethdev
and non-ethdev information in xstats.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                |   5 +
 config/common_base                         |   5 +
 doc/api/doxy-api-index.md                  |   1 +
 doc/api/doxy-api.conf                      |   1 +
 doc/guides/rel_notes/release_17_02.rst     |   7 +
 lib/Makefile                               |   1 +
 lib/librte_metrics/Makefile                |  51 +++++
 lib/librte_metrics/rte_metrics.c           | 308 +++++++++++++++++++++++++++++
 lib/librte_metrics/rte_metrics.h           | 190 ++++++++++++++++++
 lib/librte_metrics/rte_metrics_version.map |  13 ++
 mk/rte.app.mk                              |   2 +
 11 files changed, 584 insertions(+)
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index d6bb8f8..52bd8a9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -595,6 +595,11 @@ F: lib/librte_jobstats/
 F: examples/l2fwd-jobstats/
 F: doc/guides/sample_app_ug/l2_forward_job_stats.rst
 
+Metrics
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_metrics/
+F: doc/guides/sample_app_ug/keep_alive.rst
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index 4bff83a..dedc4c3 100644
--- a/config/common_base
+++ b/config/common_base
@@ -589,3 +589,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
 CONFIG_RTE_TEST_PMD=y
 CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
 CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+
+#
+# Compile the device metrics library
+#
+CONFIG_RTE_LIBRTE_METRICS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 6675f96..ca50fa6 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -147,4 +147,5 @@ There are many libraries, so their headers may be grouped by topics:
   [common]             (@ref rte_common.h),
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
+  [Device Metrics]     (@ref rte_metrics.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index 9dc7ae5..fe830eb 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -57,6 +57,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_reorder \
                           lib/librte_ring \
                           lib/librte_sched \
+                          lib/librte_metrics \
                           lib/librte_table \
                           lib/librte_timer \
                           lib/librte_vhost
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 3b65038..2d82dd1 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -34,6 +34,12 @@ New Features
 
      Refer to the previous release notes for examples.
 
+   * **Added information metric library.**
+
+     A library that allows information metrics to be added and update. It is
+     intended to provide a reporting mechanism that is independent of the
+     ethdev library.
+
      This section is a comment. do not overwrite or remove it.
      Also, make sure to start the actual text at the margin.
      =========================================================
@@ -152,6 +158,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_mbuf.so.2
      librte_mempool.so.2
      librte_meter.so.1
+   + librte_metrics.so.1
      librte_net.so.1
      librte_pdump.so.1
      librte_pipeline.so.3
diff --git a/lib/Makefile b/lib/Makefile
index 990f23a..5d85dcf 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table
 DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
+DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile
new file mode 100644
index 0000000..8d6e23a
--- /dev/null
+++ b/lib/librte_metrics/Makefile
@@ -0,0 +1,51 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_metrics.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_metrics_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c
new file mode 100644
index 0000000..5edacc6
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.c
@@ -0,0 +1,308 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <string.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_lcore.h>
+#include <rte_memzone.h>
+#include <rte_spinlock.h>
+
+#define RTE_METRICS_MAX_METRICS 256
+#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS"
+
+/**
+ * Internal stats metadata and value entry.
+ *
+ * @internal
+ * @param name
+ *   Name of metric
+ * @param value
+ *   Current value for metric
+ * @param idx_next_set
+ *   Index of next root element (zero for none)
+ * @param idx_next_metric
+ *   Index of next metric in set (zero for none)
+ *
+ * Only the root of each set needs idx_next_set but since it has to be
+ * assumed that number of sets could equal total number of metrics,
+ * having a separate set metadata table doesn't save any memory.
+ */
+struct rte_metrics_meta_s {
+	char name[RTE_METRICS_MAX_NAME_LEN];
+	uint64_t value[RTE_MAX_ETHPORTS];
+	uint64_t nonport_value;
+	uint16_t idx_next_set;
+	uint16_t idx_next_stat;
+};
+
+/**
+ * Internal stats info structure.
+ *
+ * @internal
+ * @param idx_last_set
+ *   Index of last metadata entry with valid data. This value is
+ *   not valid if cnt_stats is zero.
+ * @param cnt_stats
+ *   Number of metrics.
+ * @param metadata
+ *   Stat data memory block.
+ *
+ * Offsets into metadata are used instead of pointers because ASLR
+ * means that having the same physical addresses in different
+ * processes is not guaranteed.
+ */
+struct rte_metrics_data_s {
+	uint16_t idx_last_set;
+	uint16_t cnt_stats;
+	struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS];
+	rte_spinlock_t lock;
+};
+
+void
+rte_metrics_init(void)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone != NULL)
+		return;
+	memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME,
+		sizeof(struct rte_metrics_data_s), rte_socket_id(), 0);
+	if (memzone == NULL)
+		rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
+	stats = memzone->addr;
+	memset(stats, 0, sizeof(struct rte_metrics_data_s));
+	rte_spinlock_init(&stats->lock);
+}
+
+int
+rte_metrics_reg_metric(const char *name)
+{
+	const char *list_names[] = {name};
+
+	return rte_metrics_reg_metrics(list_names, 1);
+}
+
+int
+rte_metrics_reg_metrics(const char **names, uint16_t cnt_names)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	uint16_t idx_base;
+
+	/* Some sanity checks */
+	if (cnt_names < 1 || names == NULL)
+		return -EINVAL;
+
+	rte_metrics_init();
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS)
+		return -ENOMEM;
+
+	rte_spinlock_lock(&stats->lock);
+
+	/* Overwritten later if this is actually first set.. */
+	stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats;
+
+	stats->idx_last_set = idx_base = stats->cnt_stats;
+
+	for (idx_name = 0; idx_name < cnt_names; idx_name++) {
+		entry = &stats->metadata[idx_name + stats->cnt_stats];
+		strncpy(entry->name, names[idx_name],
+			RTE_METRICS_MAX_NAME_LEN);
+		memset(entry->value, 0, sizeof(entry->value));
+		entry->idx_next_stat = idx_name + stats->cnt_stats + 1;
+	}
+	entry->idx_next_stat = 0;
+	entry->idx_next_set = 0;
+	stats->cnt_stats += cnt_names;
+
+	rte_spinlock_unlock(&stats->lock);
+
+	return idx_base;
+}
+
+int
+rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value)
+{
+	return rte_metrics_update_metrics(port_id, key, &value, 1);
+}
+
+int
+rte_metrics_update_metrics(int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_metric;
+	uint16_t idx_value;
+	uint16_t cnt_setsize;
+
+	if (port_id != RTE_METRICS_NONPORT &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	rte_metrics_init();
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	rte_spinlock_lock(&stats->lock);
+	idx_metric = key;
+	cnt_setsize = 1;
+	while (idx_metric < stats->cnt_stats) {
+		entry = &stats->metadata[idx_metric];
+		if (entry->idx_next_stat == 0)
+			break;
+		cnt_setsize++;
+		idx_metric++;
+	}
+	/* Check update does not cross set border */
+	if (count > cnt_setsize) {
+		rte_spinlock_unlock(&stats->lock);
+		return -ERANGE;
+	}
+
+	if (port_id == RTE_METRICS_NONPORT)
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].nonport_value =
+				values[idx_value];
+		}
+	else
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].value[port_id] =
+				values[idx_value];
+		}
+	rte_spinlock_unlock(&stats->lock);
+	return 0;
+}
+
+int
+rte_metrics_get_names(struct rte_metric_name *names,
+	uint16_t capacity)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+	if (names != NULL) {
+		if (capacity < stats->cnt_stats) {
+			rte_spinlock_unlock(&stats->lock);
+			return -ERANGE;
+		}
+		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
+			strncpy(names[idx_name].name,
+				stats->metadata[idx_name].name,
+				RTE_METRICS_MAX_NAME_LEN);
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
+
+int
+rte_metrics_get_values(int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	if (port_id != RTE_METRICS_NONPORT &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+
+	if (values != NULL) {
+		if (capacity < stats->cnt_stats) {
+			rte_spinlock_unlock(&stats->lock);
+			return -ERANGE;
+		}
+		if (port_id == RTE_METRICS_NONPORT)
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->nonport_value;
+			}
+		else
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->value[port_id];
+			}
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
new file mode 100644
index 0000000..c58b366
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.h
@@ -0,0 +1,190 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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.
+ */
+
+/**
+ * @file
+ *
+ * RTE Metrics module
+ *
+ * Metric information is populated using a push model, where the
+ * information provider calls an update function on the relevant
+ * metrics. Currently only bulk querying of metrics is supported.
+ */
+
+#ifndef _RTE_METRICS_H_
+#define _RTE_METRICS_H_
+
+/** Maximum length of metric name (including null-terminator) */
+#define RTE_METRICS_MAX_NAME_LEN 64
+
+/** Used to indicate port-independent information */
+#define RTE_METRICS_NONPORT -1
+
+
+/**
+ * Metric name
+ */
+struct rte_metric_name {
+	/** String describing metric */
+	char name[RTE_METRICS_MAX_NAME_LEN];
+};
+
+
+/**
+ * Metric name.
+ */
+struct rte_metric_value {
+	/** Numeric identifier of metric */
+	uint16_t key;
+	/** Value for metric */
+	uint64_t value;
+};
+
+
+/**
+ * Initializes metric module. This only has to be explicitly called if you
+ * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a
+ * secondary process. This function must be called from a primary process.
+ */
+void rte_metrics_init(void);
+
+
+/**
+ * Register a metric
+ *
+ * @param name
+ *   Metric name
+ *
+ * @return
+ *  - Zero or positive: Success
+ *  - Negative: Failure
+ */
+int rte_metrics_reg_metric(const char *name);
+
+/**
+ * Register a set of metrics
+ *
+ * @param names
+ *   List of metric names
+ *
+ * @param cnt_names
+ *   Number of metrics in set
+ *
+ * @return
+ *  - Zero or positive: Success
+ *  - Negative: Failure
+ */
+int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names);
+
+/**
+ * Get metric name-key lookup table.
+ *
+ * @param names
+ *   Array of names to receive key names
+ *
+ * @param capacity
+ *   Space available in names
+ *
+ * @return
+ *   - Non-negative: Success (number of names)
+ *   - Negative: Failure
+ */
+int rte_metrics_get_names(
+	struct rte_metric_name *names,
+	uint16_t capacity);
+
+/**
+ * Fetch metrics.
+ *
+ * @param port_id
+ *   Port id to query
+ *
+ * @param values
+ *   Array to receive values and their keys
+ *
+ * @param capacity
+ *   Space available in values
+ *
+ * @return
+ *   - Non-negative: Success (number of names)
+ *   - Negative: Failure
+ */
+int rte_metrics_get_values(
+	int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity);
+
+/**
+ * Updates a metric
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Id of metric to update
+ * @param value
+ *   New value
+ *
+ * @return
+ *   - -EIO if unable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_metric(
+	int port_id,
+	uint16_t key,
+	const uint64_t value);
+
+/**
+ * Updates a metric set. Note that it is an error to try to
+ * update across a set boundary.
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Base id of metrics set to update
+ * @param values
+ *   Set of new values
+ * @param count
+ *   Number of new values
+ *
+ * @return
+ *   - -ERANGE if count exceeds metric set size
+ *   - -EIO if upable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_metrics(
+	int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count);
+
+#endif
diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map
new file mode 100644
index 0000000..f904814
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics_version.map
@@ -0,0 +1,13 @@
+DPDK_17.02 {
+	global:
+
+	rte_metrics_get_names;
+	rte_metrics_get_values;
+	rte_metrics_init;
+	rte_metrics_reg_metric;
+	rte_metrics_reg_metrics;
+	rte_metrics_update_metric;
+	rte_metrics_update_metrics;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index f75f0e2..40fcf33 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -98,6 +98,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING)           += -lrte_ring
 _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
+_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* [PATCH v5 2/4] lib: add bitrate statistics library
  2016-11-18  8:00       ` [PATCH v5 0/4] Expanded statistics reporting Remy Horton
  2016-11-18  8:00         ` [PATCH v5 1/4] lib: add information metrics library Remy Horton
@ 2016-11-18  8:00         ` Remy Horton
  2016-11-18  8:00         ` [PATCH v5 3/4] app/test-pmd: add support for bitrate statistics Remy Horton
                           ` (2 subsequent siblings)
  4 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2016-11-18  8:00 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patch adds a library that calculates peak and average data-rate
statistics. For ethernet devices. These statistics are reported using
the metrics library.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                        |   4 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/rel_notes/release_17_02.rst             |   6 +
 lib/Makefile                                       |   1 +
 lib/librte_bitratestats/Makefile                   |  53 +++++++++
 lib/librte_bitratestats/rte_bitrate.c              | 128 +++++++++++++++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++++++++++
 .../rte_bitratestats_version.map                   |   9 ++
 mk/rte.app.mk                                      |   1 +
 11 files changed, 289 insertions(+)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 52bd8a9..d6bbdd5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -600,6 +600,10 @@ M: Remy Horton <remy.horton@intel.com>
 F: lib/librte_metrics/
 F: doc/guides/sample_app_ug/keep_alive.rst
 
+Bit-rate statistica
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_bitratestats/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index dedc4c3..beca7ec 100644
--- a/config/common_base
+++ b/config/common_base
@@ -594,3 +594,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
 # Compile the device metrics library
 #
 CONFIG_RTE_LIBRTE_METRICS=y
+
+#
+# Compile the bitrate statistics library
+#
+CONFIG_RTE_LIBRTE_BITRATE=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index ca50fa6..91e8ea6 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -148,4 +148,5 @@ There are many libraries, so their headers may be grouped by topics:
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
   [Device Metrics]     (@ref rte_metrics.h),
+  [Bitrate Statistics] (@ref rte_bitrate.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index fe830eb..8765ddd 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -58,6 +58,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_ring \
                           lib/librte_sched \
                           lib/librte_metrics \
+                          lib/librte_bitratestats \
                           lib/librte_table \
                           lib/librte_timer \
                           lib/librte_vhost
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 2d82dd1..0f7c06d 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -40,6 +40,11 @@ New Features
      intended to provide a reporting mechanism that is independent of the
      ethdev library.
 
+   * **Added bit-rate calculation library.**
+
+     A library that can be used to calculate device bit-rates. Calculated
+     bitrates are reported using the metrics library.
+
      This section is a comment. do not overwrite or remove it.
      Also, make sure to start the actual text at the margin.
      =========================================================
@@ -143,6 +148,7 @@ The libraries prepended with a plus sign were incremented in this version.
 .. code-block:: diff
 
      librte_acl.so.2
+   + librte_bitratestats.so.1
      librte_cfgfile.so.2
      librte_cmdline.so.2
      librte_cryptodev.so.2
diff --git a/lib/Makefile b/lib/Makefile
index 5d85dcf..e211bc0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
+DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile
new file mode 100644
index 0000000..b725d4e
--- /dev/null
+++ b/lib/librte_bitratestats/Makefile
@@ -0,0 +1,53 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_bitratestats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_bitratestats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c
new file mode 100644
index 0000000..6346bb1
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.c
@@ -0,0 +1,128 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
+
+/*
+ * Persistent bit-rate data.
+ * @internal
+ */
+struct rte_stats_bitrate_s {
+	uint64_t last_ibytes;
+	uint64_t last_obytes;
+	uint64_t peak_ibits;
+	uint64_t peak_obits;
+	uint64_t ewma_ibits;
+	uint64_t ewma_obits;
+};
+
+struct rte_stats_bitrates_s {
+	struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS];
+	uint16_t id_stats_set;
+};
+
+struct rte_stats_bitrates_s *
+rte_stats_bitrate_create(void)
+{
+	return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0);
+}
+
+int
+rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data)
+{
+	const char *names[] = {
+		"mean_bits_in", "mean_bits_out",
+		"peak_bits_in", "peak_bits_out",
+	};
+	int return_value;
+
+	return_value = rte_metrics_reg_metrics(&names[0], 4);
+	if (return_value >= 0)
+		bitrate_data->id_stats_set = return_value;
+	return return_value;
+}
+
+int
+rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
+	uint8_t port_id)
+{
+	struct rte_stats_bitrate_s *port_data;
+	struct rte_eth_stats eth_stats;
+	int ret_code;
+	uint64_t cnt_bits;
+	int64_t delta;
+	const int64_t alpha_percent = 20;
+	uint64_t values[4];
+
+	ret_code = rte_eth_stats_get(port_id, &eth_stats);
+	if (ret_code != 0)
+		return ret_code;
+
+	port_data = &bitrate_data->port_stats[port_id];
+
+	/* Incoming bitrate. This is an iteratively calculated EWMA
+	 * (Expomentially Weighted Moving Average) that uses a
+	 * weighting factor of alpha_percent.
+	 */
+	cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3;
+	port_data->last_ibytes = eth_stats.ibytes;
+	if (cnt_bits > port_data->peak_ibits)
+		port_data->peak_ibits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_ibits;
+	/* The +50 fixes integer rounding during divison */
+	delta = (delta * alpha_percent + 50) / 100;
+	port_data->ewma_ibits += delta;
+
+	/* Outgoing bitrate (also EWMA) */
+	cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3;
+	port_data->last_obytes = eth_stats.obytes;
+	if (cnt_bits > port_data->peak_obits)
+		port_data->peak_obits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_obits;
+	delta = (delta * alpha_percent + 50) / 100;
+	port_data->ewma_obits += delta;
+
+	values[0] = port_data->ewma_ibits;
+	values[1] = port_data->ewma_obits;
+	values[2] = port_data->peak_ibits;
+	values[3] = port_data->peak_obits;
+	rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set,
+		values, 4);
+	return 0;
+}
diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h
new file mode 100644
index 0000000..bc87c5e
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.h
@@ -0,0 +1,80 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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.
+ */
+
+
+/**
+ *  Bitrate statistics data structure.
+ *  This data structure is intentionally opaque.
+ */
+struct rte_stats_bitrates_s;
+
+
+/**
+ * Allocate a bitrate statistics structure
+ *
+ * @return
+ *   - Pointer to structure on success
+ *   - NULL on error (zmalloc failure)
+ */
+struct rte_stats_bitrates_s *rte_stats_bitrate_create(void);
+
+
+/**
+ * Register bitrate statistics with the metric library.
+ *
+ * @param bitrate_data
+ *   Pointer allocated by rte_stats_create()
+ *
+ * @return
+ *   Zero on success
+ *   Negative on error
+ */
+int rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data);
+
+
+/**
+ * Calculate statistics for current time window. The period with which
+ * this function is called should be the intended sampling window width.
+ *
+ * @param bitrate_data
+ *   Bitrate statistics data pointer
+ *
+ * @param port_id
+ *   Port id to calculate statistics for
+ *
+ * @return
+ *  - Zero on success
+ *  - Negative value on error
+ */
+int rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
+	uint8_t port_id);
diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map
new file mode 100644
index 0000000..66f232f
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitratestats_version.map
@@ -0,0 +1,9 @@
+DPDK_17.02 {
+	global:
+
+	rte_stats_bitrate_calc;
+	rte_stats_bitrate_create;
+	rte_stats_bitrate_reg;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 40fcf33..6aac5ac 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -99,6 +99,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
 
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
-- 
2.5.5

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

* [PATCH v5 3/4] app/test-pmd: add support for bitrate statistics
  2016-11-18  8:00       ` [PATCH v5 0/4] Expanded statistics reporting Remy Horton
  2016-11-18  8:00         ` [PATCH v5 1/4] lib: add information metrics library Remy Horton
  2016-11-18  8:00         ` [PATCH v5 2/4] lib: add bitrate statistics library Remy Horton
@ 2016-11-18  8:00         ` Remy Horton
  2016-11-18  8:00         ` [PATCH v5 4/4] latencystats: added new library for latency stats Remy Horton
  2017-01-11 16:03         ` [PATCH v6 0/4] Expanded statistics reporting Remy Horton
  4 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2016-11-18  8:00 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/testpmd.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index a0332c2..60c635f 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -78,6 +78,10 @@
 #ifdef RTE_LIBRTE_PDUMP
 #include <rte_pdump.h>
 #endif
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_BITRATE
+#include <rte_bitrate.h>
+#endif
 
 #include "testpmd.h"
 
@@ -322,6 +326,9 @@ uint16_t nb_rx_queue_stats_mappings = 0;
 
 unsigned max_socket = 0;
 
+/* Bitrate statistics */
+struct rte_stats_bitrates_s *bitrate_data;
+
 /* Forward function declarations */
 static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -921,12 +928,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
 	struct fwd_stream **fsm;
 	streamid_t nb_fs;
 	streamid_t sm_id;
+#ifdef RTE_LIBRTE_BITRATE
+	uint64_t tics_per_1sec;
+	uint64_t tics_datum;
+	uint64_t tics_current;
+	uint8_t idx_port, cnt_ports;
+#endif
 
+#ifdef RTE_LIBRTE_BITRATE
+	cnt_ports = rte_eth_dev_count();
+	tics_datum = rte_rdtsc();
+	tics_per_1sec = rte_get_timer_hz();
+#endif
 	fsm = &fwd_streams[fc->stream_idx];
 	nb_fs = fc->stream_nb;
 	do {
 		for (sm_id = 0; sm_id < nb_fs; sm_id++)
 			(*pkt_fwd)(fsm[sm_id]);
+#ifdef RTE_LIBRTE_BITRATE
+		tics_current = rte_rdtsc();
+		if (tics_current - tics_datum >= tics_per_1sec) {
+			/* Periodic bitrate calculation */
+			for (idx_port = 0; idx_port < cnt_ports; idx_port++)
+				rte_stats_bitrate_calc(bitrate_data, idx_port);
+			tics_datum = tics_current;
+		}
+#endif
 	} while (! fc->stopped);
 }
 
@@ -2133,6 +2160,15 @@ main(int argc, char** argv)
 	FOREACH_PORT(port_id, ports)
 		rte_eth_promiscuous_enable(port_id);
 
+	/* Setup bitrate stats */
+#ifdef RTE_LIBRTE_BITRATE
+	bitrate_data = rte_stats_bitrate_create();
+	if (bitrate_data == NULL)
+		rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n");
+	rte_stats_bitrate_reg(bitrate_data);
+#endif
+
+
 #ifdef RTE_LIBRTE_CMDLINE
 	if (interactive == 1) {
 		if (auto_start) {
-- 
2.5.5

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

* [PATCH v5 4/4] latencystats: added new library for latency stats
  2016-11-18  8:00       ` [PATCH v5 0/4] Expanded statistics reporting Remy Horton
                           ` (2 preceding siblings ...)
  2016-11-18  8:00         ` [PATCH v5 3/4] app/test-pmd: add support for bitrate statistics Remy Horton
@ 2016-11-18  8:00         ` Remy Horton
  2017-01-11 16:03         ` [PATCH v6 0/4] Expanded statistics reporting Remy Horton
  4 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2016-11-18  8:00 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon, Reshma Pattan

Add a library designed to calculate latency statistics and report them
to the application when queried. The library measures minimum, average and
maximum latencies, and jitter in nano seconds. The current implementation
supports global latency stats, i.e. per application stats.

Added new field to mbuf struct to mark the packet arrival time on Rx.

Modify testpmd code to initialize/uninitialize latency statistics
calulation.

Modify the dpdk-procinfo process to display the newly added metrics.
Added new command line option "--metrics" to display metrics.

APIs:

* Added APIs to initialize and un initialize latency stats
  calculation.
* Added API to retrieve latency stats names and values.

Functionality:

* The library will register ethdev Rx/Tx callbacks for each active port,
  queue combinations.
* The library will register latency stats names with new metrics library.
* Rx packets will be marked with time stamp on each sampling interval.
* On Tx side, packets with time stamp will be considered for calculating
  the minimum, maximum, average latencies and also jitter.
* Average latency is calculated using exponential weighted moving average
  method.
* Minimum and maximum latencies will be low and high latency values
  observed so far.
* Jitter calculation is done based on inter packet delay variation.
* Measured stats are reported to the metrics library in a separate
  pthread.
* Measured stats can be retrieved via get API of the libray (or)
  by calling generic get API of the new metrics library.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                        |   4 +
 app/proc_info/main.c                               |  70 ++++
 app/test-pmd/testpmd.c                             |  10 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/rel_notes/release_17_02.rst             |   5 +
 lib/Makefile                                       |   1 +
 lib/librte_latencystats/Makefile                   |  57 +++
 lib/librte_latencystats/rte_latencystats.c         | 389 +++++++++++++++++++++
 lib/librte_latencystats/rte_latencystats.h         | 146 ++++++++
 .../rte_latencystats_version.map                   |  10 +
 lib/librte_mbuf/rte_mbuf.h                         |   3 +
 mk/rte.app.mk                                      |   2 +-
 14 files changed, 703 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_latencystats/Makefile
 create mode 100644 lib/librte_latencystats/rte_latencystats.c
 create mode 100644 lib/librte_latencystats/rte_latencystats.h
 create mode 100644 lib/librte_latencystats/rte_latencystats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index d6bbdd5..da7f9d1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -713,3 +713,7 @@ F: examples/tep_termination/
 F: examples/vmdq/
 F: examples/vmdq_dcb/
 F: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst
+
+Latency Stats
+M: Reshma Pattan <reshma.pattan@intel.com>
+F: lib/librte_latencystats/
diff --git a/app/proc_info/main.c b/app/proc_info/main.c
index 2c56d10..33a4b39 100644
--- a/app/proc_info/main.c
+++ b/app/proc_info/main.c
@@ -57,6 +57,7 @@
 #include <rte_atomic.h>
 #include <rte_branch_prediction.h>
 #include <rte_string_fns.h>
+#include <rte_metrics.h>
 
 /* Maximum long option length for option parsing. */
 #define MAX_LONG_OPT_SZ 64
@@ -68,6 +69,8 @@ static uint32_t enabled_port_mask;
 static uint32_t enable_stats;
 /**< Enable xstats. */
 static uint32_t enable_xstats;
+/**< Enable metrics. */
+static uint32_t enable_metrics;
 /**< Enable stats reset. */
 static uint32_t reset_stats;
 /**< Enable xstats reset. */
@@ -85,6 +88,8 @@ proc_info_usage(const char *prgname)
 		"  --stats: to display port statistics, enabled by default\n"
 		"  --xstats: to display extended port statistics, disabled by "
 			"default\n"
+		"  --metrics: to display derived metrics of the ports, disabled by "
+			"default\n"
 		"  --stats-reset: to reset port statistics\n"
 		"  --xstats-reset: to reset port extended statistics\n",
 		prgname);
@@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv)
 		{"stats", 0, NULL, 0},
 		{"stats-reset", 0, NULL, 0},
 		{"xstats", 0, NULL, 0},
+		{"metrics", 0, NULL, 0},
 		{"xstats-reset", 0, NULL, 0},
 		{NULL, 0, 0, 0}
 	};
@@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv)
 			else if (!strncmp(long_option[option_index].name, "xstats",
 					MAX_LONG_OPT_SZ))
 				enable_xstats = 1;
+			else if (!strncmp(long_option[option_index].name,
+					"metrics",
+					MAX_LONG_OPT_SZ))
+				enable_metrics = 1;
 			/* Reset stats */
 			if (!strncmp(long_option[option_index].name, "stats-reset",
 					MAX_LONG_OPT_SZ))
@@ -301,6 +311,60 @@ nic_xstats_clear(uint8_t port_id)
 	printf("\n  NIC extended statistics for port %d cleared\n", port_id);
 }
 
+static void
+metrics_display(int port_id)
+{
+	struct rte_metric_value *metrics;
+	struct rte_metric_name *names;
+	int len, ret;
+	static const char *nic_stats_border = "########################";
+
+	memset(&metrics, 0, sizeof(struct rte_metric_value));
+	len = rte_metrics_get_names(NULL, 0);
+	if (len < 0) {
+		printf("Cannot get metrics count\n");
+		return;
+	}
+
+	metrics = malloc(sizeof(struct rte_metric_value) * len);
+	if (metrics == NULL) {
+		printf("Cannot allocate memory for metrics\n");
+		return;
+	}
+
+	names =  malloc(sizeof(struct rte_metric_name) * len);
+	if (names == NULL) {
+		printf("Cannot allocate memory for metrcis names\n");
+		free(metrics);
+		return;
+	}
+
+	if (len != rte_metrics_get_names(names, len)) {
+		printf("Cannot get metrics names\n");
+		free(metrics);
+		free(names);
+		return;
+	}
+
+	printf("###### metrics for port %-2d #########\n", port_id);
+	printf("%s############################\n", nic_stats_border);
+	ret = rte_metrics_get_values(port_id, metrics, len);
+	if (ret < 0 || ret > len) {
+		printf("Cannot get metrics values\n");
+		free(metrics);
+		free(names);
+		return;
+	}
+
+	int i;
+	for (i = 0; i < len; i++)
+		printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value);
+
+	printf("%s############################\n", nic_stats_border);
+	free(metrics);
+	free(names);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -360,8 +424,14 @@ main(int argc, char **argv)
 				nic_stats_clear(i);
 			else if (reset_xstats)
 				nic_xstats_clear(i);
+			else if (enable_metrics)
+				metrics_display(i);
 		}
 	}
 
+	/* print port independent stats */
+	if (enable_metrics)
+		metrics_display(RTE_METRICS_NONPORT);
+
 	return 0;
 }
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 60c635f..774aa54 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -82,6 +82,10 @@
 #ifdef RTE_LIBRTE_BITRATE
 #include <rte_bitrate.h>
 #endif
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_LATENCY_STATS
+#include <rte_latencystats.h>
+#endif
 
 #include "testpmd.h"
 
@@ -2102,6 +2106,9 @@ signal_handler(int signum)
 		/* uninitialize packet capture framework */
 		rte_pdump_uninit();
 #endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+		rte_latencystats_uninit();
+#endif
 		force_quit();
 		/* exit with the expected status */
 		signal(signum, SIG_DFL);
@@ -2159,6 +2166,9 @@ main(int argc, char** argv)
 	/* set all ports to promiscuous mode by default */
 	FOREACH_PORT(port_id, ports)
 		rte_eth_promiscuous_enable(port_id);
+#ifdef RTE_LIBRTE_LATENCY_STATS
+	rte_latencystats_init(1, NULL);
+#endif
 
 	/* Setup bitrate stats */
 #ifdef RTE_LIBRTE_BITRATE
diff --git a/config/common_base b/config/common_base
index beca7ec..61d9352 100644
--- a/config/common_base
+++ b/config/common_base
@@ -599,3 +599,8 @@ CONFIG_RTE_LIBRTE_METRICS=y
 # Compile the bitrate statistics library
 #
 CONFIG_RTE_LIBRTE_BITRATE=y
+
+#
+# Compile the latency statistics library
+#
+CONFIG_RTE_LIBRTE_LATENCY_STATS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 91e8ea6..b98e5b5 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -149,4 +149,5 @@ There are many libraries, so their headers may be grouped by topics:
   [keepalive]          (@ref rte_keepalive.h),
   [Device Metrics]     (@ref rte_metrics.h),
   [Bitrate Statistics] (@ref rte_bitrate.h),
+  [Latency stats]      (@ref rte_latencystats.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index 8765ddd..40295ac 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -46,6 +46,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_jobstats \
                           lib/librte_kni \
                           lib/librte_kvargs \
+                          lib/librte_latencystats \
                           lib/librte_lpm \
                           lib/librte_mbuf \
                           lib/librte_mempool \
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 0f7c06d..dbd0e2f 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -49,6 +49,10 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **Added latency stats library.**
+  A library that facilitates latency stats measurment of the dpdk based applications.
+  The library measures minimum, average, maximum latencies and also jitter
+  in nano seconds.
 
 Resolved Issues
 ---------------
@@ -160,6 +164,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_jobstats.so.1
      librte_kni.so.2
      librte_kvargs.so.1
+   + librte_latencystats.so.1
      librte_lpm.so.2
      librte_mbuf.so.2
      librte_mempool.so.2
diff --git a/lib/Makefile b/lib/Makefile
index e211bc0..6fffa88 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -60,6 +60,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
+DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_latencystats/Makefile b/lib/librte_latencystats/Makefile
new file mode 100644
index 0000000..f744da6
--- /dev/null
+++ b/lib/librte_latencystats/Makefile
@@ -0,0 +1,57 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_latencystats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
+LDLIBS += -lm
+LDLIBS += -lpthread
+
+EXPORT_MAP := rte_latencystats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) := rte_latencystats.c
+
+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)-include := rte_latencystats.h
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_latencystats/rte_latencystats.c b/lib/librte_latencystats/rte_latencystats.c
new file mode 100644
index 0000000..dcde7f6
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats.c
@@ -0,0 +1,389 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <unistd.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <math.h>
+#include <pthread.h>
+
+#include <rte_mbuf.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_metrics.h>
+#include <rte_memzone.h>
+#include <rte_lcore.h>
+#include <rte_timer.h>
+
+#include "rte_latencystats.h"
+
+/** Nano seconds per second */
+#define NS_PER_SEC 1E9
+
+/** Clock cycles per nano second */
+#define CYCLES_PER_NS (rte_get_timer_hz() / NS_PER_SEC)
+
+/* Macros for printing using RTE_LOG */
+#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1
+
+static pthread_t latency_stats_thread;
+static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats";
+static int latency_stats_index;
+static uint64_t samp_intvl;
+static uint64_t timer_tsc;
+static uint64_t prev_tsc;
+
+static struct rte_latency_stats {
+	float min_latency; /**< Minimum latency in nano seconds */
+	float avg_latency; /**< Average latency in nano seconds */
+	float max_latency; /**< Maximum latency in nano seconds */
+	float jitter; /** Latency variation */
+} *glob_stats;
+
+static struct rxtx_cbs {
+	struct rte_eth_rxtx_callback *cb;
+} rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT],
+	tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
+
+struct latency_stats_nameoff {
+	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	unsigned int offset;
+};
+
+static const struct latency_stats_nameoff lat_stats_strings[] = {
+	{"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)},
+	{"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)},
+	{"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)},
+	{"jitter_ns", offsetof(struct rte_latency_stats, jitter)},
+};
+
+#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \
+				sizeof(lat_stats_strings[0]))
+
+static __attribute__((noreturn)) void *
+report_latency_stats(__rte_unused void *arg)
+{
+	for (;;) {
+		unsigned int i;
+		float *stats_ptr = NULL;
+		uint64_t values[NUM_LATENCY_STATS] = {0};
+		int ret;
+
+		for (i = 0; i < NUM_LATENCY_STATS; i++) {
+			stats_ptr = RTE_PTR_ADD(glob_stats,
+					lat_stats_strings[i].offset);
+			values[i] = (uint64_t)floor((*stats_ptr)/
+					CYCLES_PER_NS);
+		}
+
+		ret = rte_metrics_update_metrics(RTE_METRICS_NONPORT,
+						latency_stats_index,
+						values, NUM_LATENCY_STATS);
+		if (ret < 0)
+			RTE_LOG(INFO, LATENCY_STATS,
+				"Failed to push the stats\n");
+	}
+}
+
+static void
+rte_latencystats_fill_values(struct rte_metric_value *values)
+{
+	unsigned int i;
+	float *stats_ptr = NULL;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++) {
+		stats_ptr = RTE_PTR_ADD(glob_stats,
+				lat_stats_strings[i].offset);
+		values[i].key = i;
+		values[i].value = (uint64_t)floor((*stats_ptr)/
+						CYCLES_PER_NS);
+	}
+}
+
+static uint16_t
+add_time_stamps(uint8_t pid __rte_unused,
+		uint16_t qid __rte_unused,
+		struct rte_mbuf **pkts,
+		uint16_t nb_pkts,
+		uint16_t max_pkts __rte_unused,
+		void *user_cb __rte_unused)
+{
+	unsigned int i;
+	uint64_t diff_tsc, now;
+
+	/*
+	 * For every sample interval,
+	 * time stamp is marked on one received packet.
+	 */
+	now = rte_rdtsc();
+	for (i = 0; i < nb_pkts; i++) {
+		diff_tsc = now - prev_tsc;
+		timer_tsc += diff_tsc;
+		if (timer_tsc >= samp_intvl) {
+			/*
+			 * TBD: Mark the timestamp only
+			 * if not already marked by the
+			 * hardware or the PMD.
+			 */
+			pkts[i]->timestamp = now;
+			timer_tsc = 0;
+		}
+		prev_tsc = now;
+		now = rte_rdtsc();
+	}
+
+	return nb_pkts;
+}
+
+static uint16_t
+calc_latency(uint8_t pid __rte_unused,
+		uint16_t qid __rte_unused,
+		struct rte_mbuf **pkts,
+		uint16_t nb_pkts,
+		void *_ __rte_unused)
+{
+	unsigned int i, cnt = 0;
+	uint64_t now;
+	float latency[nb_pkts];
+	static float prev_latency;
+	/*
+	 * Alpha represents degree of weighting decrease in EWMA,
+	 * a constant smoothing factor between 0 and 1. The value
+	 * is used below for measuring average latency.
+	 */
+	const float alpha = 0.2;
+
+	now = rte_rdtsc();
+	for (i = 0; i < nb_pkts; i++) {
+		if (pkts[i]->timestamp)
+			latency[cnt++] = now - pkts[i]->timestamp;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		/*
+		 * The jitter is calculated as statistical mean of interpacket
+		 * delay variation. The "jitter estimate" is computed by taking
+		 * the absolute values of the ipdv sequence and applying an
+		 * exponential filter with parameter 1/16 to generate the
+		 * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter,
+		 * D(i-1,i) is difference in latency of two consecutive packets
+		 * i-1 and i.
+		 * Reference: Calculated as per RFC 5481, sec 4.1,
+		 * RFC 3393 sec 4.5, RFC 1889 sec.
+		 */
+		glob_stats->jitter +=  (abs(prev_latency - latency[i])
+					- glob_stats->jitter)/16;
+		if (glob_stats->min_latency == 0)
+			glob_stats->min_latency = latency[i];
+		else if (latency[i] < glob_stats->min_latency)
+			glob_stats->min_latency = latency[i];
+		else if (latency[i] > glob_stats->max_latency)
+			glob_stats->max_latency = latency[i];
+		/*
+		 * The average latency is measured using exponential moving
+		 * average, i.e. using EWMA
+		 * https://en.wikipedia.org/wiki/Moving_average
+		 */
+		glob_stats->avg_latency +=
+			alpha * (latency[i] - glob_stats->avg_latency);
+		prev_latency = latency[i];
+	}
+
+	return nb_pkts;
+}
+
+int
+rte_latencystats_init(uint64_t samp_intvl,
+		rte_latency_stats_flow_type_fn user_cb)
+{
+	unsigned int i;
+	uint8_t pid;
+	uint16_t qid;
+	struct rxtx_cbs *cbs = NULL;
+	const uint8_t nb_ports = rte_eth_dev_count();
+	const char *ptr_strings[NUM_LATENCY_STATS] = {0};
+	const struct rte_memzone *mz = NULL;
+	const unsigned int flags = 0;
+
+	/** Allocate stats in shared memory fo muliti process support */
+	mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats),
+					rte_socket_id(), flags);
+	if (mz == NULL) {
+		RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n",
+			__func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	glob_stats = mz->addr;
+	samp_intvl *= CYCLES_PER_NS;
+
+	/** Register latency stats with stats library */
+	for (i = 0; i < NUM_LATENCY_STATS; i++)
+		ptr_strings[i] = lat_stats_strings[i].name;
+
+	latency_stats_index = rte_metrics_reg_metrics(ptr_strings,
+							NUM_LATENCY_STATS);
+	if (latency_stats_index < 0) {
+		RTE_LOG(DEBUG, LATENCY_STATS,
+			"Failed to register latency stats names\n");
+		return -1;
+	}
+
+	/** Register Rx/Tx callbacks */
+	for (pid = 0; pid < nb_ports; pid++) {
+		struct rte_eth_dev_info dev_info;
+		rte_eth_dev_info_get(pid, &dev_info);
+		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
+			cbs = &rx_cbs[pid][qid];
+			cbs->cb = rte_eth_add_first_rx_callback(pid, qid,
+					add_time_stamps, user_cb);
+			if (!cbs->cb)
+				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
+					"register Rx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
+			cbs = &tx_cbs[pid][qid];
+			cbs->cb =  rte_eth_add_tx_callback(pid, qid,
+					calc_latency, user_cb);
+			if (!cbs->cb)
+				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
+					"register Tx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+	}
+
+	int ret = 0;
+	char thread_name[RTE_MAX_THREAD_NAME_LEN];
+
+	/** Create the host thread to update latency stats to stats library */
+	ret = pthread_create(&latency_stats_thread, NULL, report_latency_stats,
+				NULL);
+	if (ret != 0) {
+		RTE_LOG(ERR, LATENCY_STATS,
+			"Failed to create the latency stats thread:%s, %s:%d\n",
+			strerror(errno), __func__, __LINE__);
+		return -1;
+	}
+	/** Set thread_name for aid in debugging */
+	snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "latency-stats-thread");
+	ret = rte_thread_setname(latency_stats_thread, thread_name);
+	if (ret != 0)
+		RTE_LOG(DEBUG, LATENCY_STATS,
+			"Failed to set thread name for latency stats handling\n");
+
+	return 0;
+}
+
+int
+rte_latencystats_uninit(void)
+{
+	uint8_t pid;
+	uint16_t qid;
+	int ret = 0;
+	struct rxtx_cbs *cbs = NULL;
+	const uint8_t nb_ports = rte_eth_dev_count();
+
+	/** De register Rx/Tx callbacks */
+	for (pid = 0; pid < nb_ports; pid++) {
+		struct rte_eth_dev_info dev_info;
+		rte_eth_dev_info_get(pid, &dev_info);
+		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
+			cbs = &rx_cbs[pid][qid];
+			ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb);
+			if (ret)
+				RTE_LOG(INFO, LATENCY_STATS, "failed to "
+					"remove Rx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
+			cbs = &tx_cbs[pid][qid];
+			ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb);
+			if (ret)
+				RTE_LOG(INFO, LATENCY_STATS, "failed to "
+					"remove Tx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+	}
+
+	/** Cancel the thread */
+	ret = pthread_cancel(latency_stats_thread);
+	if (ret != 0) {
+		RTE_LOG(ERR, LATENCY_STATS,
+			"Failed to cancel latency stats update thread:"
+			"%s,%s:%d\n",
+			strerror(errno), __func__, __LINE__);
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size)
+{
+	unsigned int i;
+
+	if (names == NULL || size < NUM_LATENCY_STATS)
+		return NUM_LATENCY_STATS;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++)
+		snprintf(names[i].name, sizeof(names[i].name),
+				"%s", lat_stats_strings[i].name);
+
+	return NUM_LATENCY_STATS;
+}
+
+int
+rte_latencystats_get(struct rte_metric_value *values, uint16_t size)
+{
+	if (size < NUM_LATENCY_STATS || values == NULL)
+		return NUM_LATENCY_STATS;
+
+	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		const struct rte_memzone *mz;
+		mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS);
+		if (mz == NULL) {
+			RTE_LOG(ERR, LATENCY_STATS,
+				"Latency stats memzone not found\n");
+			return -ENOMEM;
+		}
+		glob_stats =  mz->addr;
+	}
+
+	/* Retrieve latency stats */
+	rte_latencystats_fill_values(values);
+
+	return NUM_LATENCY_STATS;
+}
diff --git a/lib/librte_latencystats/rte_latencystats.h b/lib/librte_latencystats/rte_latencystats.h
new file mode 100644
index 0000000..405b878
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats.h
@@ -0,0 +1,146 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 _RTE_LATENCYSTATS_H_
+#define _RTE_LATENCYSTATS_H_
+
+/**
+ * @file
+ * RTE latency stats
+ *
+ * library to provide application and flow based latency stats.
+ */
+
+#include <rte_metrics.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  Note: This function pointer is for future flow based latency stats
+ *  implementation.
+ *
+ * Function type used for identifting flow types of a Rx packet.
+ *
+ * The callback function is called on Rx for each packet.
+ * This function is used for flow based latency calculations.
+ *
+ * @param pkt
+ *   Packet that has to be identified with its flow types.
+ * @param user_param
+ *   The arbitrary user parameter passed in by the application when
+ *   the callback was originally configured.
+ * @return
+ *   The flow_mask, representing the multiple flow types of a packet.
+ */
+typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt,
+							void *user_param);
+
+/**
+ *  Registers Rx/Tx callbacks for each active port, queue.
+ *
+ * @param samp_intvl
+ *  Sampling time period in nano seconds, at which packet
+ *  should be marked with time stamp.
+ * @param user_cb
+ *  Note: This param is for future flow based latency stats
+ *  implementation.
+ *  User callback to be called to get flow types of a packet.
+ *  Used for flow based latency calculation.
+ *  If the value is NULL, global stats will be calculated,
+ *  else flow based latency stats will be calculated.
+ *  For now just pass on the NULL value to this param.
+ *  @return
+ *   -1     : On error
+ *   -ENOMEM: On error
+ *    0     : On success
+ */
+int rte_latencystats_init(uint64_t samp_intvl,
+			rte_latency_stats_flow_type_fn user_cb);
+
+/**
+ *  Removes registered Rx/Tx callbacks for each active port, queue.
+ *
+ *  @return
+ *   -1: On error
+ *    0: On success
+ */
+int rte_latencystats_uninit(void);
+
+/**
+ * Retrieve names of latency statistics
+ *
+ * @param names
+ *  Block of memory to insert names into. Must be at least size in capacity.
+ *  If set to NULL, function returns required capacity.
+ * @param size
+ *  Capacity of latency stats names (number of names).
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ */
+int rte_latencystats_get_names(struct rte_metric_name *names,
+				uint16_t size);
+
+/**
+ * Retrieve latency statistics.
+ *
+ * @param values
+ *   A pointer to a table of structure of type *rte_metric_value*
+ *   to be filled with latency statistics ids and values.
+ *   This parameter can be set to NULL if size is 0.
+ * @param size
+ *   The size of the stats table, which should be large enough to store
+ *   all the latency stats.
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ *   -ENOMEM: On failure.
+ */
+int rte_latencystats_get(struct rte_metric_value *values,
+			uint16_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_LATENCYSTATS_H_ */
diff --git a/lib/librte_latencystats/rte_latencystats_version.map b/lib/librte_latencystats/rte_latencystats_version.map
new file mode 100644
index 0000000..502018e
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats_version.map
@@ -0,0 +1,10 @@
+DPDK_17.02 {
+	global:
+
+	rte_latencystats_get;
+	rte_latencystats_get_names;
+	rte_latencystats_init;
+	rte_latencystats_uninit;
+
+	local: *;
+};
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index ead7c6e..44ba922 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -493,6 +493,9 @@ struct rte_mbuf {
 
 	/** Timesync flags for use with IEEE1588. */
 	uint16_t timesync;
+
+	/** Timestamp for measuring latency. */
+	uint64_t timestamp;
 } __rte_cache_aligned;
 
 /**
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 6aac5ac..1d36fad 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -100,7 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
 _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
-
+_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)  += -lrte_latencystats
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* [PATCH v6 0/4] Expanded statistics reporting
  2016-11-18  8:00       ` [PATCH v5 0/4] Expanded statistics reporting Remy Horton
                           ` (3 preceding siblings ...)
  2016-11-18  8:00         ` [PATCH v5 4/4] latencystats: added new library for latency stats Remy Horton
@ 2017-01-11 16:03         ` Remy Horton
  2017-01-11 16:03           ` [PATCH v6 1/4] lib: add information metrics library Remy Horton
                             ` (5 more replies)
  4 siblings, 6 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patchset extends statistics reporting to include peak and
average data-rate metrics. It comes in two parts: a statistics
reporting library, and a bitrate calculation library that uses
it. This structure is intended to seperate statistic reporting
from ethdev and allow more flexible metric registration.

Due to merge issues Reshma's latency statistics, which depends
on the reporting library, has been merged into this patchset.

--

v6 changes:
* Metrics display now has "Non port specific" rather than "port -1"
* Fixed sign issue in EWMA delta calculation
* Rebased to master

v5 changes:
* Updated Shared Library Versions in release notes
* Merged in Reshma's latencystats library

v4 changes:
* References to 16.11 changed to 17.02
* Fetching of non-port values was broken
* Added sanity checks to value fetching
* rte_stat_value renamed to rte_metric_value
* Corrected doxygen descriptions
* Added MAINTAINERS entries
* Added #ifdef directives to bitrate code in test-pmd

v3 changes:
* Marked rte_stats_bitrate_s as internal
* Minor integer roundoff correction
* Coding style corrections
* Removed spurious object allocation
* Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3.
* Reintroduced non-port values (RTE_METRICS_NONPORT)
* Added spinlocks to metric library
* Removed spurious test registration/update
* Added release notes entries

v2 changes:
* Uses a new metrics library rather than being part of ethdev


Remy Horton (4):
  lib: add information metrics library
  lib: add bitrate statistics library
  app/test-pmd: add support for bitrate statistics
  latencystats: added new library for latency stats

 MAINTAINERS                                        |  13 +
 app/proc_info/main.c                               |  73 ++++
 app/test-pmd/testpmd.c                             |  46 +++
 config/common_base                                 |  15 +
 doc/api/doxy-api-index.md                          |   3 +
 doc/api/doxy-api.conf                              |   3 +
 doc/guides/rel_notes/release_17_02.rst             |  18 +
 lib/Makefile                                       |   3 +
 lib/librte_bitratestats/Makefile                   |  53 +++
 lib/librte_bitratestats/rte_bitrate.c              | 131 +++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++
 .../rte_bitratestats_version.map                   |   9 +
 lib/librte_latencystats/Makefile                   |  57 +++
 lib/librte_latencystats/rte_latencystats.c         | 389 +++++++++++++++++++++
 lib/librte_latencystats/rte_latencystats.h         | 146 ++++++++
 .../rte_latencystats_version.map                   |  10 +
 lib/librte_mbuf/rte_mbuf.h                         |   3 +
 lib/librte_metrics/Makefile                        |  51 +++
 lib/librte_metrics/rte_metrics.c                   | 308 ++++++++++++++++
 lib/librte_metrics/rte_metrics.h                   | 190 ++++++++++
 lib/librte_metrics/rte_metrics_version.map         |  13 +
 mk/rte.app.mk                                      |   3 +
 22 files changed, 1617 insertions(+)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map
 create mode 100644 lib/librte_latencystats/Makefile
 create mode 100644 lib/librte_latencystats/rte_latencystats.c
 create mode 100644 lib/librte_latencystats/rte_latencystats.h
 create mode 100644 lib/librte_latencystats/rte_latencystats_version.map
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

-- 
2.5.5

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

* [PATCH v6 1/4] lib: add information metrics library
  2017-01-11 16:03         ` [PATCH v6 0/4] Expanded statistics reporting Remy Horton
@ 2017-01-11 16:03           ` Remy Horton
  2017-01-12 13:22             ` Thomas Monjalon
  2017-01-11 16:03           ` [PATCH v6 2/4] lib: add bitrate statistics library Remy Horton
                             ` (4 subsequent siblings)
  5 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patch adds a new information metric library that allows other
modules to register named metrics and update their values. It is
intended to be independent of ethdev, rather than mixing ethdev
and non-ethdev information in xstats.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                |   5 +
 config/common_base                         |   5 +
 doc/api/doxy-api-index.md                  |   1 +
 doc/api/doxy-api.conf                      |   1 +
 doc/guides/rel_notes/release_17_02.rst     |   7 +
 lib/Makefile                               |   1 +
 lib/librte_metrics/Makefile                |  51 +++++
 lib/librte_metrics/rte_metrics.c           | 308 +++++++++++++++++++++++++++++
 lib/librte_metrics/rte_metrics.h           | 190 ++++++++++++++++++
 lib/librte_metrics/rte_metrics_version.map |  13 ++
 mk/rte.app.mk                              |   2 +
 11 files changed, 584 insertions(+)
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 9645c9b..4a19497 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -596,6 +596,11 @@ F: lib/librte_jobstats/
 F: examples/l2fwd-jobstats/
 F: doc/guides/sample_app_ug/l2_forward_job_stats.rst
 
+Metrics
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_metrics/
+F: doc/guides/sample_app_ug/keep_alive.rst
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index 8e9dcfa..0eb3866 100644
--- a/config/common_base
+++ b/config/common_base
@@ -593,3 +593,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
 CONFIG_RTE_TEST_PMD=y
 CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
 CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+
+#
+# Compile the device metrics library
+#
+CONFIG_RTE_LIBRTE_METRICS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 72d59b2..94f0f69 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -150,4 +150,5 @@ There are many libraries, so their headers may be grouped by topics:
   [common]             (@ref rte_common.h),
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
+  [Device Metrics]     (@ref rte_metrics.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index b340fcf..13e0faf 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -58,6 +58,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_reorder \
                           lib/librte_ring \
                           lib/librte_sched \
+                          lib/librte_metrics \
                           lib/librte_table \
                           lib/librte_timer \
                           lib/librte_vhost
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 180af82..82c5616 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -34,6 +34,12 @@ New Features
 
      Refer to the previous release notes for examples.
 
+   * **Added information metric library.**
+
+     A library that allows information metrics to be added and update. It is
+     intended to provide a reporting mechanism that is independent of the
+     ethdev library.
+
      This section is a comment. do not overwrite or remove it.
      Also, make sure to start the actual text at the margin.
      =========================================================
@@ -171,6 +177,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_mbuf.so.2
      librte_mempool.so.2
      librte_meter.so.1
+   + librte_metrics.so.1
      librte_net.so.1
      librte_pdump.so.1
      librte_pipeline.so.3
diff --git a/lib/Makefile b/lib/Makefile
index 990f23a..5d85dcf 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table
 DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
+DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile
new file mode 100644
index 0000000..8d6e23a
--- /dev/null
+++ b/lib/librte_metrics/Makefile
@@ -0,0 +1,51 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_metrics.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_metrics_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c
new file mode 100644
index 0000000..5edacc6
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.c
@@ -0,0 +1,308 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <string.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_lcore.h>
+#include <rte_memzone.h>
+#include <rte_spinlock.h>
+
+#define RTE_METRICS_MAX_METRICS 256
+#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS"
+
+/**
+ * Internal stats metadata and value entry.
+ *
+ * @internal
+ * @param name
+ *   Name of metric
+ * @param value
+ *   Current value for metric
+ * @param idx_next_set
+ *   Index of next root element (zero for none)
+ * @param idx_next_metric
+ *   Index of next metric in set (zero for none)
+ *
+ * Only the root of each set needs idx_next_set but since it has to be
+ * assumed that number of sets could equal total number of metrics,
+ * having a separate set metadata table doesn't save any memory.
+ */
+struct rte_metrics_meta_s {
+	char name[RTE_METRICS_MAX_NAME_LEN];
+	uint64_t value[RTE_MAX_ETHPORTS];
+	uint64_t nonport_value;
+	uint16_t idx_next_set;
+	uint16_t idx_next_stat;
+};
+
+/**
+ * Internal stats info structure.
+ *
+ * @internal
+ * @param idx_last_set
+ *   Index of last metadata entry with valid data. This value is
+ *   not valid if cnt_stats is zero.
+ * @param cnt_stats
+ *   Number of metrics.
+ * @param metadata
+ *   Stat data memory block.
+ *
+ * Offsets into metadata are used instead of pointers because ASLR
+ * means that having the same physical addresses in different
+ * processes is not guaranteed.
+ */
+struct rte_metrics_data_s {
+	uint16_t idx_last_set;
+	uint16_t cnt_stats;
+	struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS];
+	rte_spinlock_t lock;
+};
+
+void
+rte_metrics_init(void)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone != NULL)
+		return;
+	memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME,
+		sizeof(struct rte_metrics_data_s), rte_socket_id(), 0);
+	if (memzone == NULL)
+		rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
+	stats = memzone->addr;
+	memset(stats, 0, sizeof(struct rte_metrics_data_s));
+	rte_spinlock_init(&stats->lock);
+}
+
+int
+rte_metrics_reg_metric(const char *name)
+{
+	const char *list_names[] = {name};
+
+	return rte_metrics_reg_metrics(list_names, 1);
+}
+
+int
+rte_metrics_reg_metrics(const char **names, uint16_t cnt_names)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	uint16_t idx_base;
+
+	/* Some sanity checks */
+	if (cnt_names < 1 || names == NULL)
+		return -EINVAL;
+
+	rte_metrics_init();
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS)
+		return -ENOMEM;
+
+	rte_spinlock_lock(&stats->lock);
+
+	/* Overwritten later if this is actually first set.. */
+	stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats;
+
+	stats->idx_last_set = idx_base = stats->cnt_stats;
+
+	for (idx_name = 0; idx_name < cnt_names; idx_name++) {
+		entry = &stats->metadata[idx_name + stats->cnt_stats];
+		strncpy(entry->name, names[idx_name],
+			RTE_METRICS_MAX_NAME_LEN);
+		memset(entry->value, 0, sizeof(entry->value));
+		entry->idx_next_stat = idx_name + stats->cnt_stats + 1;
+	}
+	entry->idx_next_stat = 0;
+	entry->idx_next_set = 0;
+	stats->cnt_stats += cnt_names;
+
+	rte_spinlock_unlock(&stats->lock);
+
+	return idx_base;
+}
+
+int
+rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value)
+{
+	return rte_metrics_update_metrics(port_id, key, &value, 1);
+}
+
+int
+rte_metrics_update_metrics(int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_metric;
+	uint16_t idx_value;
+	uint16_t cnt_setsize;
+
+	if (port_id != RTE_METRICS_NONPORT &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	rte_metrics_init();
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	rte_spinlock_lock(&stats->lock);
+	idx_metric = key;
+	cnt_setsize = 1;
+	while (idx_metric < stats->cnt_stats) {
+		entry = &stats->metadata[idx_metric];
+		if (entry->idx_next_stat == 0)
+			break;
+		cnt_setsize++;
+		idx_metric++;
+	}
+	/* Check update does not cross set border */
+	if (count > cnt_setsize) {
+		rte_spinlock_unlock(&stats->lock);
+		return -ERANGE;
+	}
+
+	if (port_id == RTE_METRICS_NONPORT)
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].nonport_value =
+				values[idx_value];
+		}
+	else
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].value[port_id] =
+				values[idx_value];
+		}
+	rte_spinlock_unlock(&stats->lock);
+	return 0;
+}
+
+int
+rte_metrics_get_names(struct rte_metric_name *names,
+	uint16_t capacity)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+	if (names != NULL) {
+		if (capacity < stats->cnt_stats) {
+			rte_spinlock_unlock(&stats->lock);
+			return -ERANGE;
+		}
+		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
+			strncpy(names[idx_name].name,
+				stats->metadata[idx_name].name,
+				RTE_METRICS_MAX_NAME_LEN);
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
+
+int
+rte_metrics_get_values(int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	if (port_id != RTE_METRICS_NONPORT &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+
+	if (values != NULL) {
+		if (capacity < stats->cnt_stats) {
+			rte_spinlock_unlock(&stats->lock);
+			return -ERANGE;
+		}
+		if (port_id == RTE_METRICS_NONPORT)
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->nonport_value;
+			}
+		else
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->value[port_id];
+			}
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
new file mode 100644
index 0000000..c58b366
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.h
@@ -0,0 +1,190 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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.
+ */
+
+/**
+ * @file
+ *
+ * RTE Metrics module
+ *
+ * Metric information is populated using a push model, where the
+ * information provider calls an update function on the relevant
+ * metrics. Currently only bulk querying of metrics is supported.
+ */
+
+#ifndef _RTE_METRICS_H_
+#define _RTE_METRICS_H_
+
+/** Maximum length of metric name (including null-terminator) */
+#define RTE_METRICS_MAX_NAME_LEN 64
+
+/** Used to indicate port-independent information */
+#define RTE_METRICS_NONPORT -1
+
+
+/**
+ * Metric name
+ */
+struct rte_metric_name {
+	/** String describing metric */
+	char name[RTE_METRICS_MAX_NAME_LEN];
+};
+
+
+/**
+ * Metric name.
+ */
+struct rte_metric_value {
+	/** Numeric identifier of metric */
+	uint16_t key;
+	/** Value for metric */
+	uint64_t value;
+};
+
+
+/**
+ * Initializes metric module. This only has to be explicitly called if you
+ * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a
+ * secondary process. This function must be called from a primary process.
+ */
+void rte_metrics_init(void);
+
+
+/**
+ * Register a metric
+ *
+ * @param name
+ *   Metric name
+ *
+ * @return
+ *  - Zero or positive: Success
+ *  - Negative: Failure
+ */
+int rte_metrics_reg_metric(const char *name);
+
+/**
+ * Register a set of metrics
+ *
+ * @param names
+ *   List of metric names
+ *
+ * @param cnt_names
+ *   Number of metrics in set
+ *
+ * @return
+ *  - Zero or positive: Success
+ *  - Negative: Failure
+ */
+int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names);
+
+/**
+ * Get metric name-key lookup table.
+ *
+ * @param names
+ *   Array of names to receive key names
+ *
+ * @param capacity
+ *   Space available in names
+ *
+ * @return
+ *   - Non-negative: Success (number of names)
+ *   - Negative: Failure
+ */
+int rte_metrics_get_names(
+	struct rte_metric_name *names,
+	uint16_t capacity);
+
+/**
+ * Fetch metrics.
+ *
+ * @param port_id
+ *   Port id to query
+ *
+ * @param values
+ *   Array to receive values and their keys
+ *
+ * @param capacity
+ *   Space available in values
+ *
+ * @return
+ *   - Non-negative: Success (number of names)
+ *   - Negative: Failure
+ */
+int rte_metrics_get_values(
+	int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity);
+
+/**
+ * Updates a metric
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Id of metric to update
+ * @param value
+ *   New value
+ *
+ * @return
+ *   - -EIO if unable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_metric(
+	int port_id,
+	uint16_t key,
+	const uint64_t value);
+
+/**
+ * Updates a metric set. Note that it is an error to try to
+ * update across a set boundary.
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Base id of metrics set to update
+ * @param values
+ *   Set of new values
+ * @param count
+ *   Number of new values
+ *
+ * @return
+ *   - -ERANGE if count exceeds metric set size
+ *   - -EIO if upable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_metrics(
+	int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count);
+
+#endif
diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map
new file mode 100644
index 0000000..f904814
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics_version.map
@@ -0,0 +1,13 @@
+DPDK_17.02 {
+	global:
+
+	rte_metrics_get_names;
+	rte_metrics_get_values;
+	rte_metrics_init;
+	rte_metrics_reg_metric;
+	rte_metrics_reg_metrics;
+	rte_metrics_update_metric;
+	rte_metrics_update_metrics;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index f75f0e2..40fcf33 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -98,6 +98,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING)           += -lrte_ring
 _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
+_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* [PATCH v6 2/4] lib: add bitrate statistics library
  2017-01-11 16:03         ` [PATCH v6 0/4] Expanded statistics reporting Remy Horton
  2017-01-11 16:03           ` [PATCH v6 1/4] lib: add information metrics library Remy Horton
@ 2017-01-11 16:03           ` Remy Horton
  2017-01-11 16:15             ` Stephen Hemminger
  2017-01-11 16:03           ` [PATCH v6 3/4] app/test-pmd: add support for bitrate statistics Remy Horton
                             ` (3 subsequent siblings)
  5 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patch adds a library that calculates peak and average data-rate
statistics. For ethernet devices. These statistics are reported using
the metrics library.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                        |   4 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/rel_notes/release_17_02.rst             |   6 +
 lib/Makefile                                       |   1 +
 lib/librte_bitratestats/Makefile                   |  53 +++++++++
 lib/librte_bitratestats/rte_bitrate.c              | 131 +++++++++++++++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++++++++++
 .../rte_bitratestats_version.map                   |   9 ++
 mk/rte.app.mk                                      |   1 +
 11 files changed, 292 insertions(+)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 4a19497..6cd9896 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -601,6 +601,10 @@ M: Remy Horton <remy.horton@intel.com>
 F: lib/librte_metrics/
 F: doc/guides/sample_app_ug/keep_alive.rst
 
+Bit-rate statistica
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_bitratestats/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index 0eb3866..decebe5 100644
--- a/config/common_base
+++ b/config/common_base
@@ -598,3 +598,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
 # Compile the device metrics library
 #
 CONFIG_RTE_LIBRTE_METRICS=y
+
+#
+# Compile the bitrate statistics library
+#
+CONFIG_RTE_LIBRTE_BITRATE=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 94f0f69..5e194b0 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -151,4 +151,5 @@ There are many libraries, so their headers may be grouped by topics:
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
   [Device Metrics]     (@ref rte_metrics.h),
+  [Bitrate Statistics] (@ref rte_bitrate.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index 13e0faf..ff15f5b 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -59,6 +59,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_ring \
                           lib/librte_sched \
                           lib/librte_metrics \
+                          lib/librte_bitratestats \
                           lib/librte_table \
                           lib/librte_timer \
                           lib/librte_vhost
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 82c5616..70f93e1 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -40,6 +40,11 @@ New Features
      intended to provide a reporting mechanism that is independent of the
      ethdev library.
 
+   * **Added bit-rate calculation library.**
+
+     A library that can be used to calculate device bit-rates. Calculated
+     bitrates are reported using the metrics library.
+
      This section is a comment. do not overwrite or remove it.
      Also, make sure to start the actual text at the margin.
      =========================================================
@@ -162,6 +167,7 @@ The libraries prepended with a plus sign were incremented in this version.
 .. code-block:: diff
 
      librte_acl.so.2
+   + librte_bitratestats.so.1
      librte_cfgfile.so.2
      librte_cmdline.so.2
      librte_cryptodev.so.2
diff --git a/lib/Makefile b/lib/Makefile
index 5d85dcf..e211bc0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
+DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile
new file mode 100644
index 0000000..b725d4e
--- /dev/null
+++ b/lib/librte_bitratestats/Makefile
@@ -0,0 +1,53 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_bitratestats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_bitratestats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c
new file mode 100644
index 0000000..cb7aae4
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.c
@@ -0,0 +1,131 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
+
+/*
+ * Persistent bit-rate data.
+ * @internal
+ */
+struct rte_stats_bitrate_s {
+	uint64_t last_ibytes;
+	uint64_t last_obytes;
+	uint64_t peak_ibits;
+	uint64_t peak_obits;
+	uint64_t ewma_ibits;
+	uint64_t ewma_obits;
+};
+
+struct rte_stats_bitrates_s {
+	struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS];
+	uint16_t id_stats_set;
+};
+
+struct rte_stats_bitrates_s *
+rte_stats_bitrate_create(void)
+{
+	return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0);
+}
+
+int
+rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data)
+{
+	const char *names[] = {
+		"mean_bits_in", "mean_bits_out",
+		"peak_bits_in", "peak_bits_out",
+	};
+	int return_value;
+
+	return_value = rte_metrics_reg_metrics(&names[0], 4);
+	if (return_value >= 0)
+		bitrate_data->id_stats_set = return_value;
+	return return_value;
+}
+
+int
+rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
+	uint8_t port_id)
+{
+	struct rte_stats_bitrate_s *port_data;
+	struct rte_eth_stats eth_stats;
+	int ret_code;
+	uint64_t cnt_bits;
+	int64_t delta;
+	const int64_t alpha_percent = 20;
+	uint64_t values[4];
+
+	ret_code = rte_eth_stats_get(port_id, &eth_stats);
+	if (ret_code != 0)
+		return ret_code;
+
+	port_data = &bitrate_data->port_stats[port_id];
+
+	/* Incoming bitrate. This is an iteratively calculated EWMA
+	 * (Expomentially Weighted Moving Average) that uses a
+	 * weighting factor of alpha_percent.
+	 */
+	cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3;
+	port_data->last_ibytes = eth_stats.ibytes;
+	if (cnt_bits > port_data->peak_ibits)
+		port_data->peak_ibits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_ibits;
+	/* The +-50 fixes integer rounding during divison */
+	if (delta > 0)
+		delta = (delta * alpha_percent + 50) / 100;
+	else
+		delta = (delta * alpha_percent - 50) / 100;
+	port_data->ewma_ibits += delta;
+
+	/* Outgoing bitrate (also EWMA) */
+	cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3;
+	port_data->last_obytes = eth_stats.obytes;
+	if (cnt_bits > port_data->peak_obits)
+		port_data->peak_obits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_obits;
+	delta = (delta * alpha_percent + 50) / 100;
+	port_data->ewma_obits += delta;
+
+	values[0] = port_data->ewma_ibits;
+	values[1] = port_data->ewma_obits;
+	values[2] = port_data->peak_ibits;
+	values[3] = port_data->peak_obits;
+	rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set,
+		values, 4);
+	return 0;
+}
diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h
new file mode 100644
index 0000000..bc87c5e
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.h
@@ -0,0 +1,80 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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.
+ */
+
+
+/**
+ *  Bitrate statistics data structure.
+ *  This data structure is intentionally opaque.
+ */
+struct rte_stats_bitrates_s;
+
+
+/**
+ * Allocate a bitrate statistics structure
+ *
+ * @return
+ *   - Pointer to structure on success
+ *   - NULL on error (zmalloc failure)
+ */
+struct rte_stats_bitrates_s *rte_stats_bitrate_create(void);
+
+
+/**
+ * Register bitrate statistics with the metric library.
+ *
+ * @param bitrate_data
+ *   Pointer allocated by rte_stats_create()
+ *
+ * @return
+ *   Zero on success
+ *   Negative on error
+ */
+int rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data);
+
+
+/**
+ * Calculate statistics for current time window. The period with which
+ * this function is called should be the intended sampling window width.
+ *
+ * @param bitrate_data
+ *   Bitrate statistics data pointer
+ *
+ * @param port_id
+ *   Port id to calculate statistics for
+ *
+ * @return
+ *  - Zero on success
+ *  - Negative value on error
+ */
+int rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
+	uint8_t port_id);
diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map
new file mode 100644
index 0000000..66f232f
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitratestats_version.map
@@ -0,0 +1,9 @@
+DPDK_17.02 {
+	global:
+
+	rte_stats_bitrate_calc;
+	rte_stats_bitrate_create;
+	rte_stats_bitrate_reg;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 40fcf33..6aac5ac 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -99,6 +99,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
 
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
-- 
2.5.5

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

* [PATCH v6 3/4] app/test-pmd: add support for bitrate statistics
  2017-01-11 16:03         ` [PATCH v6 0/4] Expanded statistics reporting Remy Horton
  2017-01-11 16:03           ` [PATCH v6 1/4] lib: add information metrics library Remy Horton
  2017-01-11 16:03           ` [PATCH v6 2/4] lib: add bitrate statistics library Remy Horton
@ 2017-01-11 16:03           ` Remy Horton
  2017-01-12 13:32             ` Thomas Monjalon
  2017-01-11 16:03           ` [PATCH v6 4/4] latencystats: added new library for latency stats Remy Horton
                             ` (2 subsequent siblings)
  5 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/testpmd.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index bfb2f8e..a0b7430 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -79,6 +79,10 @@
 #include <rte_pdump.h>
 #endif
 #include <rte_flow.h>
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_BITRATE
+#include <rte_bitrate.h>
+#endif
 
 #include "testpmd.h"
 
@@ -323,6 +327,9 @@ uint16_t nb_rx_queue_stats_mappings = 0;
 
 unsigned max_socket = 0;
 
+/* Bitrate statistics */
+struct rte_stats_bitrates_s *bitrate_data;
+
 /* Forward function declarations */
 static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -922,12 +929,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
 	struct fwd_stream **fsm;
 	streamid_t nb_fs;
 	streamid_t sm_id;
+#ifdef RTE_LIBRTE_BITRATE
+	uint64_t tics_per_1sec;
+	uint64_t tics_datum;
+	uint64_t tics_current;
+	uint8_t idx_port, cnt_ports;
+#endif
 
+#ifdef RTE_LIBRTE_BITRATE
+	cnt_ports = rte_eth_dev_count();
+	tics_datum = rte_rdtsc();
+	tics_per_1sec = rte_get_timer_hz();
+#endif
 	fsm = &fwd_streams[fc->stream_idx];
 	nb_fs = fc->stream_nb;
 	do {
 		for (sm_id = 0; sm_id < nb_fs; sm_id++)
 			(*pkt_fwd)(fsm[sm_id]);
+#ifdef RTE_LIBRTE_BITRATE
+		tics_current = rte_rdtsc();
+		if (tics_current - tics_datum >= tics_per_1sec) {
+			/* Periodic bitrate calculation */
+			for (idx_port = 0; idx_port < cnt_ports; idx_port++)
+				rte_stats_bitrate_calc(bitrate_data, idx_port);
+			tics_datum = tics_current;
+		}
+#endif
 	} while (! fc->stopped);
 }
 
@@ -2139,6 +2166,15 @@ main(int argc, char** argv)
 	FOREACH_PORT(port_id, ports)
 		rte_eth_promiscuous_enable(port_id);
 
+	/* Setup bitrate stats */
+#ifdef RTE_LIBRTE_BITRATE
+	bitrate_data = rte_stats_bitrate_create();
+	if (bitrate_data == NULL)
+		rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n");
+	rte_stats_bitrate_reg(bitrate_data);
+#endif
+
+
 #ifdef RTE_LIBRTE_CMDLINE
 	if (interactive == 1) {
 		if (auto_start) {
-- 
2.5.5

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

* [PATCH v6 4/4] latencystats: added new library for latency stats
  2017-01-11 16:03         ` [PATCH v6 0/4] Expanded statistics reporting Remy Horton
                             ` (2 preceding siblings ...)
  2017-01-11 16:03           ` [PATCH v6 3/4] app/test-pmd: add support for bitrate statistics Remy Horton
@ 2017-01-11 16:03           ` Remy Horton
  2017-01-12 13:41             ` Thomas Monjalon
  2017-01-11 16:58           ` [PATCH v6 0/4] Expanded statistics reporting Thomas Monjalon
  2017-01-16 16:19           ` [PATCH v7 0/6] " Remy Horton
  5 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon, Reshma Pattan

Add a library designed to calculate latency statistics and report them
to the application when queried. The library measures minimum, average and
maximum latencies, and jitter in nano seconds. The current implementation
supports global latency stats, i.e. per application stats.

Added new field to mbuf struct to mark the packet arrival time on Rx.

Modify testpmd code to initialize/uninitialize latency statistics
calulation.

Modify the dpdk-procinfo process to display the newly added metrics.
Added new command line option "--metrics" to display metrics.

APIs:

* Added APIs to initialize and un initialize latency stats
  calculation.
* Added API to retrieve latency stats names and values.

Functionality:

* The library will register ethdev Rx/Tx callbacks for each active port,
  queue combinations.
* The library will register latency stats names with new metrics library.
* Rx packets will be marked with time stamp on each sampling interval.
* On Tx side, packets with time stamp will be considered for calculating
  the minimum, maximum, average latencies and also jitter.
* Average latency is calculated using exponential weighted moving average
  method.
* Minimum and maximum latencies will be low and high latency values
  observed so far.
* Jitter calculation is done based on inter packet delay variation.
* Measured stats are reported to the metrics library in a separate
  pthread.
* Measured stats can be retrieved via get API of the libray (or)
  by calling generic get API of the new metrics library.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                        |   4 +
 app/proc_info/main.c                               |  73 ++++
 app/test-pmd/testpmd.c                             |  10 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/rel_notes/release_17_02.rst             |   5 +
 lib/Makefile                                       |   1 +
 lib/librte_latencystats/Makefile                   |  57 +++
 lib/librte_latencystats/rte_latencystats.c         | 389 +++++++++++++++++++++
 lib/librte_latencystats/rte_latencystats.h         | 146 ++++++++
 .../rte_latencystats_version.map                   |  10 +
 lib/librte_mbuf/rte_mbuf.h                         |   3 +
 mk/rte.app.mk                                      |   2 +-
 14 files changed, 706 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_latencystats/Makefile
 create mode 100644 lib/librte_latencystats/rte_latencystats.c
 create mode 100644 lib/librte_latencystats/rte_latencystats.h
 create mode 100644 lib/librte_latencystats/rte_latencystats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 6cd9896..0a41fe5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -714,3 +714,7 @@ F: examples/tep_termination/
 F: examples/vmdq/
 F: examples/vmdq_dcb/
 F: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst
+
+Latency Stats
+M: Reshma Pattan <reshma.pattan@intel.com>
+F: lib/librte_latencystats/
diff --git a/app/proc_info/main.c b/app/proc_info/main.c
index 2c56d10..5f801a9 100644
--- a/app/proc_info/main.c
+++ b/app/proc_info/main.c
@@ -57,6 +57,7 @@
 #include <rte_atomic.h>
 #include <rte_branch_prediction.h>
 #include <rte_string_fns.h>
+#include <rte_metrics.h>
 
 /* Maximum long option length for option parsing. */
 #define MAX_LONG_OPT_SZ 64
@@ -68,6 +69,8 @@ static uint32_t enabled_port_mask;
 static uint32_t enable_stats;
 /**< Enable xstats. */
 static uint32_t enable_xstats;
+/**< Enable metrics. */
+static uint32_t enable_metrics;
 /**< Enable stats reset. */
 static uint32_t reset_stats;
 /**< Enable xstats reset. */
@@ -85,6 +88,8 @@ proc_info_usage(const char *prgname)
 		"  --stats: to display port statistics, enabled by default\n"
 		"  --xstats: to display extended port statistics, disabled by "
 			"default\n"
+		"  --metrics: to display derived metrics of the ports, disabled by "
+			"default\n"
 		"  --stats-reset: to reset port statistics\n"
 		"  --xstats-reset: to reset port extended statistics\n",
 		prgname);
@@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv)
 		{"stats", 0, NULL, 0},
 		{"stats-reset", 0, NULL, 0},
 		{"xstats", 0, NULL, 0},
+		{"metrics", 0, NULL, 0},
 		{"xstats-reset", 0, NULL, 0},
 		{NULL, 0, 0, 0}
 	};
@@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv)
 			else if (!strncmp(long_option[option_index].name, "xstats",
 					MAX_LONG_OPT_SZ))
 				enable_xstats = 1;
+			else if (!strncmp(long_option[option_index].name,
+					"metrics",
+					MAX_LONG_OPT_SZ))
+				enable_metrics = 1;
 			/* Reset stats */
 			if (!strncmp(long_option[option_index].name, "stats-reset",
 					MAX_LONG_OPT_SZ))
@@ -301,6 +311,63 @@ nic_xstats_clear(uint8_t port_id)
 	printf("\n  NIC extended statistics for port %d cleared\n", port_id);
 }
 
+static void
+metrics_display(int port_id)
+{
+	struct rte_metric_value *metrics;
+	struct rte_metric_name *names;
+	int len, ret;
+	static const char *nic_stats_border = "########################";
+
+	memset(&metrics, 0, sizeof(struct rte_metric_value));
+	len = rte_metrics_get_names(NULL, 0);
+	if (len < 0) {
+		printf("Cannot get metrics count\n");
+		return;
+	}
+
+	metrics = malloc(sizeof(struct rte_metric_value) * len);
+	if (metrics == NULL) {
+		printf("Cannot allocate memory for metrics\n");
+		return;
+	}
+
+	names =  malloc(sizeof(struct rte_metric_name) * len);
+	if (names == NULL) {
+		printf("Cannot allocate memory for metrcis names\n");
+		free(metrics);
+		return;
+	}
+
+	if (len != rte_metrics_get_names(names, len)) {
+		printf("Cannot get metrics names\n");
+		free(metrics);
+		free(names);
+		return;
+	}
+
+	if (port_id == RTE_METRICS_NONPORT)
+		printf("###### Non port specific metrics  #########\n");
+	else
+		printf("###### metrics for port %-2d #########\n", port_id);
+	printf("%s############################\n", nic_stats_border);
+	ret = rte_metrics_get_values(port_id, metrics, len);
+	if (ret < 0 || ret > len) {
+		printf("Cannot get metrics values\n");
+		free(metrics);
+		free(names);
+		return;
+	}
+
+	int i;
+	for (i = 0; i < len; i++)
+		printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value);
+
+	printf("%s############################\n", nic_stats_border);
+	free(metrics);
+	free(names);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -360,8 +427,14 @@ main(int argc, char **argv)
 				nic_stats_clear(i);
 			else if (reset_xstats)
 				nic_xstats_clear(i);
+			else if (enable_metrics)
+				metrics_display(i);
 		}
 	}
 
+	/* print port independent stats */
+	if (enable_metrics)
+		metrics_display(RTE_METRICS_NONPORT);
+
 	return 0;
 }
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index a0b7430..2874ce4 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -83,6 +83,10 @@
 #ifdef RTE_LIBRTE_BITRATE
 #include <rte_bitrate.h>
 #endif
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_LATENCY_STATS
+#include <rte_latencystats.h>
+#endif
 
 #include "testpmd.h"
 
@@ -2108,6 +2112,9 @@ signal_handler(int signum)
 		/* uninitialize packet capture framework */
 		rte_pdump_uninit();
 #endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+		rte_latencystats_uninit();
+#endif
 		force_quit();
 		/* exit with the expected status */
 		signal(signum, SIG_DFL);
@@ -2165,6 +2172,9 @@ main(int argc, char** argv)
 	/* set all ports to promiscuous mode by default */
 	FOREACH_PORT(port_id, ports)
 		rte_eth_promiscuous_enable(port_id);
+#ifdef RTE_LIBRTE_LATENCY_STATS
+	rte_latencystats_init(1, NULL);
+#endif
 
 	/* Setup bitrate stats */
 #ifdef RTE_LIBRTE_BITRATE
diff --git a/config/common_base b/config/common_base
index decebe5..762a54c 100644
--- a/config/common_base
+++ b/config/common_base
@@ -603,3 +603,8 @@ CONFIG_RTE_LIBRTE_METRICS=y
 # Compile the bitrate statistics library
 #
 CONFIG_RTE_LIBRTE_BITRATE=y
+
+#
+# Compile the latency statistics library
+#
+CONFIG_RTE_LIBRTE_LATENCY_STATS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 5e194b0..1cacacc 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -152,4 +152,5 @@ There are many libraries, so their headers may be grouped by topics:
   [keepalive]          (@ref rte_keepalive.h),
   [Device Metrics]     (@ref rte_metrics.h),
   [Bitrate Statistics] (@ref rte_bitrate.h),
+  [Latency stats]      (@ref rte_latencystats.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index ff15f5b..1e55da4 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -46,6 +46,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_jobstats \
                           lib/librte_kni \
                           lib/librte_kvargs \
+                          lib/librte_latencystats \
                           lib/librte_lpm \
                           lib/librte_mbuf \
                           lib/librte_mempool \
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 70f93e1..52c7142 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -63,6 +63,10 @@ New Features
   See the :ref:`Generic flow API <Generic_flow_API>` documentation for more
   information.
 
+* **Added latency stats library.**
+  A library that facilitates latency stats measurment of the dpdk based applications.
+  The library measures minimum, average, maximum latencies and also jitter
+  in nano seconds.
 
 Resolved Issues
 ---------------
@@ -179,6 +183,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_jobstats.so.1
      librte_kni.so.2
      librte_kvargs.so.1
+   + librte_latencystats.so.1
      librte_lpm.so.2
      librte_mbuf.so.2
      librte_mempool.so.2
diff --git a/lib/Makefile b/lib/Makefile
index e211bc0..6fffa88 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -60,6 +60,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
+DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_latencystats/Makefile b/lib/librte_latencystats/Makefile
new file mode 100644
index 0000000..f744da6
--- /dev/null
+++ b/lib/librte_latencystats/Makefile
@@ -0,0 +1,57 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_latencystats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
+LDLIBS += -lm
+LDLIBS += -lpthread
+
+EXPORT_MAP := rte_latencystats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) := rte_latencystats.c
+
+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)-include := rte_latencystats.h
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_latencystats/rte_latencystats.c b/lib/librte_latencystats/rte_latencystats.c
new file mode 100644
index 0000000..dcde7f6
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats.c
@@ -0,0 +1,389 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <unistd.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <math.h>
+#include <pthread.h>
+
+#include <rte_mbuf.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_metrics.h>
+#include <rte_memzone.h>
+#include <rte_lcore.h>
+#include <rte_timer.h>
+
+#include "rte_latencystats.h"
+
+/** Nano seconds per second */
+#define NS_PER_SEC 1E9
+
+/** Clock cycles per nano second */
+#define CYCLES_PER_NS (rte_get_timer_hz() / NS_PER_SEC)
+
+/* Macros for printing using RTE_LOG */
+#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1
+
+static pthread_t latency_stats_thread;
+static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats";
+static int latency_stats_index;
+static uint64_t samp_intvl;
+static uint64_t timer_tsc;
+static uint64_t prev_tsc;
+
+static struct rte_latency_stats {
+	float min_latency; /**< Minimum latency in nano seconds */
+	float avg_latency; /**< Average latency in nano seconds */
+	float max_latency; /**< Maximum latency in nano seconds */
+	float jitter; /** Latency variation */
+} *glob_stats;
+
+static struct rxtx_cbs {
+	struct rte_eth_rxtx_callback *cb;
+} rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT],
+	tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
+
+struct latency_stats_nameoff {
+	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	unsigned int offset;
+};
+
+static const struct latency_stats_nameoff lat_stats_strings[] = {
+	{"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)},
+	{"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)},
+	{"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)},
+	{"jitter_ns", offsetof(struct rte_latency_stats, jitter)},
+};
+
+#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \
+				sizeof(lat_stats_strings[0]))
+
+static __attribute__((noreturn)) void *
+report_latency_stats(__rte_unused void *arg)
+{
+	for (;;) {
+		unsigned int i;
+		float *stats_ptr = NULL;
+		uint64_t values[NUM_LATENCY_STATS] = {0};
+		int ret;
+
+		for (i = 0; i < NUM_LATENCY_STATS; i++) {
+			stats_ptr = RTE_PTR_ADD(glob_stats,
+					lat_stats_strings[i].offset);
+			values[i] = (uint64_t)floor((*stats_ptr)/
+					CYCLES_PER_NS);
+		}
+
+		ret = rte_metrics_update_metrics(RTE_METRICS_NONPORT,
+						latency_stats_index,
+						values, NUM_LATENCY_STATS);
+		if (ret < 0)
+			RTE_LOG(INFO, LATENCY_STATS,
+				"Failed to push the stats\n");
+	}
+}
+
+static void
+rte_latencystats_fill_values(struct rte_metric_value *values)
+{
+	unsigned int i;
+	float *stats_ptr = NULL;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++) {
+		stats_ptr = RTE_PTR_ADD(glob_stats,
+				lat_stats_strings[i].offset);
+		values[i].key = i;
+		values[i].value = (uint64_t)floor((*stats_ptr)/
+						CYCLES_PER_NS);
+	}
+}
+
+static uint16_t
+add_time_stamps(uint8_t pid __rte_unused,
+		uint16_t qid __rte_unused,
+		struct rte_mbuf **pkts,
+		uint16_t nb_pkts,
+		uint16_t max_pkts __rte_unused,
+		void *user_cb __rte_unused)
+{
+	unsigned int i;
+	uint64_t diff_tsc, now;
+
+	/*
+	 * For every sample interval,
+	 * time stamp is marked on one received packet.
+	 */
+	now = rte_rdtsc();
+	for (i = 0; i < nb_pkts; i++) {
+		diff_tsc = now - prev_tsc;
+		timer_tsc += diff_tsc;
+		if (timer_tsc >= samp_intvl) {
+			/*
+			 * TBD: Mark the timestamp only
+			 * if not already marked by the
+			 * hardware or the PMD.
+			 */
+			pkts[i]->timestamp = now;
+			timer_tsc = 0;
+		}
+		prev_tsc = now;
+		now = rte_rdtsc();
+	}
+
+	return nb_pkts;
+}
+
+static uint16_t
+calc_latency(uint8_t pid __rte_unused,
+		uint16_t qid __rte_unused,
+		struct rte_mbuf **pkts,
+		uint16_t nb_pkts,
+		void *_ __rte_unused)
+{
+	unsigned int i, cnt = 0;
+	uint64_t now;
+	float latency[nb_pkts];
+	static float prev_latency;
+	/*
+	 * Alpha represents degree of weighting decrease in EWMA,
+	 * a constant smoothing factor between 0 and 1. The value
+	 * is used below for measuring average latency.
+	 */
+	const float alpha = 0.2;
+
+	now = rte_rdtsc();
+	for (i = 0; i < nb_pkts; i++) {
+		if (pkts[i]->timestamp)
+			latency[cnt++] = now - pkts[i]->timestamp;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		/*
+		 * The jitter is calculated as statistical mean of interpacket
+		 * delay variation. The "jitter estimate" is computed by taking
+		 * the absolute values of the ipdv sequence and applying an
+		 * exponential filter with parameter 1/16 to generate the
+		 * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter,
+		 * D(i-1,i) is difference in latency of two consecutive packets
+		 * i-1 and i.
+		 * Reference: Calculated as per RFC 5481, sec 4.1,
+		 * RFC 3393 sec 4.5, RFC 1889 sec.
+		 */
+		glob_stats->jitter +=  (abs(prev_latency - latency[i])
+					- glob_stats->jitter)/16;
+		if (glob_stats->min_latency == 0)
+			glob_stats->min_latency = latency[i];
+		else if (latency[i] < glob_stats->min_latency)
+			glob_stats->min_latency = latency[i];
+		else if (latency[i] > glob_stats->max_latency)
+			glob_stats->max_latency = latency[i];
+		/*
+		 * The average latency is measured using exponential moving
+		 * average, i.e. using EWMA
+		 * https://en.wikipedia.org/wiki/Moving_average
+		 */
+		glob_stats->avg_latency +=
+			alpha * (latency[i] - glob_stats->avg_latency);
+		prev_latency = latency[i];
+	}
+
+	return nb_pkts;
+}
+
+int
+rte_latencystats_init(uint64_t samp_intvl,
+		rte_latency_stats_flow_type_fn user_cb)
+{
+	unsigned int i;
+	uint8_t pid;
+	uint16_t qid;
+	struct rxtx_cbs *cbs = NULL;
+	const uint8_t nb_ports = rte_eth_dev_count();
+	const char *ptr_strings[NUM_LATENCY_STATS] = {0};
+	const struct rte_memzone *mz = NULL;
+	const unsigned int flags = 0;
+
+	/** Allocate stats in shared memory fo muliti process support */
+	mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats),
+					rte_socket_id(), flags);
+	if (mz == NULL) {
+		RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n",
+			__func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	glob_stats = mz->addr;
+	samp_intvl *= CYCLES_PER_NS;
+
+	/** Register latency stats with stats library */
+	for (i = 0; i < NUM_LATENCY_STATS; i++)
+		ptr_strings[i] = lat_stats_strings[i].name;
+
+	latency_stats_index = rte_metrics_reg_metrics(ptr_strings,
+							NUM_LATENCY_STATS);
+	if (latency_stats_index < 0) {
+		RTE_LOG(DEBUG, LATENCY_STATS,
+			"Failed to register latency stats names\n");
+		return -1;
+	}
+
+	/** Register Rx/Tx callbacks */
+	for (pid = 0; pid < nb_ports; pid++) {
+		struct rte_eth_dev_info dev_info;
+		rte_eth_dev_info_get(pid, &dev_info);
+		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
+			cbs = &rx_cbs[pid][qid];
+			cbs->cb = rte_eth_add_first_rx_callback(pid, qid,
+					add_time_stamps, user_cb);
+			if (!cbs->cb)
+				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
+					"register Rx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
+			cbs = &tx_cbs[pid][qid];
+			cbs->cb =  rte_eth_add_tx_callback(pid, qid,
+					calc_latency, user_cb);
+			if (!cbs->cb)
+				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
+					"register Tx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+	}
+
+	int ret = 0;
+	char thread_name[RTE_MAX_THREAD_NAME_LEN];
+
+	/** Create the host thread to update latency stats to stats library */
+	ret = pthread_create(&latency_stats_thread, NULL, report_latency_stats,
+				NULL);
+	if (ret != 0) {
+		RTE_LOG(ERR, LATENCY_STATS,
+			"Failed to create the latency stats thread:%s, %s:%d\n",
+			strerror(errno), __func__, __LINE__);
+		return -1;
+	}
+	/** Set thread_name for aid in debugging */
+	snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "latency-stats-thread");
+	ret = rte_thread_setname(latency_stats_thread, thread_name);
+	if (ret != 0)
+		RTE_LOG(DEBUG, LATENCY_STATS,
+			"Failed to set thread name for latency stats handling\n");
+
+	return 0;
+}
+
+int
+rte_latencystats_uninit(void)
+{
+	uint8_t pid;
+	uint16_t qid;
+	int ret = 0;
+	struct rxtx_cbs *cbs = NULL;
+	const uint8_t nb_ports = rte_eth_dev_count();
+
+	/** De register Rx/Tx callbacks */
+	for (pid = 0; pid < nb_ports; pid++) {
+		struct rte_eth_dev_info dev_info;
+		rte_eth_dev_info_get(pid, &dev_info);
+		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
+			cbs = &rx_cbs[pid][qid];
+			ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb);
+			if (ret)
+				RTE_LOG(INFO, LATENCY_STATS, "failed to "
+					"remove Rx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
+			cbs = &tx_cbs[pid][qid];
+			ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb);
+			if (ret)
+				RTE_LOG(INFO, LATENCY_STATS, "failed to "
+					"remove Tx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+	}
+
+	/** Cancel the thread */
+	ret = pthread_cancel(latency_stats_thread);
+	if (ret != 0) {
+		RTE_LOG(ERR, LATENCY_STATS,
+			"Failed to cancel latency stats update thread:"
+			"%s,%s:%d\n",
+			strerror(errno), __func__, __LINE__);
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size)
+{
+	unsigned int i;
+
+	if (names == NULL || size < NUM_LATENCY_STATS)
+		return NUM_LATENCY_STATS;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++)
+		snprintf(names[i].name, sizeof(names[i].name),
+				"%s", lat_stats_strings[i].name);
+
+	return NUM_LATENCY_STATS;
+}
+
+int
+rte_latencystats_get(struct rte_metric_value *values, uint16_t size)
+{
+	if (size < NUM_LATENCY_STATS || values == NULL)
+		return NUM_LATENCY_STATS;
+
+	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		const struct rte_memzone *mz;
+		mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS);
+		if (mz == NULL) {
+			RTE_LOG(ERR, LATENCY_STATS,
+				"Latency stats memzone not found\n");
+			return -ENOMEM;
+		}
+		glob_stats =  mz->addr;
+	}
+
+	/* Retrieve latency stats */
+	rte_latencystats_fill_values(values);
+
+	return NUM_LATENCY_STATS;
+}
diff --git a/lib/librte_latencystats/rte_latencystats.h b/lib/librte_latencystats/rte_latencystats.h
new file mode 100644
index 0000000..405b878
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats.h
@@ -0,0 +1,146 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 _RTE_LATENCYSTATS_H_
+#define _RTE_LATENCYSTATS_H_
+
+/**
+ * @file
+ * RTE latency stats
+ *
+ * library to provide application and flow based latency stats.
+ */
+
+#include <rte_metrics.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  Note: This function pointer is for future flow based latency stats
+ *  implementation.
+ *
+ * Function type used for identifting flow types of a Rx packet.
+ *
+ * The callback function is called on Rx for each packet.
+ * This function is used for flow based latency calculations.
+ *
+ * @param pkt
+ *   Packet that has to be identified with its flow types.
+ * @param user_param
+ *   The arbitrary user parameter passed in by the application when
+ *   the callback was originally configured.
+ * @return
+ *   The flow_mask, representing the multiple flow types of a packet.
+ */
+typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt,
+							void *user_param);
+
+/**
+ *  Registers Rx/Tx callbacks for each active port, queue.
+ *
+ * @param samp_intvl
+ *  Sampling time period in nano seconds, at which packet
+ *  should be marked with time stamp.
+ * @param user_cb
+ *  Note: This param is for future flow based latency stats
+ *  implementation.
+ *  User callback to be called to get flow types of a packet.
+ *  Used for flow based latency calculation.
+ *  If the value is NULL, global stats will be calculated,
+ *  else flow based latency stats will be calculated.
+ *  For now just pass on the NULL value to this param.
+ *  @return
+ *   -1     : On error
+ *   -ENOMEM: On error
+ *    0     : On success
+ */
+int rte_latencystats_init(uint64_t samp_intvl,
+			rte_latency_stats_flow_type_fn user_cb);
+
+/**
+ *  Removes registered Rx/Tx callbacks for each active port, queue.
+ *
+ *  @return
+ *   -1: On error
+ *    0: On success
+ */
+int rte_latencystats_uninit(void);
+
+/**
+ * Retrieve names of latency statistics
+ *
+ * @param names
+ *  Block of memory to insert names into. Must be at least size in capacity.
+ *  If set to NULL, function returns required capacity.
+ * @param size
+ *  Capacity of latency stats names (number of names).
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ */
+int rte_latencystats_get_names(struct rte_metric_name *names,
+				uint16_t size);
+
+/**
+ * Retrieve latency statistics.
+ *
+ * @param values
+ *   A pointer to a table of structure of type *rte_metric_value*
+ *   to be filled with latency statistics ids and values.
+ *   This parameter can be set to NULL if size is 0.
+ * @param size
+ *   The size of the stats table, which should be large enough to store
+ *   all the latency stats.
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ *   -ENOMEM: On failure.
+ */
+int rte_latencystats_get(struct rte_metric_value *values,
+			uint16_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_LATENCYSTATS_H_ */
diff --git a/lib/librte_latencystats/rte_latencystats_version.map b/lib/librte_latencystats/rte_latencystats_version.map
new file mode 100644
index 0000000..502018e
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats_version.map
@@ -0,0 +1,10 @@
+DPDK_17.02 {
+	global:
+
+	rte_latencystats_get;
+	rte_latencystats_get_names;
+	rte_latencystats_init;
+	rte_latencystats_uninit;
+
+	local: *;
+};
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index 4476d75..df85d48 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -506,6 +506,9 @@ struct rte_mbuf {
 
 	/** Timesync flags for use with IEEE1588. */
 	uint16_t timesync;
+
+	/** Timestamp for measuring latency. */
+	uint64_t timestamp;
 } __rte_cache_aligned;
 
 /**
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 6aac5ac..1d36fad 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -100,7 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
 _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
-
+_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)  += -lrte_latencystats
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* Re: [PATCH v6 2/4] lib: add bitrate statistics library
  2017-01-11 16:03           ` [PATCH v6 2/4] lib: add bitrate statistics library Remy Horton
@ 2017-01-11 16:15             ` Stephen Hemminger
  2017-01-16 13:18               ` Remy Horton
  0 siblings, 1 reply; 115+ messages in thread
From: Stephen Hemminger @ 2017-01-11 16:15 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev, Thomas Monjalon

On Thu, 12 Jan 2017 00:03:12 +0800
Remy Horton <remy.horton@intel.com> wrote:

> +
> +struct rte_stats_bitrates_s *
> +rte_stats_bitrate_create(void)
> +{
> +	return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0);
> +}
> +

You want these statistics to be cache aligned (ie not 0) to avoid
false cache sharing.

Since these statistics are often associated with a device would it
not make sense to have a NUMA socket associated with the alllocation?

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

* Re: [PATCH v6 0/4] Expanded statistics reporting
  2017-01-11 16:03         ` [PATCH v6 0/4] Expanded statistics reporting Remy Horton
                             ` (3 preceding siblings ...)
  2017-01-11 16:03           ` [PATCH v6 4/4] latencystats: added new library for latency stats Remy Horton
@ 2017-01-11 16:58           ` Thomas Monjalon
  2017-01-16 16:19           ` [PATCH v7 0/6] " Remy Horton
  5 siblings, 0 replies; 115+ messages in thread
From: Thomas Monjalon @ 2017-01-11 16:58 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev

2017-01-12 00:03, Remy Horton:
> Due to merge issues Reshma's latency statistics, which depends
> on the reporting library, has been merged into this patchset.

You losed Reshma authorship. It can be fixed with "git commit --amend --author"

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

* Re: [PATCH v6 1/4] lib: add information metrics library
  2017-01-11 16:03           ` [PATCH v6 1/4] lib: add information metrics library Remy Horton
@ 2017-01-12 13:22             ` Thomas Monjalon
  2017-01-12 15:30               ` Remy Horton
  0 siblings, 1 reply; 115+ messages in thread
From: Thomas Monjalon @ 2017-01-12 13:22 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev

2017-01-12 00:03, Remy Horton:
> This patch adds a new information metric library that allows other
> modules to register named metrics and update their values. It is
> intended to be independent of ethdev, rather than mixing ethdev
> and non-ethdev information in xstats.

[...]
> --- a/doc/api/doxy-api.conf
> +++ b/doc/api/doxy-api.conf
> @@ -58,6 +58,7 @@ INPUT                   = doc/api/doxy-api-index.md \
>                            lib/librte_reorder \
>                            lib/librte_ring \
>                            lib/librte_sched \
> +                          lib/librte_metrics \
>                            lib/librte_table \
>                            lib/librte_timer \
>                            lib/librte_vhost

It is not in the right order.
Tip: when you add an item to a list, you should ask yourself what is the
order. There are 3 types of order for the lists in DPDK:
	- chronological (add at the end)
	- alphabetical
	- logical/semantic
The game is to find the right one :)

[...]
> @@ -171,6 +177,7 @@ The libraries prepended with a plus sign were incremented in this version.
>       librte_mbuf.so.2
>       librte_mempool.so.2
>       librte_meter.so.1
> +   + librte_metrics.so.1
>       librte_net.so.1
>       librte_pdump.so.1
>       librte_pipeline.so.3

Right order here ;)

[...]
> --- /dev/null
> +++ b/lib/librte_metrics/rte_metrics.h
> +/** Used to indicate port-independent information */
> +#define RTE_METRICS_NONPORT -1

I do not understand this constant.
Why using the word "port" to name any device?
What means independent?

> +/**
> + * Metric name
> + */
> +struct rte_metric_name {
> +	/** String describing metric */
> +	char name[RTE_METRICS_MAX_NAME_LEN];
> +};

Why a struct for a simple string?

> +/**
> + * Metric name.

Copy/paste typo?

> + */
> +struct rte_metric_value {
> +	/** Numeric identifier of metric */
> +	uint16_t key;

How the key is bound to the name?
Remember how the xstats comments were improved:
	http://dpdk.org/commit/6d52d1d

> +	/** Value for metric */
> +	uint64_t value;
> +};
> +
> +
> +/**
> + * Initializes metric module. This only has to be explicitly called if you
> + * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a
> + * secondary process. This function must be called from a primary process.
> + */
> +void rte_metrics_init(void);
> +
> +
> +/**
> + * Register a metric

You need to explain what is implied in registering.
I have the same comment for registering a set of metrics.

[...]
> +int rte_metrics_reg_metric(const char *name);
> +
> +/**
> + * Register a set of metrics
[...]
> +int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names);
> +
> +/**
> + * Get metric name-key lookup table.
> + *
> + * @param names
> + *   Array of names to receive key names
> + *
> + * @param capacity
> + *   Space available in names

What happens if there is not enough space?

> + * @return
> + *   - Non-negative: Success (number of names)
> + *   - Negative: Failure
> + */
> +int rte_metrics_get_names(
> +	struct rte_metric_name *names,
> +	uint16_t capacity);

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

* Re: [PATCH v6 3/4] app/test-pmd: add support for bitrate statistics
  2017-01-11 16:03           ` [PATCH v6 3/4] app/test-pmd: add support for bitrate statistics Remy Horton
@ 2017-01-12 13:32             ` Thomas Monjalon
  0 siblings, 0 replies; 115+ messages in thread
From: Thomas Monjalon @ 2017-01-12 13:32 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev

I do not understand clearly this library and the output from testpmd.
It seems you have a need but you do not explain why it is not done in
the application.
Bitrate is specific to ethdev, right?
Why not put it directly in testpmd first?

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

* Re: [PATCH v6 4/4] latencystats: added new library for latency stats
  2017-01-11 16:03           ` [PATCH v6 4/4] latencystats: added new library for latency stats Remy Horton
@ 2017-01-12 13:41             ` Thomas Monjalon
  2017-01-12 14:44               ` Remy Horton
  2017-01-13  9:45               ` Mcnamara, John
  0 siblings, 2 replies; 115+ messages in thread
From: Thomas Monjalon @ 2017-01-12 13:41 UTC (permalink / raw)
  To: Remy Horton, Reshma Pattan; +Cc: dev, olivier.matz

2017-01-12 00:03, Remy Horton:
> Add a library designed to calculate latency statistics and report them
> to the application when queried. The library measures minimum, average and
> maximum latencies, and jitter in nano seconds. The current implementation
> supports global latency stats, i.e. per application stats.

Is it specific to ethdev ports?

> Added new field to mbuf struct to mark the packet arrival time on Rx.

There was another patch adding a timestamp in mbuf:
	http://dpdk.org/ml/archives/dev/2016-October/048809.html

> Modify testpmd code to initialize/uninitialize latency statistics
> calulation.
> 
> Modify the dpdk-procinfo process to display the newly added metrics.
> Added new command line option "--metrics" to display metrics.

It should be a separate patch.

> APIs:
> 
> * Added APIs to initialize and un initialize latency stats
>   calculation.
> * Added API to retrieve latency stats names and values.

Why bitrate and latencies are separate libs?

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

* Re: [PATCH v6 4/4] latencystats: added new library for latency stats
  2017-01-12 13:41             ` Thomas Monjalon
@ 2017-01-12 14:44               ` Remy Horton
  2017-01-13  9:45               ` Mcnamara, John
  1 sibling, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-12 14:44 UTC (permalink / raw)
  To: Thomas Monjalon, Reshma Pattan; +Cc: dev, olivier.matz


On 12/01/2017 13:41, Thomas Monjalon wrote:
> 2017-01-12 00:03, Remy Horton:
>> Add a library designed to calculate latency statistics and report them
>> to the application when queried. The library measures minimum, average and
>> maximum latencies, and jitter in nano seconds. The current implementation
>> supports global latency stats, i.e. per application stats.
>
> Is it specific to ethdev ports?

No (or at least not at the moment).


>> Added new field to mbuf struct to mark the packet arrival time on Rx.
>
> There was another patch adding a timestamp in mbuf:
> 	http://dpdk.org/ml/archives/dev/2016-October/048809.html

Will look into it. Since time is tight will have internal discussion 
whether latency will make it into 17.02..


>> APIs:
>>
>> * Added APIs to initialize and un initialize latency stats
>>   calculation.
>> * Added API to retrieve latency stats names and values.
>
> Why bitrate and latencies are separate libs?

They were developed independently by different people in response to 
seperate requirements.

Reshma went on extended leave, so I took over the latency patch at the 
last moment when development was complete. Aside from rebase-related 
fixups and one printf change it is the last version of her seperate 
patch included verbatim.

..Remy

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

* Re: [PATCH v6 1/4] lib: add information metrics library
  2017-01-12 13:22             ` Thomas Monjalon
@ 2017-01-12 15:30               ` Remy Horton
  2017-01-12 19:05                 ` Thomas Monjalon
  0 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-01-12 15:30 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev


On 12/01/2017 13:22, Thomas Monjalon wrote:
> 2017-01-12 00:03, Remy Horton:
[..]
>> --- /dev/null
>> +++ b/lib/librte_metrics/rte_metrics.h
>> +/** Used to indicate port-independent information */
>> +#define RTE_METRICS_NONPORT -1
>
> I do not understand this constant.
> Why using the word "port" to name any device?
> What means independent?

The metric library hold two sets of values: Ones specific to ports, and 
ones that are global/aggregate. Agree "non port" is not the clearest 
choice of name..


>> +/**
>> + * Metric name
>> + */
>> +struct rte_metric_name {
>> +	/** String describing metric */
>> +	char name[RTE_METRICS_MAX_NAME_LEN];
>> +};
>
> Why a struct for a simple string?

It is modelled after xstats, which does the same thing. In this case 
thinking was that using:

rte_metrics_get_names(struct rte_metric_name *names,
	uint16_t capacity)

would be tidier than (e.g.):

rte_metrics_get_names(char *names[RTE_METRICS_MAX_NAME_LEN],
	uint16_t capacity)


>> + */
>> +struct rte_metric_value {
>> +	/** Numeric identifier of metric */
>> +	uint16_t key;
>
> How the key is bound to the name?

Corresponds to array position in struct rte_metric_name. Will amend 
doxygen comments.


> Remember how the xstats comments were improved:
> 	http://dpdk.org/commit/6d52d1d

Will take account for them. I wrote this code back in October, so it 
slipped my mind to apply the same comments to this module.

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

* Re: [PATCH v6 1/4] lib: add information metrics library
  2017-01-12 15:30               ` Remy Horton
@ 2017-01-12 19:05                 ` Thomas Monjalon
  2017-01-16 10:27                   ` Remy Horton
  0 siblings, 1 reply; 115+ messages in thread
From: Thomas Monjalon @ 2017-01-12 19:05 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev

2017-01-12 15:30, Remy Horton:
> 
> On 12/01/2017 13:22, Thomas Monjalon wrote:
> > 2017-01-12 00:03, Remy Horton:
> [..]
> >> --- /dev/null
> >> +++ b/lib/librte_metrics/rte_metrics.h
> >> +/** Used to indicate port-independent information */
> >> +#define RTE_METRICS_NONPORT -1
> >
> > I do not understand this constant.
> > Why using the word "port" to name any device?
> > What means independent?
> 
> The metric library hold two sets of values: Ones specific to ports, and 
> ones that are global/aggregate. Agree "non port" is not the clearest 
> choice of name..

I think you should not use the word "port" at all.

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

* Re: [PATCH v6 4/4] latencystats: added new library for latency stats
  2017-01-12 13:41             ` Thomas Monjalon
  2017-01-12 14:44               ` Remy Horton
@ 2017-01-13  9:45               ` Mcnamara, John
  2017-01-13  9:53                 ` Thomas Monjalon
  1 sibling, 1 reply; 115+ messages in thread
From: Mcnamara, John @ 2017-01-13  9:45 UTC (permalink / raw)
  To: Thomas Monjalon, Horton, Remy, Pattan, Reshma; +Cc: dev, olivier.matz



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Thomas Monjalon
> Sent: Thursday, January 12, 2017 1:41 PM
> To: Horton, Remy <remy.horton@intel.com>; Pattan, Reshma
> <reshma.pattan@intel.com>
> Cc: dev@dpdk.org; olivier.matz@6wind.com
> Subject: Re: [dpdk-dev] [PATCH v6 4/4] latencystats: added new library for
> latency stats
> 
> 2017-01-12 00:03, Remy Horton:
> > Add a library designed to calculate latency statistics and report them
> > to the application when queried. The library measures minimum, average
> > and maximum latencies, and jitter in nano seconds. The current
> > implementation supports global latency stats, i.e. per application
> stats.
> 
> Is it specific to ethdev ports?
> 
> > Added new field to mbuf struct to mark the packet arrival time on Rx.
> 
> There was another patch adding a timestamp in mbuf:
> 	http://dpdk.org/ml/archives/dev/2016-October/048809.html

Hi Thomas,

Is that an issue? The other patch adds the same field for more or less the same purpose.
If the other patch goes in we can rework this patch or if this patch goes in the
other one won't be required.

John

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

* Re: [PATCH v6 4/4] latencystats: added new library for latency stats
  2017-01-13  9:45               ` Mcnamara, John
@ 2017-01-13  9:53                 ` Thomas Monjalon
  2017-01-16 16:18                   ` Mcnamara, John
  0 siblings, 1 reply; 115+ messages in thread
From: Thomas Monjalon @ 2017-01-13  9:53 UTC (permalink / raw)
  To: Mcnamara, John, Horton, Remy; +Cc: Pattan, Reshma, dev, olivier.matz

2017-01-13 09:45, Mcnamara, John:
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Thomas Monjalon
> > 2017-01-12 00:03, Remy Horton:
> > > Add a library designed to calculate latency statistics and report them
> > > to the application when queried. The library measures minimum, average
> > > and maximum latencies, and jitter in nano seconds. The current
> > > implementation supports global latency stats, i.e. per application
> > stats.
> > 
> > Is it specific to ethdev ports?
> > 
> > > Added new field to mbuf struct to mark the packet arrival time on Rx.
> > 
> > There was another patch adding a timestamp in mbuf:
> > 	http://dpdk.org/ml/archives/dev/2016-October/048809.html
> 
> Hi Thomas,
> 
> Is that an issue? The other patch adds the same field for more or less the same purpose.
> If the other patch goes in we can rework this patch or if this patch goes in the
> other one won't be required.

Yes
The only issue is that it is not yet accepted or merged.
I think Olivier was considering it in a more global mbuf rework.

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

* Re: [PATCH v6 1/4] lib: add information metrics library
  2017-01-12 19:05                 ` Thomas Monjalon
@ 2017-01-16 10:27                   ` Remy Horton
  0 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-16 10:27 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

On 12/01/2017 19:05, Thomas Monjalon wrote:
> 2017-01-12 15:30, Remy Horton:
[..]
>> The metric library hold two sets of values: Ones specific to ports, and
>> ones that are global/aggregate. Agree "non port" is not the clearest
>> choice of name..
>
> I think you should not use the word "port" at all.
>
Changing it is on the todo list.. :)

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

* Re: [PATCH v6 2/4] lib: add bitrate statistics library
  2017-01-11 16:15             ` Stephen Hemminger
@ 2017-01-16 13:18               ` Remy Horton
  0 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-16 13:18 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev, Thomas Monjalon

On 11/01/2017 16:15, Stephen Hemminger wrote:
[..]
> You want these statistics to be cache aligned (ie not 0) to avoid
> false cache sharing.

Done.

> Since these statistics are often associated with a device would it
> not make sense to have a NUMA socket associated with the alllocation?

Makes sense, although given the intended frequency of access and the 
amount of data, not sure it would gain much.

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

* Re: [PATCH v6 4/4] latencystats: added new library for latency stats
  2017-01-13  9:53                 ` Thomas Monjalon
@ 2017-01-16 16:18                   ` Mcnamara, John
  0 siblings, 0 replies; 115+ messages in thread
From: Mcnamara, John @ 2017-01-16 16:18 UTC (permalink / raw)
  To: Thomas Monjalon, Horton, Remy; +Cc: Pattan, Reshma, dev, olivier.matz



> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Friday, January 13, 2017 9:54 AM
> To: Mcnamara, John <john.mcnamara@intel.com>; Horton, Remy
> <remy.horton@intel.com>
> Cc: Pattan, Reshma <reshma.pattan@intel.com>; dev@dpdk.org;
> olivier.matz@6wind.com
> Subject: Re: [dpdk-dev] [PATCH v6 4/4] latencystats: added new library for
> latency stats
>
> ...
> >
> > Is that an issue? The other patch adds the same field for more or less
> the same purpose.
> > If the other patch goes in we can rework this patch or if this patch
> > goes in the other one won't be required.
> 
> Yes
> The only issue is that it is not yet accepted or merged.
> I think Olivier was considering it in a more global mbuf rework.

Hi,

I think we should put the timestamp into this release since more than 
one developer/feature is looking for it. If Olivier does the rework in
the next release he can move it or leave it in the current position.

John

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

* [PATCH v7 0/6] Expanded statistics reporting
  2017-01-11 16:03         ` [PATCH v6 0/4] Expanded statistics reporting Remy Horton
                             ` (4 preceding siblings ...)
  2017-01-11 16:58           ` [PATCH v6 0/4] Expanded statistics reporting Thomas Monjalon
@ 2017-01-16 16:19           ` Remy Horton
  2017-01-16 16:19             ` [PATCH v7 1/6] lib: add information metrics library Remy Horton
                               ` (6 more replies)
  5 siblings, 7 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-16 16:19 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patchset extends statistics reporting to include peak and
average data-rate metrics. It comes in two parts: a statistics
reporting library, and a bitrate calculation library that uses
it. This structure is intended to seperate statistic reporting
from ethdev and allow more flexible metric registration.

Due to merge issues Reshma's latency statistics, which depends
on the reporting library, has been merged into this patchset.

--

v7 changes:
* RTE_METRICS_NONPORT renamed to RTE_METRICS_GLOBAL
* Multiple changes to rte_metrics.h doxygen documentation
* Split apart latency patch into lib, test-pmd, & proc_info parts
* Reordered patches by functionality
* Insufficent capacity return value changed from -ERANGE to actual size
* Cache alignment in bitrate library
* Tightened up const usage to avoid STATIC_CONST_CHAR_ARRAY warning
* Reshma reinstated as author for (now split) latency patch
* Rebase to master

v6 changes:
* Metrics display now has "Non port specific" rather than "port -1"
* Fixed sign issue in EWMA delta calculation
* Rebased to master

v5 changes:
* Updated Shared Library Versions in release notes
* Merged in Reshma's latencystats library

v4 changes:
* References to 16.11 changed to 17.02
* Fetching of non-port values was broken
* Added sanity checks to value fetching
* rte_stat_value renamed to rte_metric_value
* Corrected doxygen descriptions
* Added MAINTAINERS entries
* Added #ifdef directives to bitrate code in test-pmd

v3 changes:
* Marked rte_stats_bitrate_s as internal
* Minor integer roundoff correction
* Coding style corrections
* Removed spurious object allocation
* Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3.
* Reintroduced non-port values (RTE_METRICS_NONPORT)
* Added spinlocks to metric library
* Removed spurious test registration/update
* Added release notes entries

v2 changes:
* Uses a new metrics library rather than being part of ethdev


Remy Horton (3):
  lib: add information metrics library
  lib: add bitrate statistics library
  app/test-pmd: add bitrate statistics calculation

Reshma Pattan (3):
  app/proc_info: add metrics displaying
  lib: added new library for latency stats
  app/test-pmd: add latency statistics calculation

 MAINTAINERS                                        |  13 +
 app/proc_info/main.c                               |  73 ++++
 app/test-pmd/testpmd.c                             |  46 +++
 config/common_base                                 |  15 +
 doc/api/doxy-api-index.md                          |   3 +
 doc/api/doxy-api.conf                              |   3 +
 doc/guides/rel_notes/release_17_02.rst             |  18 +
 lib/Makefile                                       |   3 +
 lib/librte_bitratestats/Makefile                   |  53 +++
 lib/librte_bitratestats/rte_bitrate.c              | 132 +++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++
 .../rte_bitratestats_version.map                   |   9 +
 lib/librte_latencystats/Makefile                   |  57 +++
 lib/librte_latencystats/rte_latencystats.c         | 389 +++++++++++++++++++++
 lib/librte_latencystats/rte_latencystats.h         | 146 ++++++++
 .../rte_latencystats_version.map                   |  10 +
 lib/librte_mbuf/rte_mbuf.h                         |   3 +
 lib/librte_metrics/Makefile                        |  51 +++
 lib/librte_metrics/rte_metrics.c                   | 310 ++++++++++++++++
 lib/librte_metrics/rte_metrics.h                   | 223 ++++++++++++
 lib/librte_metrics/rte_metrics_version.map         |  13 +
 mk/rte.app.mk                                      |   3 +
 22 files changed, 1653 insertions(+)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map
 create mode 100644 lib/librte_latencystats/Makefile
 create mode 100644 lib/librte_latencystats/rte_latencystats.c
 create mode 100644 lib/librte_latencystats/rte_latencystats.h
 create mode 100644 lib/librte_latencystats/rte_latencystats_version.map
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

-- 
2.5.5

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

* [PATCH v7 1/6] lib: add information metrics library
  2017-01-16 16:19           ` [PATCH v7 0/6] " Remy Horton
@ 2017-01-16 16:19             ` Remy Horton
  2017-01-17 11:01               ` Van Haaren, Harry
  2017-01-16 16:19             ` [PATCH v7 2/6] app/proc_info: add metrics displaying Remy Horton
                               ` (5 subsequent siblings)
  6 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-01-16 16:19 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patch adds a new information metric library that allows other
modules to register named metrics and update their values. It is
intended to be independent of ethdev, rather than mixing ethdev
and non-ethdev information in xstats.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                |   5 +
 config/common_base                         |   5 +
 doc/api/doxy-api-index.md                  |   1 +
 doc/api/doxy-api.conf                      |   1 +
 doc/guides/rel_notes/release_17_02.rst     |   8 +
 lib/Makefile                               |   1 +
 lib/librte_metrics/Makefile                |  51 +++++
 lib/librte_metrics/rte_metrics.c           | 310 +++++++++++++++++++++++++++++
 lib/librte_metrics/rte_metrics.h           | 223 +++++++++++++++++++++
 lib/librte_metrics/rte_metrics_version.map |  13 ++
 mk/rte.app.mk                              |   2 +
 11 files changed, 620 insertions(+)
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 9645c9b..4a19497 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -596,6 +596,11 @@ F: lib/librte_jobstats/
 F: examples/l2fwd-jobstats/
 F: doc/guides/sample_app_ug/l2_forward_job_stats.rst
 
+Metrics
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_metrics/
+F: doc/guides/sample_app_ug/keep_alive.rst
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index 8e9dcfa..0eb3866 100644
--- a/config/common_base
+++ b/config/common_base
@@ -593,3 +593,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
 CONFIG_RTE_TEST_PMD=y
 CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
 CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+
+#
+# Compile the device metrics library
+#
+CONFIG_RTE_LIBRTE_METRICS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 72d59b2..94f0f69 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -150,4 +150,5 @@ There are many libraries, so their headers may be grouped by topics:
   [common]             (@ref rte_common.h),
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
+  [Device Metrics]     (@ref rte_metrics.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index b340fcf..194b670 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -50,6 +50,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_mbuf \
                           lib/librte_mempool \
                           lib/librte_meter \
+                          lib/librte_metrics \
                           lib/librte_net \
                           lib/librte_pdump \
                           lib/librte_pipeline \
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index d445d64..4fca29b 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -34,6 +34,12 @@ New Features
 
      Refer to the previous release notes for examples.
 
+   * **Added information metric library.**
+
+     A library that allows information metrics to be added and update. It is
+     intended to provide a reporting mechanism that is independent of the
+     ethdev library.
+
      This section is a comment. do not overwrite or remove it.
      Also, make sure to start the actual text at the margin.
      =========================================================
@@ -161,6 +167,7 @@ The libraries prepended with a plus sign were incremented in this version.
 .. code-block:: diff
 
      librte_acl.so.2
+   + librte_bitratestats.so.1
      librte_cfgfile.so.2
      librte_cmdline.so.2
      librte_cryptodev.so.2
@@ -176,6 +183,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_mbuf.so.2
      librte_mempool.so.2
      librte_meter.so.1
+   + librte_metrics.so.1
      librte_net.so.1
      librte_pdump.so.1
      librte_pipeline.so.3
diff --git a/lib/Makefile b/lib/Makefile
index 990f23a..5d85dcf 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table
 DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
+DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile
new file mode 100644
index 0000000..8d6e23a
--- /dev/null
+++ b/lib/librte_metrics/Makefile
@@ -0,0 +1,51 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_metrics.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_metrics_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c
new file mode 100644
index 0000000..5072f4d
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.c
@@ -0,0 +1,310 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <string.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_lcore.h>
+#include <rte_memzone.h>
+#include <rte_spinlock.h>
+
+#define RTE_METRICS_MAX_METRICS 256
+#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS"
+
+/**
+ * Internal stats metadata and value entry.
+ *
+ * @internal
+ * @param name
+ *   Name of metric
+ * @param value
+ *   Current value for metric
+ * @param idx_next_set
+ *   Index of next root element (zero for none)
+ * @param idx_next_metric
+ *   Index of next metric in set (zero for none)
+ *
+ * Only the root of each set needs idx_next_set but since it has to be
+ * assumed that number of sets could equal total number of metrics,
+ * having a separate set metadata table doesn't save any memory.
+ */
+struct rte_metrics_meta_s {
+	char name[RTE_METRICS_MAX_NAME_LEN];
+	uint64_t value[RTE_MAX_ETHPORTS];
+	uint64_t nonport_value;
+	uint16_t idx_next_set;
+	uint16_t idx_next_stat;
+};
+
+/**
+ * Internal stats info structure.
+ *
+ * @internal
+ * @param idx_last_set
+ *   Index of last metadata entry with valid data. This value is
+ *   not valid if cnt_stats is zero.
+ * @param cnt_stats
+ *   Number of metrics.
+ * @param metadata
+ *   Stat data memory block.
+ *
+ * Offsets into metadata are used instead of pointers because ASLR
+ * means that having the same physical addresses in different
+ * processes is not guaranteed.
+ */
+struct rte_metrics_data_s {
+	uint16_t idx_last_set;
+	uint16_t cnt_stats;
+	struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS];
+	rte_spinlock_t lock;
+};
+
+void
+rte_metrics_init(void)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone != NULL)
+		return;
+	memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME,
+		sizeof(struct rte_metrics_data_s), rte_socket_id(), 0);
+	if (memzone == NULL)
+		rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
+	stats = memzone->addr;
+	memset(stats, 0, sizeof(struct rte_metrics_data_s));
+	rte_spinlock_init(&stats->lock);
+}
+
+int
+rte_metrics_reg_metric(const char *name)
+{
+	const char * const list_names[] = {name};
+
+	return rte_metrics_reg_metrics(list_names, 1);
+}
+
+int
+rte_metrics_reg_metrics(const char * const *names, uint16_t cnt_names)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	uint16_t idx_base;
+
+	/* Some sanity checks */
+	if (cnt_names < 1 || names == NULL)
+		return -EINVAL;
+
+	rte_metrics_init();
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS)
+		return -ENOMEM;
+
+	rte_spinlock_lock(&stats->lock);
+
+	/* Overwritten later if this is actually first set.. */
+	stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats;
+
+	stats->idx_last_set = idx_base = stats->cnt_stats;
+
+	for (idx_name = 0; idx_name < cnt_names; idx_name++) {
+		entry = &stats->metadata[idx_name + stats->cnt_stats];
+		strncpy(entry->name, names[idx_name],
+			RTE_METRICS_MAX_NAME_LEN);
+		memset(entry->value, 0, sizeof(entry->value));
+		entry->idx_next_stat = idx_name + stats->cnt_stats + 1;
+	}
+	entry->idx_next_stat = 0;
+	entry->idx_next_set = 0;
+	stats->cnt_stats += cnt_names;
+
+	rte_spinlock_unlock(&stats->lock);
+
+	return idx_base;
+}
+
+int
+rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value)
+{
+	return rte_metrics_update_metrics(port_id, key, &value, 1);
+}
+
+int
+rte_metrics_update_metrics(int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_metric;
+	uint16_t idx_value;
+	uint16_t cnt_setsize;
+
+	if (port_id != RTE_METRICS_GLOBAL &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	rte_metrics_init();
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	rte_spinlock_lock(&stats->lock);
+	idx_metric = key;
+	cnt_setsize = 1;
+	while (idx_metric < stats->cnt_stats) {
+		entry = &stats->metadata[idx_metric];
+		if (entry->idx_next_stat == 0)
+			break;
+		cnt_setsize++;
+		idx_metric++;
+	}
+	/* Check update does not cross set border */
+	if (count > cnt_setsize) {
+		rte_spinlock_unlock(&stats->lock);
+		return -ERANGE;
+	}
+
+	if (port_id == RTE_METRICS_GLOBAL)
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].nonport_value =
+				values[idx_value];
+		}
+	else
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].value[port_id] =
+				values[idx_value];
+		}
+	rte_spinlock_unlock(&stats->lock);
+	return 0;
+}
+
+int
+rte_metrics_get_names(struct rte_metric_name *names,
+	uint16_t capacity)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+	if (names != NULL) {
+		if (capacity < stats->cnt_stats) {
+			return_value = stats->cnt_stats;
+			rte_spinlock_unlock(&stats->lock);
+			return return_value;
+		}
+		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
+			strncpy(names[idx_name].name,
+				stats->metadata[idx_name].name,
+				RTE_METRICS_MAX_NAME_LEN);
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
+
+int
+rte_metrics_get_values(int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	if (port_id != RTE_METRICS_GLOBAL &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+
+	if (values != NULL) {
+		if (capacity < stats->cnt_stats) {
+			return_value = stats->cnt_stats;
+			rte_spinlock_unlock(&stats->lock);
+			return return_value;
+		}
+		if (port_id == RTE_METRICS_GLOBAL)
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->nonport_value;
+			}
+		else
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->value[port_id];
+			}
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
new file mode 100644
index 0000000..fd82af9
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.h
@@ -0,0 +1,223 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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.
+ */
+
+/**
+ * @file
+ *
+ * RTE Metrics module
+ *
+ * Metric information is populated using a push model, where the
+ * information provider calls an update function on the relevant
+ * metrics. Currently only bulk querying of metrics is supported.
+ */
+
+#ifndef _RTE_METRICS_H_
+#define _RTE_METRICS_H_
+
+/** Maximum length of metric name (including null-terminator) */
+#define RTE_METRICS_MAX_NAME_LEN 64
+
+/**
+ * Global (rather than port-specific) metric.
+ *
+ * When used instead of port number by rte_metrics_update_metric()
+ * or rte_metrics_update_metric(), the global metrics, which are
+ * not associated with any specific port, are updated.
+ */
+#define RTE_METRICS_GLOBAL -1
+
+
+/**
+ * A name-key lookup for metrics.
+ *
+ * An array of this structure is returned by rte_metrics_get_names().
+ * The struct rte_eth_stats references these names via their array index.
+ */
+struct rte_metric_name {
+	/** String describing metric */
+	char name[RTE_METRICS_MAX_NAME_LEN];
+};
+
+
+/**
+ * Metric value structure.
+ *
+ * This structure is used by rte_metrics_get_values() to return metrics,
+ * which are statistics that are not generated by PMDs. It maps a name key,
+ * which corresponds to an index in the array returned by
+ * rte_metrics_get_names().
+ */
+struct rte_metric_value {
+	/** Numeric identifier of metric. */
+	uint16_t key;
+	/** Value for metric */
+	uint64_t value;
+};
+
+
+/**
+ * Initializes metric module. This only has to be explicitly called if you
+ * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a
+ * secondary process. This function must be called from a primary process.
+ */
+void rte_metrics_init(void);
+
+/**
+ * Register a metric, making it available as a reporting parameter.
+ *
+ * Registering a metric is the way third-parties declare a parameter
+ * that they wish to be reported. Once registered, the associated
+ * numeric key can be obtained via rte_metrics_get_names(), which
+ * is required for updating said metric's value.
+ *
+ * @param name
+ *   Metric name
+ *
+ * @return
+ *  - Zero or positive: Success
+ *  - Negative: Failure
+ */
+int rte_metrics_reg_metric(const char *name);
+
+/**
+ * Register a set of metrics.
+ *
+ * This is a bulk version of rte_metrics_reg_metrics() and aside from
+ * handling multiple keys at once is functionally identical.
+ *
+ * @param names
+ *   List of metric names
+ *
+ * @param cnt_names
+ *   Number of metrics in set
+ *
+ * @return
+ *  - Zero or positive: Success
+ *  - Negative: Failure
+ */
+int rte_metrics_reg_metrics(const char * const *names, uint16_t cnt_names);
+
+/**
+ * Get metric name-key lookup table.
+ *
+ * @param names
+ *   A struct rte_metric_name array of at least *capacity* in size to
+ *   receive key names. If this is NULL, function returns the required
+ *   number of elements for this array.
+ *
+ * @param capacity
+ *   Size (number of elements) of struct rte_metric_name array.
+ *   Disregarded if names is NULL.
+ *
+ * @return
+ *   - Positive value above capacity: error, *names* is too small.
+ *     Return value is required size.
+ *   - Positive value equal or less than capacity: Success. Return
+ *     value is number of elements filled in.
+ *   - Negative value: error.
+ */
+int rte_metrics_get_names(
+	struct rte_metric_name *names,
+	uint16_t capacity);
+
+/**
+ * Get metric value table.
+ *
+ * @param port_id
+ *   Port id to query
+ *
+ * @param values
+ *   A struct rte_metric_value array of at least *capacity* in size to
+ *   receive metric ids and values. If this is NULL, function returns
+ *   the required number of elements for this array.
+ *
+ * @param capacity
+ *   Size (number of elements) of struct rte_metric_value array.
+ *   Disregarded if names is NULL.
+ *
+ * @return
+ *   - Positive value above capacity: error, *values* is too small.
+ *     Return value is required size.
+ *   - Positive value equal or less than capacity: Success. Return
+ *     value is number of elements filled in.
+ *   - Negative value: error.
+ */
+int rte_metrics_get_values(
+	int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity);
+
+/**
+ * Updates a metric
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Id of metric to update
+ * @param value
+ *   New value
+ *
+ * @return
+ *   - -EIO if unable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_metric(
+	int port_id,
+	uint16_t key,
+	const uint64_t value);
+
+/**
+ * Updates a metric set. Note that it is an error to try to
+ * update across a set boundary.
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Base id of metrics set to update
+ * @param values
+ *   Set of new values
+ * @param count
+ *   Number of new values
+ *
+ * @return
+ *   - -ERANGE if count exceeds metric set size
+ *   - -EIO if upable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_metrics(
+	int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count);
+
+#endif
diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map
new file mode 100644
index 0000000..f904814
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics_version.map
@@ -0,0 +1,13 @@
+DPDK_17.02 {
+	global:
+
+	rte_metrics_get_names;
+	rte_metrics_get_values;
+	rte_metrics_init;
+	rte_metrics_reg_metric;
+	rte_metrics_reg_metrics;
+	rte_metrics_update_metric;
+	rte_metrics_update_metrics;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index f75f0e2..40fcf33 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -98,6 +98,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING)           += -lrte_ring
 _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
+_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* [PATCH v7 2/6] app/proc_info: add metrics displaying
  2017-01-16 16:19           ` [PATCH v7 0/6] " Remy Horton
  2017-01-16 16:19             ` [PATCH v7 1/6] lib: add information metrics library Remy Horton
@ 2017-01-16 16:19             ` Remy Horton
  2017-01-17 11:08               ` Van Haaren, Harry
  2017-01-16 16:19             ` [PATCH v7 3/6] lib: add bitrate statistics library Remy Horton
                               ` (4 subsequent siblings)
  6 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-01-16 16:19 UTC (permalink / raw)
  To: dev; +Cc: Reshma Pattan, Thomas Monjalon

From: Reshma Pattan <reshma.pattan@intel.com>

Modify the dpdk-procinfo process to display the newly added metrics.
Added new command line option "--metrics" to display metrics.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/proc_info/main.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)

diff --git a/app/proc_info/main.c b/app/proc_info/main.c
index 2c56d10..e5d626e 100644
--- a/app/proc_info/main.c
+++ b/app/proc_info/main.c
@@ -57,6 +57,7 @@
 #include <rte_atomic.h>
 #include <rte_branch_prediction.h>
 #include <rte_string_fns.h>
+#include <rte_metrics.h>
 
 /* Maximum long option length for option parsing. */
 #define MAX_LONG_OPT_SZ 64
@@ -68,6 +69,8 @@ static uint32_t enabled_port_mask;
 static uint32_t enable_stats;
 /**< Enable xstats. */
 static uint32_t enable_xstats;
+/**< Enable metrics. */
+static uint32_t enable_metrics;
 /**< Enable stats reset. */
 static uint32_t reset_stats;
 /**< Enable xstats reset. */
@@ -85,6 +88,8 @@ proc_info_usage(const char *prgname)
 		"  --stats: to display port statistics, enabled by default\n"
 		"  --xstats: to display extended port statistics, disabled by "
 			"default\n"
+		"  --metrics: to display derived metrics of the ports, disabled by "
+			"default\n"
 		"  --stats-reset: to reset port statistics\n"
 		"  --xstats-reset: to reset port extended statistics\n",
 		prgname);
@@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv)
 		{"stats", 0, NULL, 0},
 		{"stats-reset", 0, NULL, 0},
 		{"xstats", 0, NULL, 0},
+		{"metrics", 0, NULL, 0},
 		{"xstats-reset", 0, NULL, 0},
 		{NULL, 0, 0, 0}
 	};
@@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv)
 			else if (!strncmp(long_option[option_index].name, "xstats",
 					MAX_LONG_OPT_SZ))
 				enable_xstats = 1;
+			else if (!strncmp(long_option[option_index].name,
+					"metrics",
+					MAX_LONG_OPT_SZ))
+				enable_metrics = 1;
 			/* Reset stats */
 			if (!strncmp(long_option[option_index].name, "stats-reset",
 					MAX_LONG_OPT_SZ))
@@ -301,6 +311,63 @@ nic_xstats_clear(uint8_t port_id)
 	printf("\n  NIC extended statistics for port %d cleared\n", port_id);
 }
 
+static void
+metrics_display(int port_id)
+{
+	struct rte_metric_value *metrics;
+	struct rte_metric_name *names;
+	int len, ret;
+	static const char *nic_stats_border = "########################";
+
+	memset(&metrics, 0, sizeof(struct rte_metric_value));
+	len = rte_metrics_get_names(NULL, 0);
+	if (len < 0) {
+		printf("Cannot get metrics count\n");
+		return;
+	}
+
+	metrics = malloc(sizeof(struct rte_metric_value) * len);
+	if (metrics == NULL) {
+		printf("Cannot allocate memory for metrics\n");
+		return;
+	}
+
+	names =  malloc(sizeof(struct rte_metric_name) * len);
+	if (names == NULL) {
+		printf("Cannot allocate memory for metrcis names\n");
+		free(metrics);
+		return;
+	}
+
+	if (len != rte_metrics_get_names(names, len)) {
+		printf("Cannot get metrics names\n");
+		free(metrics);
+		free(names);
+		return;
+	}
+
+	if (port_id == RTE_METRICS_GLOBAL)
+		printf("###### Non port specific metrics  #########\n");
+	else
+		printf("###### metrics for port %-2d #########\n", port_id);
+	printf("%s############################\n", nic_stats_border);
+	ret = rte_metrics_get_values(port_id, metrics, len);
+	if (ret < 0 || ret > len) {
+		printf("Cannot get metrics values\n");
+		free(metrics);
+		free(names);
+		return;
+	}
+
+	int i;
+	for (i = 0; i < len; i++)
+		printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value);
+
+	printf("%s############################\n", nic_stats_border);
+	free(metrics);
+	free(names);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -360,8 +427,14 @@ main(int argc, char **argv)
 				nic_stats_clear(i);
 			else if (reset_xstats)
 				nic_xstats_clear(i);
+			else if (enable_metrics)
+				metrics_display(i);
 		}
 	}
 
+	/* print port independent stats */
+	if (enable_metrics)
+		metrics_display(RTE_METRICS_GLOBAL);
+
 	return 0;
 }
-- 
2.5.5

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

* [PATCH v7 3/6] lib: add bitrate statistics library
  2017-01-16 16:19           ` [PATCH v7 0/6] " Remy Horton
  2017-01-16 16:19             ` [PATCH v7 1/6] lib: add information metrics library Remy Horton
  2017-01-16 16:19             ` [PATCH v7 2/6] app/proc_info: add metrics displaying Remy Horton
@ 2017-01-16 16:19             ` Remy Horton
  2017-01-17 11:16               ` Van Haaren, Harry
  2017-01-16 16:19             ` [PATCH v7 4/6] app/test-pmd: add bitrate statistics calculation Remy Horton
                               ` (3 subsequent siblings)
  6 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-01-16 16:19 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patch adds a library that calculates peak and average data-rate
statistics. For ethernet devices. These statistics are reported using
the metrics library.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                        |   4 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/rel_notes/release_17_02.rst             |   5 +
 lib/Makefile                                       |   1 +
 lib/librte_bitratestats/Makefile                   |  53 +++++++++
 lib/librte_bitratestats/rte_bitrate.c              | 132 +++++++++++++++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++++++++++
 .../rte_bitratestats_version.map                   |   9 ++
 mk/rte.app.mk                                      |   1 +
 11 files changed, 292 insertions(+)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 4a19497..6cd9896 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -601,6 +601,10 @@ M: Remy Horton <remy.horton@intel.com>
 F: lib/librte_metrics/
 F: doc/guides/sample_app_ug/keep_alive.rst
 
+Bit-rate statistica
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_bitratestats/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index 0eb3866..decebe5 100644
--- a/config/common_base
+++ b/config/common_base
@@ -598,3 +598,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
 # Compile the device metrics library
 #
 CONFIG_RTE_LIBRTE_METRICS=y
+
+#
+# Compile the bitrate statistics library
+#
+CONFIG_RTE_LIBRTE_BITRATE=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 94f0f69..5e194b0 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -151,4 +151,5 @@ There are many libraries, so their headers may be grouped by topics:
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
   [Device Metrics]     (@ref rte_metrics.h),
+  [Bitrate Statistics] (@ref rte_bitrate.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index 194b670..6e6ab5c 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -35,6 +35,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_eal/common/include \
                           lib/librte_eal/common/include/generic \
                           lib/librte_acl \
+                          lib/librte_bitratestats \
                           lib/librte_cfgfile \
                           lib/librte_cmdline \
                           lib/librte_compat \
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 4fca29b..44012c8 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -40,6 +40,11 @@ New Features
      intended to provide a reporting mechanism that is independent of the
      ethdev library.
 
+   * **Added bit-rate calculation library.**
+
+     A library that can be used to calculate device bit-rates. Calculated
+     bitrates are reported using the metrics library.
+
      This section is a comment. do not overwrite or remove it.
      Also, make sure to start the actual text at the margin.
      =========================================================
diff --git a/lib/Makefile b/lib/Makefile
index 5d85dcf..e211bc0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
+DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile
new file mode 100644
index 0000000..b725d4e
--- /dev/null
+++ b/lib/librte_bitratestats/Makefile
@@ -0,0 +1,53 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_bitratestats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_bitratestats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c
new file mode 100644
index 0000000..c8d9a20
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.c
@@ -0,0 +1,132 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
+
+/*
+ * Persistent bit-rate data.
+ * @internal
+ */
+struct rte_stats_bitrate_s {
+	uint64_t last_ibytes;
+	uint64_t last_obytes;
+	uint64_t peak_ibits;
+	uint64_t peak_obits;
+	uint64_t ewma_ibits;
+	uint64_t ewma_obits;
+};
+
+struct rte_stats_bitrates_s {
+	struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS];
+	uint16_t id_stats_set;
+};
+
+struct rte_stats_bitrates_s *
+rte_stats_bitrate_create(void)
+{
+	return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s),
+		RTE_CACHE_LINE_SIZE);
+}
+
+int
+rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data)
+{
+	const char * const names[] = {
+		"mean_bits_in", "mean_bits_out",
+		"peak_bits_in", "peak_bits_out",
+	};
+	int return_value;
+
+	return_value = rte_metrics_reg_metrics(&names[0], 4);
+	if (return_value >= 0)
+		bitrate_data->id_stats_set = return_value;
+	return return_value;
+}
+
+int
+rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
+	uint8_t port_id)
+{
+	struct rte_stats_bitrate_s *port_data;
+	struct rte_eth_stats eth_stats;
+	int ret_code;
+	uint64_t cnt_bits;
+	int64_t delta;
+	const int64_t alpha_percent = 20;
+	uint64_t values[4];
+
+	ret_code = rte_eth_stats_get(port_id, &eth_stats);
+	if (ret_code != 0)
+		return ret_code;
+
+	port_data = &bitrate_data->port_stats[port_id];
+
+	/* Incoming bitrate. This is an iteratively calculated EWMA
+	 * (Expomentially Weighted Moving Average) that uses a
+	 * weighting factor of alpha_percent.
+	 */
+	cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3;
+	port_data->last_ibytes = eth_stats.ibytes;
+	if (cnt_bits > port_data->peak_ibits)
+		port_data->peak_ibits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_ibits;
+	/* The +-50 fixes integer rounding during divison */
+	if (delta > 0)
+		delta = (delta * alpha_percent + 50) / 100;
+	else
+		delta = (delta * alpha_percent - 50) / 100;
+	port_data->ewma_ibits += delta;
+
+	/* Outgoing bitrate (also EWMA) */
+	cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3;
+	port_data->last_obytes = eth_stats.obytes;
+	if (cnt_bits > port_data->peak_obits)
+		port_data->peak_obits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_obits;
+	delta = (delta * alpha_percent + 50) / 100;
+	port_data->ewma_obits += delta;
+
+	values[0] = port_data->ewma_ibits;
+	values[1] = port_data->ewma_obits;
+	values[2] = port_data->peak_ibits;
+	values[3] = port_data->peak_obits;
+	rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set,
+		values, 4);
+	return 0;
+}
diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h
new file mode 100644
index 0000000..bc87c5e
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.h
@@ -0,0 +1,80 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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.
+ */
+
+
+/**
+ *  Bitrate statistics data structure.
+ *  This data structure is intentionally opaque.
+ */
+struct rte_stats_bitrates_s;
+
+
+/**
+ * Allocate a bitrate statistics structure
+ *
+ * @return
+ *   - Pointer to structure on success
+ *   - NULL on error (zmalloc failure)
+ */
+struct rte_stats_bitrates_s *rte_stats_bitrate_create(void);
+
+
+/**
+ * Register bitrate statistics with the metric library.
+ *
+ * @param bitrate_data
+ *   Pointer allocated by rte_stats_create()
+ *
+ * @return
+ *   Zero on success
+ *   Negative on error
+ */
+int rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data);
+
+
+/**
+ * Calculate statistics for current time window. The period with which
+ * this function is called should be the intended sampling window width.
+ *
+ * @param bitrate_data
+ *   Bitrate statistics data pointer
+ *
+ * @param port_id
+ *   Port id to calculate statistics for
+ *
+ * @return
+ *  - Zero on success
+ *  - Negative value on error
+ */
+int rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
+	uint8_t port_id);
diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map
new file mode 100644
index 0000000..66f232f
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitratestats_version.map
@@ -0,0 +1,9 @@
+DPDK_17.02 {
+	global:
+
+	rte_stats_bitrate_calc;
+	rte_stats_bitrate_create;
+	rte_stats_bitrate_reg;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 40fcf33..6aac5ac 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -99,6 +99,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
 
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
-- 
2.5.5

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

* [PATCH v7 4/6] app/test-pmd: add bitrate statistics calculation
  2017-01-16 16:19           ` [PATCH v7 0/6] " Remy Horton
                               ` (2 preceding siblings ...)
  2017-01-16 16:19             ` [PATCH v7 3/6] lib: add bitrate statistics library Remy Horton
@ 2017-01-16 16:19             ` Remy Horton
  2017-01-17 11:19               ` Van Haaren, Harry
  2017-01-16 16:19             ` [PATCH v7 5/6] lib: added new library for latency stats Remy Horton
                               ` (2 subsequent siblings)
  6 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-01-16 16:19 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

Calculate bitrate statistics using the bitrate stats library. The
resulting statistics can be viewed via proc_info.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/testpmd.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index bfb2f8e..a0b7430 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -79,6 +79,10 @@
 #include <rte_pdump.h>
 #endif
 #include <rte_flow.h>
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_BITRATE
+#include <rte_bitrate.h>
+#endif
 
 #include "testpmd.h"
 
@@ -323,6 +327,9 @@ uint16_t nb_rx_queue_stats_mappings = 0;
 
 unsigned max_socket = 0;
 
+/* Bitrate statistics */
+struct rte_stats_bitrates_s *bitrate_data;
+
 /* Forward function declarations */
 static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -922,12 +929,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
 	struct fwd_stream **fsm;
 	streamid_t nb_fs;
 	streamid_t sm_id;
+#ifdef RTE_LIBRTE_BITRATE
+	uint64_t tics_per_1sec;
+	uint64_t tics_datum;
+	uint64_t tics_current;
+	uint8_t idx_port, cnt_ports;
+#endif
 
+#ifdef RTE_LIBRTE_BITRATE
+	cnt_ports = rte_eth_dev_count();
+	tics_datum = rte_rdtsc();
+	tics_per_1sec = rte_get_timer_hz();
+#endif
 	fsm = &fwd_streams[fc->stream_idx];
 	nb_fs = fc->stream_nb;
 	do {
 		for (sm_id = 0; sm_id < nb_fs; sm_id++)
 			(*pkt_fwd)(fsm[sm_id]);
+#ifdef RTE_LIBRTE_BITRATE
+		tics_current = rte_rdtsc();
+		if (tics_current - tics_datum >= tics_per_1sec) {
+			/* Periodic bitrate calculation */
+			for (idx_port = 0; idx_port < cnt_ports; idx_port++)
+				rte_stats_bitrate_calc(bitrate_data, idx_port);
+			tics_datum = tics_current;
+		}
+#endif
 	} while (! fc->stopped);
 }
 
@@ -2139,6 +2166,15 @@ main(int argc, char** argv)
 	FOREACH_PORT(port_id, ports)
 		rte_eth_promiscuous_enable(port_id);
 
+	/* Setup bitrate stats */
+#ifdef RTE_LIBRTE_BITRATE
+	bitrate_data = rte_stats_bitrate_create();
+	if (bitrate_data == NULL)
+		rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n");
+	rte_stats_bitrate_reg(bitrate_data);
+#endif
+
+
 #ifdef RTE_LIBRTE_CMDLINE
 	if (interactive == 1) {
 		if (auto_start) {
-- 
2.5.5

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

* [PATCH v7 5/6] lib: added new library for latency stats
  2017-01-16 16:19           ` [PATCH v7 0/6] " Remy Horton
                               ` (3 preceding siblings ...)
  2017-01-16 16:19             ` [PATCH v7 4/6] app/test-pmd: add bitrate statistics calculation Remy Horton
@ 2017-01-16 16:19             ` Remy Horton
  2017-01-17  4:29               ` Jerin Jacob
  2017-01-17 11:41               ` Van Haaren, Harry
  2017-01-16 16:19             ` [PATCH v7 6/6] app/test-pmd: add latency statistics calculation Remy Horton
  2017-01-17 23:24             ` [PATCH v8 0/7] Expanded statistics reporting Remy Horton
  6 siblings, 2 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-16 16:19 UTC (permalink / raw)
  To: dev; +Cc: Reshma Pattan, Thomas Monjalon

From: Reshma Pattan <reshma.pattan@intel.com>

Add a library designed to calculate latency statistics and report them
to the application when queried. The library measures minimum, average and
maximum latencies, and jitter in nano seconds. The current implementation
supports global latency stats, i.e. per application stats.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                        |   4 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/rel_notes/release_17_02.rst             |   5 +
 lib/Makefile                                       |   1 +
 lib/librte_latencystats/Makefile                   |  57 +++
 lib/librte_latencystats/rte_latencystats.c         | 389 +++++++++++++++++++++
 lib/librte_latencystats/rte_latencystats.h         | 146 ++++++++
 .../rte_latencystats_version.map                   |  10 +
 lib/librte_mbuf/rte_mbuf.h                         |   3 +
 mk/rte.app.mk                                      |   2 +-
 12 files changed, 623 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_latencystats/Makefile
 create mode 100644 lib/librte_latencystats/rte_latencystats.c
 create mode 100644 lib/librte_latencystats/rte_latencystats.h
 create mode 100644 lib/librte_latencystats/rte_latencystats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 6cd9896..0a41fe5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -714,3 +714,7 @@ F: examples/tep_termination/
 F: examples/vmdq/
 F: examples/vmdq_dcb/
 F: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst
+
+Latency Stats
+M: Reshma Pattan <reshma.pattan@intel.com>
+F: lib/librte_latencystats/
diff --git a/config/common_base b/config/common_base
index decebe5..762a54c 100644
--- a/config/common_base
+++ b/config/common_base
@@ -603,3 +603,8 @@ CONFIG_RTE_LIBRTE_METRICS=y
 # Compile the bitrate statistics library
 #
 CONFIG_RTE_LIBRTE_BITRATE=y
+
+#
+# Compile the latency statistics library
+#
+CONFIG_RTE_LIBRTE_LATENCY_STATS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 5e194b0..1cacacc 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -152,4 +152,5 @@ There are many libraries, so their headers may be grouped by topics:
   [keepalive]          (@ref rte_keepalive.h),
   [Device Metrics]     (@ref rte_metrics.h),
   [Bitrate Statistics] (@ref rte_bitrate.h),
+  [Latency stats]      (@ref rte_latencystats.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index 6e6ab5c..0effece 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -47,6 +47,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_jobstats \
                           lib/librte_kni \
                           lib/librte_kvargs \
+                          lib/librte_latencystats \
                           lib/librte_lpm \
                           lib/librte_mbuf \
                           lib/librte_mempool \
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 44012c8..c09e60b 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -68,6 +68,10 @@ New Features
   Six new APIs have been added to the ixgbe PMD for MACsec offload support.
   The declarations for the APIs can be found in ``rte_pmd_ixgbe.h``.
 
+* **Added latency stats library.**
+  A library that facilitates latency stats measurment of the dpdk based
+  applications. The library measures minimum, average, maximum latencies
+  and also jitter in nano seconds.
 
 Resolved Issues
 ---------------
@@ -184,6 +188,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_jobstats.so.1
      librte_kni.so.2
      librte_kvargs.so.1
+   + librte_latencystats.so.1
      librte_lpm.so.2
      librte_mbuf.so.2
      librte_mempool.so.2
diff --git a/lib/Makefile b/lib/Makefile
index e211bc0..6fffa88 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -60,6 +60,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
+DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_latencystats/Makefile b/lib/librte_latencystats/Makefile
new file mode 100644
index 0000000..f744da6
--- /dev/null
+++ b/lib/librte_latencystats/Makefile
@@ -0,0 +1,57 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_latencystats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
+LDLIBS += -lm
+LDLIBS += -lpthread
+
+EXPORT_MAP := rte_latencystats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) := rte_latencystats.c
+
+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)-include := rte_latencystats.h
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_latencystats/rte_latencystats.c b/lib/librte_latencystats/rte_latencystats.c
new file mode 100644
index 0000000..1a68469
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats.c
@@ -0,0 +1,389 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 <unistd.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <math.h>
+#include <pthread.h>
+
+#include <rte_mbuf.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_metrics.h>
+#include <rte_memzone.h>
+#include <rte_lcore.h>
+#include <rte_timer.h>
+
+#include "rte_latencystats.h"
+
+/** Nano seconds per second */
+#define NS_PER_SEC 1E9
+
+/** Clock cycles per nano second */
+#define CYCLES_PER_NS (rte_get_timer_hz() / NS_PER_SEC)
+
+/* Macros for printing using RTE_LOG */
+#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1
+
+static pthread_t latency_stats_thread;
+static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats";
+static int latency_stats_index;
+static uint64_t samp_intvl;
+static uint64_t timer_tsc;
+static uint64_t prev_tsc;
+
+static struct rte_latency_stats {
+	float min_latency; /**< Minimum latency in nano seconds */
+	float avg_latency; /**< Average latency in nano seconds */
+	float max_latency; /**< Maximum latency in nano seconds */
+	float jitter; /** Latency variation */
+} *glob_stats;
+
+static struct rxtx_cbs {
+	struct rte_eth_rxtx_callback *cb;
+} rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT],
+	tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
+
+struct latency_stats_nameoff {
+	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	unsigned int offset;
+};
+
+static const struct latency_stats_nameoff lat_stats_strings[] = {
+	{"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)},
+	{"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)},
+	{"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)},
+	{"jitter_ns", offsetof(struct rte_latency_stats, jitter)},
+};
+
+#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \
+				sizeof(lat_stats_strings[0]))
+
+static __attribute__((noreturn)) void *
+report_latency_stats(__rte_unused void *arg)
+{
+	for (;;) {
+		unsigned int i;
+		float *stats_ptr = NULL;
+		uint64_t values[NUM_LATENCY_STATS] = {0};
+		int ret;
+
+		for (i = 0; i < NUM_LATENCY_STATS; i++) {
+			stats_ptr = RTE_PTR_ADD(glob_stats,
+					lat_stats_strings[i].offset);
+			values[i] = (uint64_t)floor((*stats_ptr)/
+					CYCLES_PER_NS);
+		}
+
+		ret = rte_metrics_update_metrics(RTE_METRICS_GLOBAL,
+						latency_stats_index,
+						values, NUM_LATENCY_STATS);
+		if (ret < 0)
+			RTE_LOG(INFO, LATENCY_STATS,
+				"Failed to push the stats\n");
+	}
+}
+
+static void
+rte_latencystats_fill_values(struct rte_metric_value *values)
+{
+	unsigned int i;
+	float *stats_ptr = NULL;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++) {
+		stats_ptr = RTE_PTR_ADD(glob_stats,
+				lat_stats_strings[i].offset);
+		values[i].key = i;
+		values[i].value = (uint64_t)floor((*stats_ptr)/
+						CYCLES_PER_NS);
+	}
+}
+
+static uint16_t
+add_time_stamps(uint8_t pid __rte_unused,
+		uint16_t qid __rte_unused,
+		struct rte_mbuf **pkts,
+		uint16_t nb_pkts,
+		uint16_t max_pkts __rte_unused,
+		void *user_cb __rte_unused)
+{
+	unsigned int i;
+	uint64_t diff_tsc, now;
+
+	/*
+	 * For every sample interval,
+	 * time stamp is marked on one received packet.
+	 */
+	now = rte_rdtsc();
+	for (i = 0; i < nb_pkts; i++) {
+		diff_tsc = now - prev_tsc;
+		timer_tsc += diff_tsc;
+		if (timer_tsc >= samp_intvl) {
+			/*
+			 * TBD: Mark the timestamp only
+			 * if not already marked by the
+			 * hardware or the PMD.
+			 */
+			pkts[i]->timestamp = now;
+			timer_tsc = 0;
+		}
+		prev_tsc = now;
+		now = rte_rdtsc();
+	}
+
+	return nb_pkts;
+}
+
+static uint16_t
+calc_latency(uint8_t pid __rte_unused,
+		uint16_t qid __rte_unused,
+		struct rte_mbuf **pkts,
+		uint16_t nb_pkts,
+		void *_ __rte_unused)
+{
+	unsigned int i, cnt = 0;
+	uint64_t now;
+	float latency[nb_pkts];
+	static float prev_latency;
+	/*
+	 * Alpha represents degree of weighting decrease in EWMA,
+	 * a constant smoothing factor between 0 and 1. The value
+	 * is used below for measuring average latency.
+	 */
+	const float alpha = 0.2;
+
+	now = rte_rdtsc();
+	for (i = 0; i < nb_pkts; i++) {
+		if (pkts[i]->timestamp)
+			latency[cnt++] = now - pkts[i]->timestamp;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		/*
+		 * The jitter is calculated as statistical mean of interpacket
+		 * delay variation. The "jitter estimate" is computed by taking
+		 * the absolute values of the ipdv sequence and applying an
+		 * exponential filter with parameter 1/16 to generate the
+		 * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter,
+		 * D(i-1,i) is difference in latency of two consecutive packets
+		 * i-1 and i.
+		 * Reference: Calculated as per RFC 5481, sec 4.1,
+		 * RFC 3393 sec 4.5, RFC 1889 sec.
+		 */
+		glob_stats->jitter +=  (abs(prev_latency - latency[i])
+					- glob_stats->jitter)/16;
+		if (glob_stats->min_latency == 0)
+			glob_stats->min_latency = latency[i];
+		else if (latency[i] < glob_stats->min_latency)
+			glob_stats->min_latency = latency[i];
+		else if (latency[i] > glob_stats->max_latency)
+			glob_stats->max_latency = latency[i];
+		/*
+		 * The average latency is measured using exponential moving
+		 * average, i.e. using EWMA
+		 * https://en.wikipedia.org/wiki/Moving_average
+		 */
+		glob_stats->avg_latency +=
+			alpha * (latency[i] - glob_stats->avg_latency);
+		prev_latency = latency[i];
+	}
+
+	return nb_pkts;
+}
+
+int
+rte_latencystats_init(uint64_t samp_intvl,
+		rte_latency_stats_flow_type_fn user_cb)
+{
+	unsigned int i;
+	uint8_t pid;
+	uint16_t qid;
+	struct rxtx_cbs *cbs = NULL;
+	const uint8_t nb_ports = rte_eth_dev_count();
+	const char *ptr_strings[NUM_LATENCY_STATS] = {0};
+	const struct rte_memzone *mz = NULL;
+	const unsigned int flags = 0;
+
+	/** Allocate stats in shared memory fo muliti process support */
+	mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats),
+					rte_socket_id(), flags);
+	if (mz == NULL) {
+		RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n",
+			__func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	glob_stats = mz->addr;
+	samp_intvl *= CYCLES_PER_NS;
+
+	/** Register latency stats with stats library */
+	for (i = 0; i < NUM_LATENCY_STATS; i++)
+		ptr_strings[i] = lat_stats_strings[i].name;
+
+	latency_stats_index = rte_metrics_reg_metrics(ptr_strings,
+							NUM_LATENCY_STATS);
+	if (latency_stats_index < 0) {
+		RTE_LOG(DEBUG, LATENCY_STATS,
+			"Failed to register latency stats names\n");
+		return -1;
+	}
+
+	/** Register Rx/Tx callbacks */
+	for (pid = 0; pid < nb_ports; pid++) {
+		struct rte_eth_dev_info dev_info;
+		rte_eth_dev_info_get(pid, &dev_info);
+		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
+			cbs = &rx_cbs[pid][qid];
+			cbs->cb = rte_eth_add_first_rx_callback(pid, qid,
+					add_time_stamps, user_cb);
+			if (!cbs->cb)
+				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
+					"register Rx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
+			cbs = &tx_cbs[pid][qid];
+			cbs->cb =  rte_eth_add_tx_callback(pid, qid,
+					calc_latency, user_cb);
+			if (!cbs->cb)
+				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
+					"register Tx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+	}
+
+	int ret = 0;
+	char thread_name[RTE_MAX_THREAD_NAME_LEN];
+
+	/** Create the host thread to update latency stats to stats library */
+	ret = pthread_create(&latency_stats_thread, NULL, report_latency_stats,
+				NULL);
+	if (ret != 0) {
+		RTE_LOG(ERR, LATENCY_STATS,
+			"Failed to create the latency stats thread:%s, %s:%d\n",
+			strerror(errno), __func__, __LINE__);
+		return -1;
+	}
+	/** Set thread_name for aid in debugging */
+	snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "latency-stats-thread");
+	ret = rte_thread_setname(latency_stats_thread, thread_name);
+	if (ret != 0)
+		RTE_LOG(DEBUG, LATENCY_STATS,
+			"Failed to set thread name for latency stats handling\n");
+
+	return 0;
+}
+
+int
+rte_latencystats_uninit(void)
+{
+	uint8_t pid;
+	uint16_t qid;
+	int ret = 0;
+	struct rxtx_cbs *cbs = NULL;
+	const uint8_t nb_ports = rte_eth_dev_count();
+
+	/** De register Rx/Tx callbacks */
+	for (pid = 0; pid < nb_ports; pid++) {
+		struct rte_eth_dev_info dev_info;
+		rte_eth_dev_info_get(pid, &dev_info);
+		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
+			cbs = &rx_cbs[pid][qid];
+			ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb);
+			if (ret)
+				RTE_LOG(INFO, LATENCY_STATS, "failed to "
+					"remove Rx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
+			cbs = &tx_cbs[pid][qid];
+			ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb);
+			if (ret)
+				RTE_LOG(INFO, LATENCY_STATS, "failed to "
+					"remove Tx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+	}
+
+	/** Cancel the thread */
+	ret = pthread_cancel(latency_stats_thread);
+	if (ret != 0) {
+		RTE_LOG(ERR, LATENCY_STATS,
+			"Failed to cancel latency stats update thread:"
+			"%s,%s:%d\n",
+			strerror(errno), __func__, __LINE__);
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size)
+{
+	unsigned int i;
+
+	if (names == NULL || size < NUM_LATENCY_STATS)
+		return NUM_LATENCY_STATS;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++)
+		snprintf(names[i].name, sizeof(names[i].name),
+				"%s", lat_stats_strings[i].name);
+
+	return NUM_LATENCY_STATS;
+}
+
+int
+rte_latencystats_get(struct rte_metric_value *values, uint16_t size)
+{
+	if (size < NUM_LATENCY_STATS || values == NULL)
+		return NUM_LATENCY_STATS;
+
+	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		const struct rte_memzone *mz;
+		mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS);
+		if (mz == NULL) {
+			RTE_LOG(ERR, LATENCY_STATS,
+				"Latency stats memzone not found\n");
+			return -ENOMEM;
+		}
+		glob_stats =  mz->addr;
+	}
+
+	/* Retrieve latency stats */
+	rte_latencystats_fill_values(values);
+
+	return NUM_LATENCY_STATS;
+}
diff --git a/lib/librte_latencystats/rte_latencystats.h b/lib/librte_latencystats/rte_latencystats.h
new file mode 100644
index 0000000..405b878
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats.h
@@ -0,0 +1,146 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 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 _RTE_LATENCYSTATS_H_
+#define _RTE_LATENCYSTATS_H_
+
+/**
+ * @file
+ * RTE latency stats
+ *
+ * library to provide application and flow based latency stats.
+ */
+
+#include <rte_metrics.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  Note: This function pointer is for future flow based latency stats
+ *  implementation.
+ *
+ * Function type used for identifting flow types of a Rx packet.
+ *
+ * The callback function is called on Rx for each packet.
+ * This function is used for flow based latency calculations.
+ *
+ * @param pkt
+ *   Packet that has to be identified with its flow types.
+ * @param user_param
+ *   The arbitrary user parameter passed in by the application when
+ *   the callback was originally configured.
+ * @return
+ *   The flow_mask, representing the multiple flow types of a packet.
+ */
+typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt,
+							void *user_param);
+
+/**
+ *  Registers Rx/Tx callbacks for each active port, queue.
+ *
+ * @param samp_intvl
+ *  Sampling time period in nano seconds, at which packet
+ *  should be marked with time stamp.
+ * @param user_cb
+ *  Note: This param is for future flow based latency stats
+ *  implementation.
+ *  User callback to be called to get flow types of a packet.
+ *  Used for flow based latency calculation.
+ *  If the value is NULL, global stats will be calculated,
+ *  else flow based latency stats will be calculated.
+ *  For now just pass on the NULL value to this param.
+ *  @return
+ *   -1     : On error
+ *   -ENOMEM: On error
+ *    0     : On success
+ */
+int rte_latencystats_init(uint64_t samp_intvl,
+			rte_latency_stats_flow_type_fn user_cb);
+
+/**
+ *  Removes registered Rx/Tx callbacks for each active port, queue.
+ *
+ *  @return
+ *   -1: On error
+ *    0: On success
+ */
+int rte_latencystats_uninit(void);
+
+/**
+ * Retrieve names of latency statistics
+ *
+ * @param names
+ *  Block of memory to insert names into. Must be at least size in capacity.
+ *  If set to NULL, function returns required capacity.
+ * @param size
+ *  Capacity of latency stats names (number of names).
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ */
+int rte_latencystats_get_names(struct rte_metric_name *names,
+				uint16_t size);
+
+/**
+ * Retrieve latency statistics.
+ *
+ * @param values
+ *   A pointer to a table of structure of type *rte_metric_value*
+ *   to be filled with latency statistics ids and values.
+ *   This parameter can be set to NULL if size is 0.
+ * @param size
+ *   The size of the stats table, which should be large enough to store
+ *   all the latency stats.
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ *   -ENOMEM: On failure.
+ */
+int rte_latencystats_get(struct rte_metric_value *values,
+			uint16_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_LATENCYSTATS_H_ */
diff --git a/lib/librte_latencystats/rte_latencystats_version.map b/lib/librte_latencystats/rte_latencystats_version.map
new file mode 100644
index 0000000..502018e
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats_version.map
@@ -0,0 +1,10 @@
+DPDK_17.02 {
+	global:
+
+	rte_latencystats_get;
+	rte_latencystats_get_names;
+	rte_latencystats_init;
+	rte_latencystats_uninit;
+
+	local: *;
+};
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index bfce9f4..c35ba0a 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -512,6 +512,9 @@ struct rte_mbuf {
 
 	/** Timesync flags for use with IEEE1588. */
 	uint16_t timesync;
+
+	/** Timestamp for measuring latency. */
+	uint64_t timestamp;
 } __rte_cache_aligned;
 
 /**
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 6aac5ac..1d36fad 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -100,7 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
 _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
-
+_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)  += -lrte_latencystats
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* [PATCH v7 6/6] app/test-pmd: add latency statistics calculation
  2017-01-16 16:19           ` [PATCH v7 0/6] " Remy Horton
                               ` (4 preceding siblings ...)
  2017-01-16 16:19             ` [PATCH v7 5/6] lib: added new library for latency stats Remy Horton
@ 2017-01-16 16:19             ` Remy Horton
  2017-01-17 11:45               ` Van Haaren, Harry
  2017-01-17 23:24             ` [PATCH v8 0/7] Expanded statistics reporting Remy Horton
  6 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-01-16 16:19 UTC (permalink / raw)
  To: dev; +Cc: Reshma Pattan, Thomas Monjalon

From: Reshma Pattan <reshma.pattan@intel.com>

Modify testpmd code to initialize/uninitialize latency statistics
calulation.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/testpmd.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index a0b7430..2874ce4 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -83,6 +83,10 @@
 #ifdef RTE_LIBRTE_BITRATE
 #include <rte_bitrate.h>
 #endif
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_LATENCY_STATS
+#include <rte_latencystats.h>
+#endif
 
 #include "testpmd.h"
 
@@ -2108,6 +2112,9 @@ signal_handler(int signum)
 		/* uninitialize packet capture framework */
 		rte_pdump_uninit();
 #endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+		rte_latencystats_uninit();
+#endif
 		force_quit();
 		/* exit with the expected status */
 		signal(signum, SIG_DFL);
@@ -2165,6 +2172,9 @@ main(int argc, char** argv)
 	/* set all ports to promiscuous mode by default */
 	FOREACH_PORT(port_id, ports)
 		rte_eth_promiscuous_enable(port_id);
+#ifdef RTE_LIBRTE_LATENCY_STATS
+	rte_latencystats_init(1, NULL);
+#endif
 
 	/* Setup bitrate stats */
 #ifdef RTE_LIBRTE_BITRATE
-- 
2.5.5

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

* Re: [PATCH v7 5/6] lib: added new library for latency stats
  2017-01-16 16:19             ` [PATCH v7 5/6] lib: added new library for latency stats Remy Horton
@ 2017-01-17  4:29               ` Jerin Jacob
  2017-01-17  6:48                 ` Remy Horton
  2017-01-17 11:19                 ` Mcnamara, John
  2017-01-17 11:41               ` Van Haaren, Harry
  1 sibling, 2 replies; 115+ messages in thread
From: Jerin Jacob @ 2017-01-17  4:29 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev, Reshma Pattan, Thomas Monjalon

On Mon, Jan 16, 2017 at 04:19:32PM +0000, Remy Horton wrote:
> From: Reshma Pattan <reshma.pattan@intel.com>
> 
> Add a library designed to calculate latency statistics and report them
> to the application when queried. The library measures minimum, average and
> maximum latencies, and jitter in nano seconds. The current implementation
> supports global latency stats, i.e. per application stats.
> 
> Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
> Signed-off-by: Remy Horton <remy.horton@intel.com>
> ---
>  MAINTAINERS                                        |   4 +
>  config/common_base                                 |   5 +
>  doc/api/doxy-api-index.md                          |   1 +
>  doc/api/doxy-api.conf                              |   1 +
>  doc/guides/rel_notes/release_17_02.rst             |   5 +
>  lib/Makefile                                       |   1 +
>  lib/librte_latencystats/Makefile                   |  57 +++
>  lib/librte_latencystats/rte_latencystats.c         | 389 +++++++++++++++++++++
>  lib/librte_latencystats/rte_latencystats.h         | 146 ++++++++
>  .../rte_latencystats_version.map                   |  10 +
>  lib/librte_mbuf/rte_mbuf.h                         |   3 +

It is a value added feature for DPDK. But what is the plan for incorporating
the mbuf change? I have 8 month old mbuf change for ARM for natural
alignment. If we are accepting any mbuf change then we need to include
outstanding mbuf changes to avoid future ABI breakage.

http://dpdk.org/dev/patchwork/patch/12878/

Jerin

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

* Re: [PATCH v7 5/6] lib: added new library for latency stats
  2017-01-17  4:29               ` Jerin Jacob
@ 2017-01-17  6:48                 ` Remy Horton
  2017-01-17  7:35                   ` Jerin Jacob
  2017-01-17 11:19                 ` Mcnamara, John
  1 sibling, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-01-17  6:48 UTC (permalink / raw)
  To: Jerin Jacob; +Cc: dev, Reshma Pattan, Thomas Monjalon


On 17/01/2017 04:29, Jerin Jacob wrote:
[..]
> It is a value added feature for DPDK. But what is the plan for incorporating
> the mbuf change? I have 8 month old mbuf change for ARM for natural
> alignment. If we are accepting any mbuf change then we need to include
> outstanding mbuf changes to avoid future ABI breakage.
>
> http://dpdk.org/dev/patchwork/patch/12878/

I know there's some discussion going on in the background regarding 
this. I've yet to hear a definite answer myself..

..Remy

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

* Re: [PATCH v7 5/6] lib: added new library for latency stats
  2017-01-17  6:48                 ` Remy Horton
@ 2017-01-17  7:35                   ` Jerin Jacob
  0 siblings, 0 replies; 115+ messages in thread
From: Jerin Jacob @ 2017-01-17  7:35 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev, Reshma Pattan, Thomas Monjalon

On Tue, Jan 17, 2017 at 06:48:30AM +0000, Remy Horton wrote:
> 
> On 17/01/2017 04:29, Jerin Jacob wrote:
> [..]
> > It is a value added feature for DPDK. But what is the plan for incorporating
> > the mbuf change? I have 8 month old mbuf change for ARM for natural
> > alignment. If we are accepting any mbuf change then we need to include
> > outstanding mbuf changes to avoid future ABI breakage.
> > 
> > http://dpdk.org/dev/patchwork/patch/12878/
> 
> I know there's some discussion going on in the background regarding this.
> I've yet to hear a definite answer myself..

This was the last thread on this topic
http://dpdk.org/ml/archives/dev/2016-July/043222.html

Where Oliver want to group a few of the mbuf changes together.
Thats is good. But, looking at the history(holding a ARM specific patch for 8
months), I don't believe, we will get consensus on _all_ the items on
mbuf change like ports, m->next etc.
I think we had consensus on my change(making mbuf natural
aligned), but it was queued for grouping with other mbuf changes.

Jerin

> 
> ..Remy

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

* Re: [PATCH v7 1/6] lib: add information metrics library
  2017-01-16 16:19             ` [PATCH v7 1/6] lib: add information metrics library Remy Horton
@ 2017-01-17 11:01               ` Van Haaren, Harry
  2017-01-17 13:40                 ` Remy Horton
  0 siblings, 1 reply; 115+ messages in thread
From: Van Haaren, Harry @ 2017-01-17 11:01 UTC (permalink / raw)
  To: Horton, Remy, dev; +Cc: Thomas Monjalon

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton

> This patch adds a new information metric library that allows other
> modules to register named metrics and update their values. It is
> intended to be independent of ethdev, rather than mixing ethdev
> and non-ethdev information in xstats.
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>


Comments inline below.


> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9645c9b..4a19497 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -596,6 +596,11 @@ F: lib/librte_jobstats/
>  F: examples/l2fwd-jobstats/
>  F: doc/guides/sample_app_ug/l2_forward_job_stats.rst
> 
> +Metrics
> +M: Remy Horton <remy.horton@intel.com>
> +F: lib/librte_metrics/
> +F: doc/guides/sample_app_ug/keep_alive.rst

Copy paste error, Keep alive sample app guide should not be here. There is no sample app / guide for usage of the metrics library in this patchset as it is.

> +++ b/lib/librte_metrics/rte_metrics.c
> @@ -0,0 +1,310 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2016 Intel Corporation. All rights reserved.
> + *   All rights reserved.

Update to 2016-2017

> +/**
> + * Internal stats metadata and value entry.
> + *
> + * @internal
> + * @param name
> + *   Name of metric
> + * @param value
> + *   Current value for metric
> + * @param idx_next_set
> + *   Index of next root element (zero for none)
> + * @param idx_next_metric
> + *   Index of next metric in set (zero for none)
> + *
> + * Only the root of each set needs idx_next_set but since it has to be
> + * assumed that number of sets could equal total number of metrics,
> + * having a separate set metadata table doesn't save any memory.
> + */
> +struct rte_metrics_meta_s {
> +	char name[RTE_METRICS_MAX_NAME_LEN];
> +	uint64_t value[RTE_MAX_ETHPORTS];
> +	uint64_t nonport_value;
> +	uint16_t idx_next_set;
> +	uint16_t idx_next_stat;
> +};

Nit: why the _s in rte_metrics_meta_s? Is there a reason why struct rte_metrics_meta {  is not suitable? Same question for rte_metrics_data_s.

> +void
> +rte_metrics_init(void)
> +{
> +	struct rte_metrics_data_s *stats;
> +	const struct rte_memzone *memzone;
> +
> +	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
> +		return;
> +
> +	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
> +	if (memzone != NULL)
> +		return;
> +	memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME,
> +		sizeof(struct rte_metrics_data_s), rte_socket_id(), 0);

In my opinion, passing socket_id to rte_metrics_init() would be a better API, than relying on the metrics initialization core to be on the correct socket.

> +	if (memzone == NULL)
> +		rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
> +	stats = memzone->addr;
> +	memset(stats, 0, sizeof(struct rte_metrics_data_s));
> +	rte_spinlock_init(&stats->lock);

Should this spinlock be initialized before the creation of the memzone? Creating the memzone first, and later initializing the locking-structure for it feels racey to me. The lock should probably be taken and unlocked again after init and memset.

> +}
> +
> +int
> +rte_metrics_reg_metric(const char *name)
> +{

Nit: would rte_metrics_reg_name() be a better function name?

> +	const char * const list_names[] = {name};
> +
> +	return rte_metrics_reg_metrics(list_names, 1);
> +}
> +
> +int
> +rte_metrics_reg_metrics(const char * const *names, uint16_t cnt_names)
> +{

Nit: would rte_metrics_reg_names() be a better function name?

> +
> +int
> +rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value)
> +{

Would rte_metrics_update_single() be a better function name? I presume updating a single metric at a time is exception case, and the (see below) more generic rte_metrics_update() would be more commonly used.

> +	return rte_metrics_update_metrics(port_id, key, &value, 1);
> +}
> +
> +int
> +rte_metrics_update_metrics(int port_id,
> +	uint16_t key,
> +	const uint64_t *values,
> +	uint32_t count)

Would rte_metrics_update() be a better function name?

> +{
> +	struct rte_metrics_meta_s *entry;
> +	struct rte_metrics_data_s *stats;
> +	const struct rte_memzone *memzone;
> +	uint16_t idx_metric;
> +	uint16_t idx_value;
> +	uint16_t cnt_setsize;
> +
> +	if (port_id != RTE_METRICS_GLOBAL &&
> +			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
> +		return -EINVAL;
> +
> +	rte_metrics_init();

See above comments on rte_metrics_init() taking a socket_id parameter. Here any core could call update_metrics(), and if the library was not yet initialized, the memory for metrics would end up on the socket of this core. This should be avoided by
A) adding socket_id parameter to the metrics_init() function
B) Demanding that metrics_init() is called by the application before any core uses update_metrics() 

> +	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
> +	if (memzone == NULL)
> +		return -EIO;
> +	stats = memzone->addr;
> +
> +	rte_spinlock_lock(&stats->lock);
> +	idx_metric = key;
> +	cnt_setsize = 1;
> +	while (idx_metric < stats->cnt_stats) {
> +		entry = &stats->metadata[idx_metric];
> +		if (entry->idx_next_stat == 0)
> +			break;
> +		cnt_setsize++;
> +		idx_metric++;
> +	}
> +	/* Check update does not cross set border */
> +	if (count > cnt_setsize) {
> +		rte_spinlock_unlock(&stats->lock);
> +		return -ERANGE;
> +	}

What is a "set border"? I think this ensures that one set of metrics cannot overwrite the index's of another metrics set - correct?

> +
> +	if (port_id == RTE_METRICS_GLOBAL)
> +		for (idx_value = 0; idx_value < count; idx_value++) {
> +			idx_metric = key + idx_value;
> +			stats->metadata[idx_metric].nonport_value =
> +				values[idx_value];
> +		}
> +	else
> +		for (idx_value = 0; idx_value < count; idx_value++) {
> +			idx_metric = key + idx_value;
> +			stats->metadata[idx_metric].value[port_id] =
> +				values[idx_value];
> +		}
> +	rte_spinlock_unlock(&stats->lock);
> +	return 0;
> +}

<snip>

> diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
> new file mode 100644
> index 0000000..fd82af9
> --- /dev/null
> +++ b/lib/librte_metrics/rte_metrics.h
> @@ -0,0 +1,223 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2016 Intel Corporation. All rights reserved.
> + *   All rights reserved.

Add -2017

> +
> +
> +/**
> + * Initializes metric module. This only has to be explicitly called if you
> + * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a
> + * secondary process. This function must be called from a primary process.
> + */
> +void rte_metrics_init(void);

As noted in the C function above:
- accept a socket-id
- demand an application calls it if it will use the metrics library. 

<snip>

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

* Re: [PATCH v7 2/6] app/proc_info: add metrics displaying
  2017-01-16 16:19             ` [PATCH v7 2/6] app/proc_info: add metrics displaying Remy Horton
@ 2017-01-17 11:08               ` Van Haaren, Harry
  2017-01-17 14:27                 ` Remy Horton
  0 siblings, 1 reply; 115+ messages in thread
From: Van Haaren, Harry @ 2017-01-17 11:08 UTC (permalink / raw)
  To: Horton, Remy, dev; +Cc: Pattan, Reshma, Thomas Monjalon

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Monday, January 16, 2017 4:19 PM
> To: dev@dpdk.org
> Cc: Pattan, Reshma <reshma.pattan@intel.com>; Thomas Monjalon <thomas.monjalon@6wind.com>
> Subject: [dpdk-dev] [PATCH v7 2/6] app/proc_info: add metrics displaying
> 
> From: Reshma Pattan <reshma.pattan@intel.com>
> 
> Modify the dpdk-procinfo process to display the newly added metrics.
> Added new command line option "--metrics" to display metrics.
> 
> Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
> Signed-off-by: Remy Horton <remy.horton@intel.com>

Note that current git HEAD has a bug in secondary process - this has already
been raised and fixed in patches on the ML. In testing, I manually fixed the
secondary proc issue, after which testing here worked successfully.

Comments inline.

> ---
>  app/proc_info/main.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 73 insertions(+)
> 
> diff --git a/app/proc_info/main.c b/app/proc_info/main.c
> index 2c56d10..e5d626e 100644
> --- a/app/proc_info/main.c
> +++ b/app/proc_info/main.c
> @@ -57,6 +57,7 @@
>  #include <rte_atomic.h>
>  #include <rte_branch_prediction.h>
>  #include <rte_string_fns.h>
> +#include <rte_metrics.h>
> 
>  /* Maximum long option length for option parsing. */
>  #define MAX_LONG_OPT_SZ 64
> @@ -68,6 +69,8 @@ static uint32_t enabled_port_mask;
>  static uint32_t enable_stats;
>  /**< Enable xstats. */
>  static uint32_t enable_xstats;
> +/**< Enable metrics. */
> +static uint32_t enable_metrics;
>  /**< Enable stats reset. */
>  static uint32_t reset_stats;
>  /**< Enable xstats reset. */
> @@ -85,6 +88,8 @@ proc_info_usage(const char *prgname)
>  		"  --stats: to display port statistics, enabled by default\n"
>  		"  --xstats: to display extended port statistics, disabled by "
>  			"default\n"
> +		"  --metrics: to display derived metrics of the ports, disabled by "
> +			"default\n"
>  		"  --stats-reset: to reset port statistics\n"
>  		"  --xstats-reset: to reset port extended statistics\n",

I presume there is no need for a --metrics-reset as the values are reset when printed, correct?

>  		prgname);
> @@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv)
>  		{"stats", 0, NULL, 0},
>  		{"stats-reset", 0, NULL, 0},
>  		{"xstats", 0, NULL, 0},
> +		{"metrics", 0, NULL, 0},
>  		{"xstats-reset", 0, NULL, 0},
>  		{NULL, 0, 0, 0}
>  	};
> @@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv)
>  			else if (!strncmp(long_option[option_index].name, "xstats",
>  					MAX_LONG_OPT_SZ))
>  				enable_xstats = 1;
> +			else if (!strncmp(long_option[option_index].name,
> +					"metrics",
> +					MAX_LONG_OPT_SZ))
> +				enable_metrics = 1;
>  			/* Reset stats */
>  			if (!strncmp(long_option[option_index].name, "stats-reset",
>  					MAX_LONG_OPT_SZ))
> @@ -301,6 +311,63 @@ nic_xstats_clear(uint8_t port_id)
>  	printf("\n  NIC extended statistics for port %d cleared\n", port_id);
>  }
> 
> +static void
> +metrics_display(int port_id)
> +{
> +	struct rte_metric_value *metrics;
> +	struct rte_metric_name *names;
> +	int len, ret;
> +	static const char *nic_stats_border = "########################";
> +
> +	memset(&metrics, 0, sizeof(struct rte_metric_value));
> +	len = rte_metrics_get_names(NULL, 0);
> +	if (len < 0) {
> +		printf("Cannot get metrics count\n");
> +		return;
> +	}
> +
> +	metrics = malloc(sizeof(struct rte_metric_value) * len);
> +	if (metrics == NULL) {
> +		printf("Cannot allocate memory for metrics\n");
> +		return;
> +	}

Is malloc() favoured over rte_malloc() for a reason?

> +
> +	names =  malloc(sizeof(struct rte_metric_name) * len);
> +	if (names == NULL) {
> +		printf("Cannot allocate memory for metrcis names\n");
> +		free(metrics);
> +		return;
> +	}
> +
> +	if (len != rte_metrics_get_names(names, len)) {
> +		printf("Cannot get metrics names\n");
> +		free(metrics);
> +		free(names);
> +		return;
> +	}
> +
> +	if (port_id == RTE_METRICS_GLOBAL)
> +		printf("###### Non port specific metrics  #########\n");
> +	else
> +		printf("###### metrics for port %-2d #########\n", port_id);
> +	printf("%s############################\n", nic_stats_border);
> +	ret = rte_metrics_get_values(port_id, metrics, len);
> +	if (ret < 0 || ret > len) {
> +		printf("Cannot get metrics values\n");
> +		free(metrics);
> +		free(names);
> +		return;
> +	}
> +
> +	int i;
> +	for (i = 0; i < len; i++)
> +		printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value);
> +
> +	printf("%s############################\n", nic_stats_border);
> +	free(metrics);
> +	free(names);
> +}
> +
>  int
>  main(int argc, char **argv)
>  {
> @@ -360,8 +427,14 @@ main(int argc, char **argv)
>  				nic_stats_clear(i);
>  			else if (reset_xstats)
>  				nic_xstats_clear(i);
> +			else if (enable_metrics)
> +				metrics_display(i);
>  		}
>  	}
> 
> +	/* print port independent stats */
> +	if (enable_metrics)
> +		metrics_display(RTE_METRICS_GLOBAL);
> +
>  	return 0;
>  }
> --
> 2.5.5

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

* Re: [PATCH v7 3/6] lib: add bitrate statistics library
  2017-01-16 16:19             ` [PATCH v7 3/6] lib: add bitrate statistics library Remy Horton
@ 2017-01-17 11:16               ` Van Haaren, Harry
  2017-01-17 15:37                 ` Remy Horton
  0 siblings, 1 reply; 115+ messages in thread
From: Van Haaren, Harry @ 2017-01-17 11:16 UTC (permalink / raw)
  To: Horton, Remy, dev; +Cc: Thomas Monjalon

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Monday, January 16, 2017 4:20 PM
> To: dev@dpdk.org
> Cc: Thomas Monjalon <thomas.monjalon@6wind.com>
> Subject: [dpdk-dev] [PATCH v7 3/6] lib: add bitrate statistics library
> 
> This patch adds a library that calculates peak and average data-rate
> statistics. For ethernet devices. These statistics are reported using
> the metrics library.
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>

Comments inline

> ---
>  MAINTAINERS                                        |   4 +
>  config/common_base                                 |   5 +
>  doc/api/doxy-api-index.md                          |   1 +
>  doc/api/doxy-api.conf                              |   1 +
>  doc/guides/rel_notes/release_17_02.rst             |   5 +
>  lib/Makefile                                       |   1 +
>  lib/librte_bitratestats/Makefile                   |  53 +++++++++
>  lib/librte_bitratestats/rte_bitrate.c              | 132 +++++++++++++++++++++
>  lib/librte_bitratestats/rte_bitrate.h              |  80 +++++++++++++
>  .../rte_bitratestats_version.map                   |   9 ++
>  mk/rte.app.mk                                      |   1 +
>  11 files changed, 292 insertions(+)
>  create mode 100644 lib/librte_bitratestats/Makefile
>  create mode 100644 lib/librte_bitratestats/rte_bitrate.c
>  create mode 100644 lib/librte_bitratestats/rte_bitrate.h
>  create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 4a19497..6cd9896 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -601,6 +601,10 @@ M: Remy Horton <remy.horton@intel.com>
>  F: lib/librte_metrics/
>  F: doc/guides/sample_app_ug/keep_alive.rst
> 
> +Bit-rate statistica
> +M: Remy Horton <remy.horton@intel.com>
> +F: lib/librte_bitratestats/
> +
> 
>  Test Applications
>  -----------------
> diff --git a/config/common_base b/config/common_base
> index 0eb3866..decebe5 100644
> --- a/config/common_base
> +++ b/config/common_base
> @@ -598,3 +598,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
>  # Compile the device metrics library
>  #
>  CONFIG_RTE_LIBRTE_METRICS=y
> +
> +#
> +# Compile the bitrate statistics library
> +#
> +CONFIG_RTE_LIBRTE_BITRATE=y
> diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
> index 94f0f69..5e194b0 100644
> --- a/doc/api/doxy-api-index.md
> +++ b/doc/api/doxy-api-index.md
> @@ -151,4 +151,5 @@ There are many libraries, so their headers may be grouped by topics:
>    [ABI compat]         (@ref rte_compat.h),
>    [keepalive]          (@ref rte_keepalive.h),
>    [Device Metrics]     (@ref rte_metrics.h),
> +  [Bitrate Statistics] (@ref rte_bitrate.h),
>    [version]            (@ref rte_version.h)
> diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
> index 194b670..6e6ab5c 100644
> --- a/doc/api/doxy-api.conf
> +++ b/doc/api/doxy-api.conf
> @@ -35,6 +35,7 @@ INPUT                   = doc/api/doxy-api-index.md \
>                            lib/librte_eal/common/include \
>                            lib/librte_eal/common/include/generic \
>                            lib/librte_acl \
> +                          lib/librte_bitratestats \
>                            lib/librte_cfgfile \
>                            lib/librte_cmdline \
>                            lib/librte_compat \
> diff --git a/doc/guides/rel_notes/release_17_02.rst
> b/doc/guides/rel_notes/release_17_02.rst
> index 4fca29b..44012c8 100644
> --- a/doc/guides/rel_notes/release_17_02.rst
> +++ b/doc/guides/rel_notes/release_17_02.rst
> @@ -40,6 +40,11 @@ New Features
>       intended to provide a reporting mechanism that is independent of the
>       ethdev library.
> 
> +   * **Added bit-rate calculation library.**
> +
> +     A library that can be used to calculate device bit-rates. Calculated
> +     bitrates are reported using the metrics library.
> +
>       This section is a comment. do not overwrite or remove it.
>       Also, make sure to start the actual text at the margin.
>       =========================================================
> diff --git a/lib/Makefile b/lib/Makefile
> index 5d85dcf..e211bc0 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
>  DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
>  DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
>  DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
> +DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
> 
>  ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
>  DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
> diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile
> new file mode 100644
> index 0000000..b725d4e
> --- /dev/null
> +++ b/lib/librte_bitratestats/Makefile
> @@ -0,0 +1,53 @@
> +#   BSD LICENSE
> +#
> +#   Copyright(c) 2016 Intel Corporation. All rights reserved.
> +#   All rights reserved.

Add -2017


> +#
> +#   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 $(RTE_SDK)/mk/rte.vars.mk
> +
> +# library name
> +LIB = librte_bitratestats.a
> +
> +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
> +
> +EXPORT_MAP := rte_bitratestats_version.map
> +
> +LIBABIVER := 1
> +
> +# all source are stored in SRCS-y
> +SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c
> +
> +# Install header file
> +SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h
> +
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics
> +
> +include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c
> new file mode 100644
> index 0000000..c8d9a20
> --- /dev/null
> +++ b/lib/librte_bitratestats/rte_bitrate.c
> @@ -0,0 +1,132 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2016 Intel Corporation. All rights reserved.
> + *   All rights reserved.

-2017

> + *
> + *   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 <rte_common.h>
> +#include <rte_ethdev.h>
> +#include <rte_malloc.h>
> +#include <rte_metrics.h>
> +#include <rte_bitrate.h>
> +
> +/*
> + * Persistent bit-rate data.
> + * @internal
> + */
> +struct rte_stats_bitrate_s {
> +	uint64_t last_ibytes;
> +	uint64_t last_obytes;
> +	uint64_t peak_ibits;
> +	uint64_t peak_obits;
> +	uint64_t ewma_ibits;
> +	uint64_t ewma_obits;
> +};

Nit: same as previous metrics patch, any reason for the _s at the end? Same for following structs:

> +
> +struct rte_stats_bitrates_s {
> +	struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS];
> +	uint16_t id_stats_set;
> +};
> +
> +struct rte_stats_bitrates_s *
> +rte_stats_bitrate_create(void)
> +{
> +	return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s),
> +		RTE_CACHE_LINE_SIZE);
> +}

Is the socket relevant here? Perhaps pass socket_id to the function, and use rte_zmalloc_socket(). This function has no way of initializing bitrate structs on two different sockets, using one a single setup thread.

> +
> +int
> +rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data)
> +{
> +	const char * const names[] = {
> +		"mean_bits_in", "mean_bits_out",
> +		"peak_bits_in", "peak_bits_out",
> +	};
> +	int return_value;
> +
> +	return_value = rte_metrics_reg_metrics(&names[0], 4);
> +	if (return_value >= 0)
> +		bitrate_data->id_stats_set = return_value;
> +	return return_value;
> +}
> +
> +int
> +rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
> +	uint8_t port_id)
> +{
> +	struct rte_stats_bitrate_s *port_data;
> +	struct rte_eth_stats eth_stats;
> +	int ret_code;
> +	uint64_t cnt_bits;
> +	int64_t delta;
> +	const int64_t alpha_percent = 20;
> +	uint64_t values[4];
> +
> +	ret_code = rte_eth_stats_get(port_id, &eth_stats);
> +	if (ret_code != 0)
> +		return ret_code;
> +
> +	port_data = &bitrate_data->port_stats[port_id];
> +
> +	/* Incoming bitrate. This is an iteratively calculated EWMA
> +	 * (Expomentially Weighted Moving Average) that uses a
> +	 * weighting factor of alpha_percent.
> +	 */
> +	cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3;
> +	port_data->last_ibytes = eth_stats.ibytes;
> +	if (cnt_bits > port_data->peak_ibits)
> +		port_data->peak_ibits = cnt_bits;
> +	delta = cnt_bits;
> +	delta -= port_data->ewma_ibits;
> +	/* The +-50 fixes integer rounding during divison */
> +	if (delta > 0)
> +		delta = (delta * alpha_percent + 50) / 100;
> +	else
> +		delta = (delta * alpha_percent - 50) / 100;
> +	port_data->ewma_ibits += delta;

The integer +50 feels a bit odd, I'm not opposed to this if it works though.
The latency stats uses a float alpha multiplier, is that a
cleaner solution? The two libraries should probably be consistent anyway.

> +
> +	/* Outgoing bitrate (also EWMA) */
> +	cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3;
> +	port_data->last_obytes = eth_stats.obytes;
> +	if (cnt_bits > port_data->peak_obits)
> +		port_data->peak_obits = cnt_bits;
> +	delta = cnt_bits;
> +	delta -= port_data->ewma_obits;
> +	delta = (delta * alpha_percent + 50) / 100;

Same float multiplier comment.

> +	port_data->ewma_obits += delta;
> +
> +	values[0] = port_data->ewma_ibits;
> +	values[1] = port_data->ewma_obits;
> +	values[2] = port_data->peak_ibits;
> +	values[3] = port_data->peak_obits;
> +	rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set,
> +		values, 4);
> +	return 0;
> +}
> diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h
> new file mode 100644
> index 0000000..bc87c5e
> --- /dev/null
> +++ b/lib/librte_bitratestats/rte_bitrate.h
> @@ -0,0 +1,80 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2016 Intel Corporation. All rights reserved.
> + *   All rights reserved.

-2017

> + *
> + *   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.
> + */
> +
> +
> +/**
> + *  Bitrate statistics data structure.
> + *  This data structure is intentionally opaque.
> + */
> +struct rte_stats_bitrates_s;

_s question as previously highlighted.

> +
> +
> +/**
> + * Allocate a bitrate statistics structure
> + *
> + * @return
> + *   - Pointer to structure on success
> + *   - NULL on error (zmalloc failure)
> + */
> +struct rte_stats_bitrates_s *rte_stats_bitrate_create(void);
> +
> +
> +/**
> + * Register bitrate statistics with the metric library.
> + *
> + * @param bitrate_data
> + *   Pointer allocated by rte_stats_create()
> + *
> + * @return
> + *   Zero on success
> + *   Negative on error
> + */
> +int rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data);
> +
> +
> +/**
> + * Calculate statistics for current time window. The period with which
> + * this function is called should be the intended sampling window width.
> + *
> + * @param bitrate_data
> + *   Bitrate statistics data pointer
> + *
> + * @param port_id
> + *   Port id to calculate statistics for
> + *
> + * @return
> + *  - Zero on success
> + *  - Negative value on error
> + */
> +int rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data,
> +	uint8_t port_id);
> diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map
> b/lib/librte_bitratestats/rte_bitratestats_version.map
> new file mode 100644
> index 0000000..66f232f
> --- /dev/null
> +++ b/lib/librte_bitratestats/rte_bitratestats_version.map
> @@ -0,0 +1,9 @@
> +DPDK_17.02 {
> +	global:
> +
> +	rte_stats_bitrate_calc;
> +	rte_stats_bitrate_create;
> +	rte_stats_bitrate_reg;
> +
> +	local: *;
> +};
> diff --git a/mk/rte.app.mk b/mk/rte.app.mk
> index 40fcf33..6aac5ac 100644
> --- a/mk/rte.app.mk
> +++ b/mk/rte.app.mk
> @@ -99,6 +99,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
> +_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
> 
> 
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
> --
> 2.5.5

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

* Re: [PATCH v7 4/6] app/test-pmd: add bitrate statistics calculation
  2017-01-16 16:19             ` [PATCH v7 4/6] app/test-pmd: add bitrate statistics calculation Remy Horton
@ 2017-01-17 11:19               ` Van Haaren, Harry
  0 siblings, 0 replies; 115+ messages in thread
From: Van Haaren, Harry @ 2017-01-17 11:19 UTC (permalink / raw)
  To: Horton, Remy, dev; +Cc: Thomas Monjalon

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Monday, January 16, 2017 4:20 PM
> To: dev@dpdk.org
> Cc: Thomas Monjalon <thomas.monjalon@6wind.com>
> Subject: [dpdk-dev] [PATCH v7 4/6] app/test-pmd: add bitrate statistics calculation
> 
> Calculate bitrate statistics using the bitrate stats library. The
> resulting statistics can be viewed via proc_info.
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>

Inline

> ---
>  app/test-pmd/testpmd.c | 36 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 36 insertions(+)
> 

License year update, 2016 to 2017.

Rest of changes looks good to me.


> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
> index bfb2f8e..a0b7430 100644
> --- a/app/test-pmd/testpmd.c
> +++ b/app/test-pmd/testpmd.c
> @@ -79,6 +79,10 @@
>  #include <rte_pdump.h>
>  #endif
>  #include <rte_flow.h>
> +#include <rte_metrics.h>
> +#ifdef RTE_LIBRTE_BITRATE
> +#include <rte_bitrate.h>
> +#endif
> 
>  #include "testpmd.h"
> 
> @@ -323,6 +327,9 @@ uint16_t nb_rx_queue_stats_mappings = 0;
> 
>  unsigned max_socket = 0;
> 
> +/* Bitrate statistics */
> +struct rte_stats_bitrates_s *bitrate_data;
> +
>  /* Forward function declarations */
>  static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
>  static void check_all_ports_link_status(uint32_t port_mask);
> @@ -922,12 +929,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
>  	struct fwd_stream **fsm;
>  	streamid_t nb_fs;
>  	streamid_t sm_id;
> +#ifdef RTE_LIBRTE_BITRATE
> +	uint64_t tics_per_1sec;
> +	uint64_t tics_datum;
> +	uint64_t tics_current;
> +	uint8_t idx_port, cnt_ports;
> +#endif
> 
> +#ifdef RTE_LIBRTE_BITRATE
> +	cnt_ports = rte_eth_dev_count();
> +	tics_datum = rte_rdtsc();
> +	tics_per_1sec = rte_get_timer_hz();
> +#endif
>  	fsm = &fwd_streams[fc->stream_idx];
>  	nb_fs = fc->stream_nb;
>  	do {
>  		for (sm_id = 0; sm_id < nb_fs; sm_id++)
>  			(*pkt_fwd)(fsm[sm_id]);
> +#ifdef RTE_LIBRTE_BITRATE
> +		tics_current = rte_rdtsc();
> +		if (tics_current - tics_datum >= tics_per_1sec) {
> +			/* Periodic bitrate calculation */
> +			for (idx_port = 0; idx_port < cnt_ports; idx_port++)
> +				rte_stats_bitrate_calc(bitrate_data, idx_port);
> +			tics_datum = tics_current;
> +		}
> +#endif
>  	} while (! fc->stopped);
>  }
> 
> @@ -2139,6 +2166,15 @@ main(int argc, char** argv)
>  	FOREACH_PORT(port_id, ports)
>  		rte_eth_promiscuous_enable(port_id);
> 
> +	/* Setup bitrate stats */
> +#ifdef RTE_LIBRTE_BITRATE
> +	bitrate_data = rte_stats_bitrate_create();
> +	if (bitrate_data == NULL)
> +		rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n");
> +	rte_stats_bitrate_reg(bitrate_data);
> +#endif
> +
> +
>  #ifdef RTE_LIBRTE_CMDLINE
>  	if (interactive == 1) {
>  		if (auto_start) {
> --
> 2.5.5

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

* Re: [PATCH v7 5/6] lib: added new library for latency stats
  2017-01-17  4:29               ` Jerin Jacob
  2017-01-17  6:48                 ` Remy Horton
@ 2017-01-17 11:19                 ` Mcnamara, John
  2017-01-17 12:34                   ` Jerin Jacob
  1 sibling, 1 reply; 115+ messages in thread
From: Mcnamara, John @ 2017-01-17 11:19 UTC (permalink / raw)
  To: Jerin Jacob, Horton, Remy
  Cc: dev, Pattan, Reshma, Thomas Monjalon, olivier.matz

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Jerin Jacob
> Sent: Tuesday, January 17, 2017 4:30 AM
> To: Horton, Remy <remy.horton@intel.com>
> Cc: dev@dpdk.org; Pattan, Reshma <reshma.pattan@intel.com>; Thomas
> Monjalon <thomas.monjalon@6wind.com>
> Subject: Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency
> stats
> 
> On Mon, Jan 16, 2017 at 04:19:32PM +0000, Remy Horton wrote:
> > From: Reshma Pattan <reshma.pattan@intel.com>
> >
> > Add a library designed to calculate latency statistics and report them
> > to the application when queried. The library measures minimum, average
> > and maximum latencies, and jitter in nano seconds. The current
> > implementation supports global latency stats, i.e. per application
> stats.
> >
> > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
> > Signed-off-by: Remy Horton <remy.horton@intel.com>
> > ---
> >  MAINTAINERS                                        |   4 +
> >  config/common_base                                 |   5 +
> >  doc/api/doxy-api-index.md                          |   1 +
> >  doc/api/doxy-api.conf                              |   1 +
> >  doc/guides/rel_notes/release_17_02.rst             |   5 +
> >  lib/Makefile                                       |   1 +
> >  lib/librte_latencystats/Makefile                   |  57 +++
> >  lib/librte_latencystats/rte_latencystats.c         | 389
> +++++++++++++++++++++
> >  lib/librte_latencystats/rte_latencystats.h         | 146 ++++++++
> >  .../rte_latencystats_version.map                   |  10 +
> >  lib/librte_mbuf/rte_mbuf.h                         |   3 +
> 
> It is a value added feature for DPDK. But what is the plan for
> incorporating the mbuf change? I have 8 month old mbuf change for ARM for
> natural alignment. If we are accepting any mbuf change then we need to
> include outstanding mbuf changes to avoid future ABI breakage.
> 
> http://dpdk.org/dev/patchwork/patch/12878/
> 

Hi Jerin,

As far as I know the plan was to reach some sort of consensus on the mbuf
structure at the DPDK Userspace 2016, during and after Olivier's
presentation and then to make those changes during 17.02.

However, I believe Olivier had other work commitments in this release and
wasn't able to work on the mbuf changes.

The above mbuf change (and addition at the end of the struct) should
have gone into that mbuf rework, along with your changes.

However, since the mbuf rework didn't happen we need to add the field in
this release.

I guess the difference between the above change and your change is that
the latter is more complex and potentially affect performance, and as such
makes more sense as part of a rework.

Perhaps we, as a community, should commit to the mbuf rework in 17.05
and make sure it gets done.

John


 

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

* Re: [PATCH v7 5/6] lib: added new library for latency stats
  2017-01-16 16:19             ` [PATCH v7 5/6] lib: added new library for latency stats Remy Horton
  2017-01-17  4:29               ` Jerin Jacob
@ 2017-01-17 11:41               ` Van Haaren, Harry
  1 sibling, 0 replies; 115+ messages in thread
From: Van Haaren, Harry @ 2017-01-17 11:41 UTC (permalink / raw)
  To: Horton, Remy, dev; +Cc: Pattan, Reshma, Thomas Monjalon

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Monday, January 16, 2017 4:20 PM
> To: dev@dpdk.org
> Cc: Pattan, Reshma <reshma.pattan@intel.com>; Thomas Monjalon <thomas.monjalon@6wind.com>
> Subject: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats
> 
> From: Reshma Pattan <reshma.pattan@intel.com>
> 
> Add a library designed to calculate latency statistics and report them
> to the application when queried. The library measures minimum, average and
> maximum latencies, and jitter in nano seconds. The current implementation
> supports global latency stats, i.e. per application stats.
> 
> Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
> Signed-off-by: Remy Horton <remy.horton@intel.com>
> ---

This patch addresses a few changes - and should probably be split out a bit more than the v6 -> v7 changes done. In particular, the mbuf change should be its own commit to make it visible in the git log.

Detailed comments inline.


> diff --git a/MAINTAINERS b/MAINTAINERS
> index 6cd9896..0a41fe5 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -714,3 +714,7 @@ F: examples/tep_termination/
>  F: examples/vmdq/
>  F: examples/vmdq_dcb/
>  F: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst
> +
> +Latency Stats
> +M: Reshma Pattan <reshma.pattan@intel.com>
> +F: lib/librte_latencystats/

Wrong section? This should be added to the "other libraries" I think.


> +++ b/lib/librte_latencystats/Makefile
> @@ -0,0 +1,57 @@
> +#   BSD LICENSE
> +#
> +#   Copyright(c) 2016 Intel Corporation. All rights reserved.
> +#   All rights reserved.

-2017

> +++ b/lib/librte_latencystats/rte_latencystats.c
> @@ -0,0 +1,389 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2016 Intel Corporation. All rights reserved.
> + *   All rights reserved.

-2017

> +
> +/** Nano seconds per second */
> +#define NS_PER_SEC 1E9
> +
> +/** Clock cycles per nano second */
> +#define CYCLES_PER_NS (rte_get_timer_hz() / NS_PER_SEC)

Concidering this calls a function, it should probably be a
static inline function instead of a #define, so it is obvious
this cannot be used for static initialization.

> +
> +/* Macros for printing using RTE_LOG */
> +#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1
> +
> +static pthread_t latency_stats_thread;

Concerned about the pthread - see below.

> +static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats";
> +static int latency_stats_index;
> +static uint64_t samp_intvl;
> +static uint64_t timer_tsc;
> +static uint64_t prev_tsc;
> +
> +static struct rte_latency_stats {
> +	float min_latency; /**< Minimum latency in nano seconds */
> +	float avg_latency; /**< Average latency in nano seconds */
> +	float max_latency; /**< Maximum latency in nano seconds */
> +	float jitter; /** Latency variation */
> +} *glob_stats;

Style guide advises against this type of initialization IIRC;
http://dpdk.org/doc/guides/contributing/coding_style.html#structure-declarations

Its not very clear, but I do think a separate line makes the variable declaration on its own line more obvious:

static struct rte_latency_stats *glob_stats;

> +
> +static struct rxtx_cbs {
> +	struct rte_eth_rxtx_callback *cb;
> +} rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT],
> +	tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];

Same as previous comment - this struct looks very confusing to me :)
Please declare explicitly on own lines:

static struct rxtx_cbs {
    struct rte_eth_rxtx_callback *cb;
};

static struct rxtx_cbs rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
static struct rxtx_cbs tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];

> +
> +struct latency_stats_nameoff {
> +	char name[RTE_ETH_XSTATS_NAME_SIZE];
> +	unsigned int offset;
> +};
> +
> +static const struct latency_stats_nameoff lat_stats_strings[] = {
> +	{"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)},
> +	{"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)},
> +	{"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)},
> +	{"jitter_ns", offsetof(struct rte_latency_stats, jitter)},
> +};
> +
> +#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \
> +				sizeof(lat_stats_strings[0]))
> +
> +static __attribute__((noreturn)) void *
> +report_latency_stats(__rte_unused void *arg)
> +{
> +	for (;;) {
> +		unsigned int i;
> +		float *stats_ptr = NULL;
> +		uint64_t values[NUM_LATENCY_STATS] = {0};
> +		int ret;
> +
> +		for (i = 0; i < NUM_LATENCY_STATS; i++) {
> +			stats_ptr = RTE_PTR_ADD(glob_stats,
> +					lat_stats_strings[i].offset);
> +			values[i] = (uint64_t)floor((*stats_ptr)/
> +					CYCLES_PER_NS);
> +		}
> +
> +		ret = rte_metrics_update_metrics(RTE_METRICS_GLOBAL,
> +						latency_stats_index,
> +						values, NUM_LATENCY_STATS);
> +		if (ret < 0)
> +			RTE_LOG(INFO, LATENCY_STATS,
> +				"Failed to push the stats\n");
> +	}
> +}

This function is strange - the library creates a pthread and then calls this function internally?
This does not look like a good design from my point-of-view.

The Timer library may be of use for inspiration, it requires the application polls a function to handle expired timers:
void rte_timer_manage().


> +static void
> +rte_latencystats_fill_values(struct rte_metric_value *values)
> +{
> +	unsigned int i;
> +	float *stats_ptr = NULL;
> +
> +	for (i = 0; i < NUM_LATENCY_STATS; i++) {
> +		stats_ptr = RTE_PTR_ADD(glob_stats,
> +				lat_stats_strings[i].offset);
> +		values[i].key = i;
> +		values[i].value = (uint64_t)floor((*stats_ptr)/
> +						CYCLES_PER_NS);
> +	}
> +}
> +
> +static uint16_t
> +add_time_stamps(uint8_t pid __rte_unused,
> +		uint16_t qid __rte_unused,
> +		struct rte_mbuf **pkts,
> +		uint16_t nb_pkts,
> +		uint16_t max_pkts __rte_unused,
> +		void *user_cb __rte_unused)
> +{
> +	unsigned int i;
> +	uint64_t diff_tsc, now;
> +
> +	/*
> +	 * For every sample interval,
> +	 * time stamp is marked on one received packet.
> +	 */
> +	now = rte_rdtsc();
> +	for (i = 0; i < nb_pkts; i++) {
> +		diff_tsc = now - prev_tsc;
> +		timer_tsc += diff_tsc;
> +		if (timer_tsc >= samp_intvl) {
> +			/*
> +			 * TBD: Mark the timestamp only
> +			 * if not already marked by the
> +			 * hardware or the PMD.
> +			 */
> +			pkts[i]->timestamp = now;
> +			timer_tsc = 0;
> +		}
> +		prev_tsc = now;
> +		now = rte_rdtsc();
> +	}
> +
> +	return nb_pkts;
> +}
> +
> +static uint16_t
> +calc_latency(uint8_t pid __rte_unused,
> +		uint16_t qid __rte_unused,
> +		struct rte_mbuf **pkts,
> +		uint16_t nb_pkts,
> +		void *_ __rte_unused)
> +{
> +	unsigned int i, cnt = 0;
> +	uint64_t now;
> +	float latency[nb_pkts];
> +	static float prev_latency;
> +	/*
> +	 * Alpha represents degree of weighting decrease in EWMA,
> +	 * a constant smoothing factor between 0 and 1. The value
> +	 * is used below for measuring average latency.
> +	 */
> +	const float alpha = 0.2;
> +
> +	now = rte_rdtsc();
> +	for (i = 0; i < nb_pkts; i++) {
> +		if (pkts[i]->timestamp)
> +			latency[cnt++] = now - pkts[i]->timestamp;
> +	}
> +
> +	for (i = 0; i < cnt; i++) {
> +		/*
> +		 * The jitter is calculated as statistical mean of interpacket
> +		 * delay variation. The "jitter estimate" is computed by taking
> +		 * the absolute values of the ipdv sequence and applying an
> +		 * exponential filter with parameter 1/16 to generate the
> +		 * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter,
> +		 * D(i-1,i) is difference in latency of two consecutive packets
> +		 * i-1 and i.
> +		 * Reference: Calculated as per RFC 5481, sec 4.1,
> +		 * RFC 3393 sec 4.5, RFC 1889 sec.
> +		 */
> +		glob_stats->jitter +=  (abs(prev_latency - latency[i])
> +					- glob_stats->jitter)/16;
> +		if (glob_stats->min_latency == 0)
> +			glob_stats->min_latency = latency[i];
> +		else if (latency[i] < glob_stats->min_latency)
> +			glob_stats->min_latency = latency[i];
> +		else if (latency[i] > glob_stats->max_latency)
> +			glob_stats->max_latency = latency[i];
> +		/*
> +		 * The average latency is measured using exponential moving
> +		 * average, i.e. using EWMA
> +		 * https://en.wikipedia.org/wiki/Moving_average
> +		 */
> +		glob_stats->avg_latency +=
> +			alpha * (latency[i] - glob_stats->avg_latency);
> +		prev_latency = latency[i];
> +	}
> +
> +	return nb_pkts;
> +}
> +
> +int
> +rte_latencystats_init(uint64_t samp_intvl,
> +		rte_latency_stats_flow_type_fn user_cb)
> +{
> +	unsigned int i;
> +	uint8_t pid;
> +	uint16_t qid;
> +	struct rxtx_cbs *cbs = NULL;
> +	const uint8_t nb_ports = rte_eth_dev_count();
> +	const char *ptr_strings[NUM_LATENCY_STATS] = {0};
> +	const struct rte_memzone *mz = NULL;
> +	const unsigned int flags = 0;
> +
> +	/** Allocate stats in shared memory fo muliti process support */
> +	mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats),
> +					rte_socket_id(), flags);
> +	if (mz == NULL) {
> +		RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n",
> +			__func__, __LINE__);
> +		return -ENOMEM;
> +	}

There is no check for double-initialization of the library - although it is an application error to initialize twice, the library should handle it.

> +
> +	glob_stats = mz->addr;
> +	samp_intvl *= CYCLES_PER_NS;
> +
> +	/** Register latency stats with stats library */
> +	for (i = 0; i < NUM_LATENCY_STATS; i++)
> +		ptr_strings[i] = lat_stats_strings[i].name;
> +
> +	latency_stats_index = rte_metrics_reg_metrics(ptr_strings,
> +							NUM_LATENCY_STATS);
> +	if (latency_stats_index < 0) {
> +		RTE_LOG(DEBUG, LATENCY_STATS,
> +			"Failed to register latency stats names\n");
> +		return -1;
> +	}
> +
> +	/** Register Rx/Tx callbacks */
> +	for (pid = 0; pid < nb_ports; pid++) {
> +		struct rte_eth_dev_info dev_info;
> +		rte_eth_dev_info_get(pid, &dev_info);
> +		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
> +			cbs = &rx_cbs[pid][qid];
> +			cbs->cb = rte_eth_add_first_rx_callback(pid, qid,
> +					add_time_stamps, user_cb);
> +			if (!cbs->cb)
> +				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
> +					"register Rx callback for pid=%d, "
> +					"qid=%d\n", pid, qid);
> +		}
> +		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
> +			cbs = &tx_cbs[pid][qid];
> +			cbs->cb =  rte_eth_add_tx_callback(pid, qid,
> +					calc_latency, user_cb);
> +			if (!cbs->cb)
> +				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
> +					"register Tx callback for pid=%d, "
> +					"qid=%d\n", pid, qid);
> +		}
> +	}
> +
> +	int ret = 0;
> +	char thread_name[RTE_MAX_THREAD_NAME_LEN];
> +
> +	/** Create the host thread to update latency stats to stats library */
> +	ret = pthread_create(&latency_stats_thread, NULL, report_latency_stats,
> +				NULL);
> +	if (ret != 0) {
> +		RTE_LOG(ERR, LATENCY_STATS,
> +			"Failed to create the latency stats thread:%s, %s:%d\n",
> +			strerror(errno), __func__, __LINE__);
> +		return -1;
> +	}

This pthread_create() raises some flags, spawning a thread "behind the applications back" isn't a good plan. We should require a thread poll the latency stats, not create a thread ourselves. See note above on using an application thread.


> +	/** Set thread_name for aid in debugging */
> +	snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "latency-stats-thread");
> +	ret = rte_thread_setname(latency_stats_thread, thread_name);
> +	if (ret != 0)
> +		RTE_LOG(DEBUG, LATENCY_STATS,
> +			"Failed to set thread name for latency stats handling\n");
> +
> +	return 0;
> +}
> +
> +int
> +rte_latencystats_uninit(void)
> +{
> +	uint8_t pid;
> +	uint16_t qid;
> +	int ret = 0;
> +	struct rxtx_cbs *cbs = NULL;
> +	const uint8_t nb_ports = rte_eth_dev_count();
> +
> +	/** De register Rx/Tx callbacks */
> +	for (pid = 0; pid < nb_ports; pid++) {
> +		struct rte_eth_dev_info dev_info;
> +		rte_eth_dev_info_get(pid, &dev_info);
> +		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
> +			cbs = &rx_cbs[pid][qid];
> +			ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb);
> +			if (ret)
> +				RTE_LOG(INFO, LATENCY_STATS, "failed to "
> +					"remove Rx callback for pid=%d, "
> +					"qid=%d\n", pid, qid);
> +		}
> +		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
> +			cbs = &tx_cbs[pid][qid];
> +			ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb);
> +			if (ret)
> +				RTE_LOG(INFO, LATENCY_STATS, "failed to "
> +					"remove Tx callback for pid=%d, "
> +					"qid=%d\n", pid, qid);
> +		}
> +	}
> +
> +	/** Cancel the thread */
> +	ret = pthread_cancel(latency_stats_thread);
> +	if (ret != 0) {
> +		RTE_LOG(ERR, LATENCY_STATS,
> +			"Failed to cancel latency stats update thread:"
> +			"%s,%s:%d\n",
> +			strerror(errno), __func__, __LINE__);
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +int
> +rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size)
> +{
> +	unsigned int i;
> +
> +	if (names == NULL || size < NUM_LATENCY_STATS)
> +		return NUM_LATENCY_STATS;
> +
> +	for (i = 0; i < NUM_LATENCY_STATS; i++)
> +		snprintf(names[i].name, sizeof(names[i].name),
> +				"%s", lat_stats_strings[i].name);
> +
> +	return NUM_LATENCY_STATS;
> +}
> +
> +int
> +rte_latencystats_get(struct rte_metric_value *values, uint16_t size)
> +{
> +	if (size < NUM_LATENCY_STATS || values == NULL)
> +		return NUM_LATENCY_STATS;
> +
> +	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
> +		const struct rte_memzone *mz;
> +		mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS);
> +		if (mz == NULL) {
> +			RTE_LOG(ERR, LATENCY_STATS,
> +				"Latency stats memzone not found\n");
> +			return -ENOMEM;
> +		}
> +		glob_stats =  mz->addr;
> +	}
> +
> +	/* Retrieve latency stats */
> +	rte_latencystats_fill_values(values);
> +
> +	return NUM_LATENCY_STATS;
> +}
> diff --git a/lib/librte_latencystats/rte_latencystats.h
> b/lib/librte_latencystats/rte_latencystats.h
> new file mode 100644
> index 0000000..405b878
> --- /dev/null
> +++ b/lib/librte_latencystats/rte_latencystats.h
> @@ -0,0 +1,146 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2016 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 _RTE_LATENCYSTATS_H_
> +#define _RTE_LATENCYSTATS_H_
> +
> +/**
> + * @file
> + * RTE latency stats
> + *
> + * library to provide application and flow based latency stats.
> + */
> +
> +#include <rte_metrics.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**
> + *  Note: This function pointer is for future flow based latency stats
> + *  implementation.
> + *
> + * Function type used for identifting flow types of a Rx packet.
> + *
> + * The callback function is called on Rx for each packet.
> + * This function is used for flow based latency calculations.
> + *
> + * @param pkt
> + *   Packet that has to be identified with its flow types.
> + * @param user_param
> + *   The arbitrary user parameter passed in by the application when
> + *   the callback was originally configured.
> + * @return
> + *   The flow_mask, representing the multiple flow types of a packet.
> + */
> +typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt,
> +							void *user_param);
> +
> +/**
> + *  Registers Rx/Tx callbacks for each active port, queue.
> + *
> + * @param samp_intvl
> + *  Sampling time period in nano seconds, at which packet
> + *  should be marked with time stamp.
> + * @param user_cb
> + *  Note: This param is for future flow based latency stats
> + *  implementation.
> + *  User callback to be called to get flow types of a packet.
> + *  Used for flow based latency calculation.
> + *  If the value is NULL, global stats will be calculated,
> + *  else flow based latency stats will be calculated.
> + *  For now just pass on the NULL value to this param.
> + *  @return
> + *   -1     : On error
> + *   -ENOMEM: On error
> + *    0     : On success
> + */
> +int rte_latencystats_init(uint64_t samp_intvl,
> +			rte_latency_stats_flow_type_fn user_cb);
> +
> +/**
> + *  Removes registered Rx/Tx callbacks for each active port, queue.
> + *
> + *  @return
> + *   -1: On error
> + *    0: On success
> + */
> +int rte_latencystats_uninit(void);
> +
> +/**
> + * Retrieve names of latency statistics
> + *
> + * @param names
> + *  Block of memory to insert names into. Must be at least size in capacity.
> + *  If set to NULL, function returns required capacity.
> + * @param size
> + *  Capacity of latency stats names (number of names).
> + * @return
> + *   - positive value lower or equal to size: success. The return value
> + *     is the number of entries filled in the stats table.
> + *   - positive value higher than size: error, the given statistics table
> + *     is too small. The return value corresponds to the size that should
> + *     be given to succeed. The entries in the table are not valid and
> + *     shall not be used by the caller.
> + */
> +int rte_latencystats_get_names(struct rte_metric_name *names,
> +				uint16_t size);
> +
> +/**
> + * Retrieve latency statistics.
> + *
> + * @param values
> + *   A pointer to a table of structure of type *rte_metric_value*
> + *   to be filled with latency statistics ids and values.
> + *   This parameter can be set to NULL if size is 0.
> + * @param size
> + *   The size of the stats table, which should be large enough to store
> + *   all the latency stats.
> + * @return
> + *   - positive value lower or equal to size: success. The return value
> + *     is the number of entries filled in the stats table.
> + *   - positive value higher than size: error, the given statistics table
> + *     is too small. The return value corresponds to the size that should
> + *     be given to succeed. The entries in the table are not valid and
> + *     shall not be used by the caller.
> + *   -ENOMEM: On failure.
> + */
> +int rte_latencystats_get(struct rte_metric_value *values,
> +			uint16_t size);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_LATENCYSTATS_H_ */
> diff --git a/lib/librte_latencystats/rte_latencystats_version.map
> b/lib/librte_latencystats/rte_latencystats_version.map
> new file mode 100644
> index 0000000..502018e
> --- /dev/null
> +++ b/lib/librte_latencystats/rte_latencystats_version.map
> @@ -0,0 +1,10 @@
> +DPDK_17.02 {
> +	global:
> +
> +	rte_latencystats_get;
> +	rte_latencystats_get_names;
> +	rte_latencystats_init;
> +	rte_latencystats_uninit;
> +
> +	local: *;
> +};
> diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
> index bfce9f4..c35ba0a 100644
> --- a/lib/librte_mbuf/rte_mbuf.h
> +++ b/lib/librte_mbuf/rte_mbuf.h
> @@ -512,6 +512,9 @@ struct rte_mbuf {
> 
>  	/** Timesync flags for use with IEEE1588. */
>  	uint16_t timesync;
> +
> +	/** Timestamp for measuring latency. */
> +	uint64_t timestamp;
>  } __rte_cache_aligned;
> 

This change needs its own patch, so it can be reviewed independently and the position in the struct for timestamp can be analysed easily.


>  /**
> diff --git a/mk/rte.app.mk b/mk/rte.app.mk
> index 6aac5ac..1d36fad 100644
> --- a/mk/rte.app.mk
> +++ b/mk/rte.app.mk
> @@ -100,7 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
> -
> +_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)  += -lrte_latencystats
> 
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
>  _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
> --
> 2.5.5

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

* Re: [PATCH v7 6/6] app/test-pmd: add latency statistics calculation
  2017-01-16 16:19             ` [PATCH v7 6/6] app/test-pmd: add latency statistics calculation Remy Horton
@ 2017-01-17 11:45               ` Van Haaren, Harry
  0 siblings, 0 replies; 115+ messages in thread
From: Van Haaren, Harry @ 2017-01-17 11:45 UTC (permalink / raw)
  To: Horton, Remy, dev; +Cc: Pattan, Reshma, Thomas Monjalon

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Monday, January 16, 2017 4:20 PM
> To: dev@dpdk.org
> Cc: Pattan, Reshma <reshma.pattan@intel.com>; Thomas Monjalon <thomas.monjalon@6wind.com>
> Subject: [dpdk-dev] [PATCH v7 6/6] app/test-pmd: add latency statistics calculation
> 
> From: Reshma Pattan <reshma.pattan@intel.com>
> 
> Modify testpmd code to initialize/uninitialize latency statistics
> calulation.
> 
> Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
> Signed-off-by: Remy Horton <remy.horton@intel.com>

Comment inline.

> ---
>  app/test-pmd/testpmd.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
> index a0b7430..2874ce4 100644
> --- a/app/test-pmd/testpmd.c
> +++ b/app/test-pmd/testpmd.c
> @@ -83,6 +83,10 @@
>  #ifdef RTE_LIBRTE_BITRATE
>  #include <rte_bitrate.h>
>  #endif
> +#include <rte_metrics.h>
> +#ifdef RTE_LIBRTE_LATENCY_STATS
> +#include <rte_latencystats.h>
> +#endif
> 
>  #include "testpmd.h"
> 
> @@ -2108,6 +2112,9 @@ signal_handler(int signum)
>  		/* uninitialize packet capture framework */
>  		rte_pdump_uninit();
>  #endif
> +#ifdef RTE_LIBRTE_LATENCY_STATS
> +		rte_latencystats_uninit();
> +#endif
>  		force_quit();
>  		/* exit with the expected status */
>  		signal(signum, SIG_DFL);
> @@ -2165,6 +2172,9 @@ main(int argc, char** argv)
>  	/* set all ports to promiscuous mode by default */
>  	FOREACH_PORT(port_id, ports)
>  		rte_eth_promiscuous_enable(port_id);
> +#ifdef RTE_LIBRTE_LATENCY_STATS
> +	rte_latencystats_init(1, NULL);
> +#endif

The 1 here represents reporting time in ns correct? 1 ns seems a very short amount of time.
Perhaps clarify (here or in the header) what exactly this number does, or set it to 0 for "as fast as possible"?

> 
>  	/* Setup bitrate stats */
>  #ifdef RTE_LIBRTE_BITRATE
> --
> 2.5.5

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

* Re: [PATCH v7 5/6] lib: added new library for latency stats
  2017-01-17 11:19                 ` Mcnamara, John
@ 2017-01-17 12:34                   ` Jerin Jacob
  2017-01-17 14:53                     ` Mcnamara, John
  0 siblings, 1 reply; 115+ messages in thread
From: Jerin Jacob @ 2017-01-17 12:34 UTC (permalink / raw)
  To: Mcnamara, John
  Cc: Horton, Remy, dev, Pattan, Reshma, Thomas Monjalon, olivier.matz

On Tue, Jan 17, 2017 at 11:19:24AM +0000, Mcnamara, John wrote:
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Jerin Jacob
> > Sent: Tuesday, January 17, 2017 4:30 AM
> > To: Horton, Remy <remy.horton@intel.com>
> > Cc: dev@dpdk.org; Pattan, Reshma <reshma.pattan@intel.com>; Thomas
> > Monjalon <thomas.monjalon@6wind.com>
> > Subject: Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency
> > stats
> > 
> > On Mon, Jan 16, 2017 at 04:19:32PM +0000, Remy Horton wrote:
> > > From: Reshma Pattan <reshma.pattan@intel.com>
> > >
> > > Add a library designed to calculate latency statistics and report them
> > > to the application when queried. The library measures minimum, average
> > > and maximum latencies, and jitter in nano seconds. The current
> > > implementation supports global latency stats, i.e. per application
> > stats.
> > >
> > > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
> > > Signed-off-by: Remy Horton <remy.horton@intel.com>
> > > ---
> > >  MAINTAINERS                                        |   4 +
> > >  config/common_base                                 |   5 +
> > >  doc/api/doxy-api-index.md                          |   1 +
> > >  doc/api/doxy-api.conf                              |   1 +
> > >  doc/guides/rel_notes/release_17_02.rst             |   5 +
> > >  lib/Makefile                                       |   1 +
> > >  lib/librte_latencystats/Makefile                   |  57 +++
> > >  lib/librte_latencystats/rte_latencystats.c         | 389
> > +++++++++++++++++++++
> > >  lib/librte_latencystats/rte_latencystats.h         | 146 ++++++++
> > >  .../rte_latencystats_version.map                   |  10 +
> > >  lib/librte_mbuf/rte_mbuf.h                         |   3 +
> > 
> > It is a value added feature for DPDK. But what is the plan for
> > incorporating the mbuf change? I have 8 month old mbuf change for ARM for
> > natural alignment. If we are accepting any mbuf change then we need to
> > include outstanding mbuf changes to avoid future ABI breakage.
> > 
> > http://dpdk.org/dev/patchwork/patch/12878/
> > 
> 
> Hi Jerin,

Hi John,

> 
> As far as I know the plan was to reach some sort of consensus on the mbuf
> structure at the DPDK Userspace 2016, during and after Olivier's
> presentation and then to make those changes during 17.02.
> 
> However, I believe Olivier had other work commitments in this release and
> wasn't able to work on the mbuf changes.
> 
> The above mbuf change (and addition at the end of the struct) should
> have gone into that mbuf rework, along with your changes.
> 
> However, since the mbuf rework didn't happen we need to add the field in
> this release.

So we don't care the mbuf ABI breakage in the next release. This wasn't
the message I got earlier for ARM's mbuf change.

http://dpdk.org/dev/patchwork/patch/12878/

> 
> I guess the difference between the above change and your change is that
> the latter is more complex and potentially affect performance, and as such
> makes more sense as part of a rework.

The mbuf natural alignment is a not complex change, it just moving the field and
it does not have any performance impact on IA nor nobody reported any
performance regression on IA.

There is nothing against you or this feature. The only part concerns me
that some set of patches can always override any rule and include in the release
(even as marking as EXPERIMENTAL) because of its important for some set of consumers.
Another set has to wait in the queue because its not important for some people.
For me, it is not a sign of vendor neutral open source project.

Jerin

> 
> Perhaps we, as a community, should commit to the mbuf rework in 17.05
> and make sure it gets done.
> 
> John
> 
> 
>  
> 
> 
> 

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

* Re: [PATCH v7 1/6] lib: add information metrics library
  2017-01-17 11:01               ` Van Haaren, Harry
@ 2017-01-17 13:40                 ` Remy Horton
  2017-01-17 14:23                   ` Van Haaren, Harry
  0 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-01-17 13:40 UTC (permalink / raw)
  To: Van Haaren, Harry, dev; +Cc: Thomas Monjalon


On 17/01/2017 11:01, Van Haaren, Harry wrote:
>> -----Original Message-----
>> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
[..]
> Nit: why the _s in rte_metrics_meta_s? Is there a reason why struct
> rte_metrics_meta {  is not suitable? Same question for
> rte_metrics_data_s.

Think it was originally to avoid a namespace collision, and I left the 
suffix in because this is an internal data-structure.


>> +	if (memzone == NULL)
>> +		rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
>> +	stats = memzone->addr;
>> +	memset(stats, 0, sizeof(struct rte_metrics_data_s));
>> +	rte_spinlock_init(&stats->lock);
>
> Should this spinlock be initialized before the creation of the
> memzone? Creating the memzone first, and later initializing the
> locking-structure for it feels racey to me. The lock should probably
> be taken and unlocked again after init and memset.

Problem is the lock being part of the reserved memzone allocation. It is 
in there so that secondary processes can use the lock.


> Nit: would rte_metrics_reg_name() be a better function name?
[..]
> Nit: would rte_metrics_reg_names() be a better function name?

Agree. Done.


> Would rte_metrics_update_single() be a better function name?
[..]
> Would rte_metrics_update() be a better function name?

Think rte_metrics_update_value & rte_metrics_update_values would make a 
better pair. My preference at the moment is not to nominate a preferred one.


>> +	if (port_id != RTE_METRICS_GLOBAL &&
>> +			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
>> +		return -EINVAL;
>> +
>> +	rte_metrics_init();
>
> See above comments on rte_metrics_init() taking a socket_id parameter. Here any core could call update_metrics(), and if the library was not yet initialized, the memory for metrics would end up on the socket of this core. This should be avoided by
> A) adding socket_id parameter to the metrics_init() function
> B) Demanding that metrics_init() is called by the application before any core uses update_metrics()

Done. Should also help alleviate the race.


> What is a "set border"? I think this ensures that one set of metrics
> cannot overwrite the index's of another metrics set - correct?

It is intended to stop things like:

  idx1 = rte_metrics_reg_names(some_names, 2);
  idx2 = rte_metrics_reg_names(more_names, 3);
   ...
  rte_metrics_update_values(port_id, idx1, &new_values, 5);

as the above assumes idx2=idx1+2 which is not guaranteed in concurrent 
enviornments

..Remy

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

* Re: [PATCH v7 1/6] lib: add information metrics library
  2017-01-17 13:40                 ` Remy Horton
@ 2017-01-17 14:23                   ` Van Haaren, Harry
  0 siblings, 0 replies; 115+ messages in thread
From: Van Haaren, Harry @ 2017-01-17 14:23 UTC (permalink / raw)
  To: Horton, Remy, dev; +Cc: Thomas Monjalon

> -----Original Message-----
> From: Horton, Remy
> Sent: Tuesday, January 17, 2017 1:40 PM
> To: Van Haaren, Harry <harry.van.haaren@intel.com>; dev@dpdk.org
> Cc: Thomas Monjalon <thomas.monjalon@6wind.com>
> Subject: Re: [dpdk-dev] [PATCH v7 1/6] lib: add information metrics library
> 
> 
> On 17/01/2017 11:01, Van Haaren, Harry wrote:
> >> -----Original Message-----
> >> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> [..]
> > Nit: why the _s in rte_metrics_meta_s? Is there a reason why struct
> > rte_metrics_meta {  is not suitable? Same question for
> > rte_metrics_data_s.
> 
> Think it was originally to avoid a namespace collision, and I left the
> suffix in because this is an internal data-structure.

OK.

> >> +	if (memzone == NULL)
> >> +		rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
> >> +	stats = memzone->addr;
> >> +	memset(stats, 0, sizeof(struct rte_metrics_data_s));
> >> +	rte_spinlock_init(&stats->lock);
> >
> > Should this spinlock be initialized before the creation of the
> > memzone? Creating the memzone first, and later initializing the
> > locking-structure for it feels racey to me. The lock should probably
> > be taken and unlocked again after init and memset.
> 
> Problem is the lock being part of the reserved memzone allocation. It is
> in there so that secondary processes can use the lock.

Ah ok - apologies I missed that the lock is in the memory itself.

> 
> > Nit: would rte_metrics_reg_name() be a better function name?
> [..]
> > Nit: would rte_metrics_reg_names() be a better function name?
> 
> Agree. Done.

Great

> > Would rte_metrics_update_single() be a better function name?
> [..]
> > Would rte_metrics_update() be a better function name?
> 
> Think rte_metrics_update_value & rte_metrics_update_values would make a
> better pair. My preference at the moment is not to nominate a preferred one.
> 
> 
> >> +	if (port_id != RTE_METRICS_GLOBAL &&
> >> +			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
> >> +		return -EINVAL;
> >> +
> >> +	rte_metrics_init();
> >
> > See above comments on rte_metrics_init() taking a socket_id parameter. Here any core
> could call update_metrics(), and if the library was not yet initialized, the memory for
> metrics would end up on the socket of this core. This should be avoided by
> > A) adding socket_id parameter to the metrics_init() function
> > B) Demanding that metrics_init() is called by the application before any core uses
> update_metrics()
> 
> Done. Should also help alleviate the race.

Cool.


> > What is a "set border"? I think this ensures that one set of metrics
> > cannot overwrite the index's of another metrics set - correct?
> 
> It is intended to stop things like:
> 
>   idx1 = rte_metrics_reg_names(some_names, 2);
>   idx2 = rte_metrics_reg_names(more_names, 3);
>    ...
>   rte_metrics_update_values(port_id, idx1, &new_values, 5);
> 
> as the above assumes idx2=idx1+2 which is not guaranteed in concurrent
> enviornments


That confirms my understanding - thanks.

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

* Re: [PATCH v7 2/6] app/proc_info: add metrics displaying
  2017-01-17 11:08               ` Van Haaren, Harry
@ 2017-01-17 14:27                 ` Remy Horton
  0 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-17 14:27 UTC (permalink / raw)
  To: Van Haaren, Harry, dev; +Cc: Pattan, Reshma, Thomas Monjalon


On 17/01/2017 11:08, Van Haaren, Harry wrote:
[..]
>> +		"  --metrics: to display derived metrics of the ports, disabled by "
>> +			"default\n"
[..]
> I presume there is no need for a --metrics-reset as the values are reset when printed, correct?

Reset is not (currently) supported, as some of the expected future use 
of metrics is informational values that are not continually updated.


> Is malloc() favoured over rte_malloc() for a reason?

None I am aware of. There is a recent-ish preference for rte_malloc() 
over malloc() in new code, so will update..

..Remy

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

* Re: [PATCH v7 5/6] lib: added new library for latency stats
  2017-01-17 12:34                   ` Jerin Jacob
@ 2017-01-17 14:53                     ` Mcnamara, John
  2017-01-17 16:25                       ` Jerin Jacob
  0 siblings, 1 reply; 115+ messages in thread
From: Mcnamara, John @ 2017-01-17 14:53 UTC (permalink / raw)
  To: Jerin Jacob
  Cc: Horton, Remy, dev, Pattan, Reshma, Thomas Monjalon, olivier.matz,
	Richardson, Bruce



> -----Original Message-----
> From: Jerin Jacob [mailto:jerin.jacob@caviumnetworks.com]
> Sent: Tuesday, January 17, 2017 12:34 PM
> To: Mcnamara, John <john.mcnamara@intel.com>
> Cc: Horton, Remy <remy.horton@intel.com>; dev@dpdk.org; Pattan, Reshma
> <reshma.pattan@intel.com>; Thomas Monjalon <thomas.monjalon@6wind.com>;
> olivier.matz@6wind.com
> Subject: Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency
> stats
> 
> On Tue, Jan 17, 2017 at 11:19:24AM +0000, Mcnamara, John wrote:
> > > -----Original Message-----
> > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Jerin Jacob
> > > Sent: Tuesday, January 17, 2017 4:30 AM
> > > To: Horton, Remy <remy.horton@intel.com>
> > > Cc: dev@dpdk.org; Pattan, Reshma <reshma.pattan@intel.com>; Thomas
> > > Monjalon <thomas.monjalon@6wind.com>
> > > Subject: Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for
> > > latency stats
> > >
> > > On Mon, Jan 16, 2017 at 04:19:32PM +0000, Remy Horton wrote:
> > > > From: Reshma Pattan <reshma.pattan@intel.com>
> > > >
> > > > Add a library designed to calculate latency statistics and report
> > > > them to the application when queried. The library measures
> > > > minimum, average and maximum latencies, and jitter in nano
> > > > seconds. The current implementation supports global latency stats,
> > > > i.e. per application
> > > stats.
> > > >
> > > > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
> > > > Signed-off-by: Remy Horton <remy.horton@intel.com>
> > > > ---
> > > >  MAINTAINERS                                        |   4 +
> > > >  config/common_base                                 |   5 +
> > > >  doc/api/doxy-api-index.md                          |   1 +
> > > >  doc/api/doxy-api.conf                              |   1 +
> > > >  doc/guides/rel_notes/release_17_02.rst             |   5 +
> > > >  lib/Makefile                                       |   1 +
> > > >  lib/librte_latencystats/Makefile                   |  57 +++
> > > >  lib/librte_latencystats/rte_latencystats.c         | 389
> > > +++++++++++++++++++++
> > > >  lib/librte_latencystats/rte_latencystats.h         | 146 ++++++++
> > > >  .../rte_latencystats_version.map                   |  10 +
> > > >  lib/librte_mbuf/rte_mbuf.h                         |   3 +
> > >
> > > It is a value added feature for DPDK. But what is the plan for
> > > incorporating the mbuf change? I have 8 month old mbuf change for
> > > ARM for natural alignment. If we are accepting any mbuf change then
> > > we need to include outstanding mbuf changes to avoid future ABI
> breakage.
> > >
> > > http://dpdk.org/dev/patchwork/patch/12878/
> > >
> >
> > Hi Jerin,
> 
> Hi John,
> 
> >
> > As far as I know the plan was to reach some sort of consensus on the
> > mbuf structure at the DPDK Userspace 2016, during and after Olivier's
> > presentation and then to make those changes during 17.02.
> >
> > However, I believe Olivier had other work commitments in this release
> > and wasn't able to work on the mbuf changes.
> >
> > The above mbuf change (and addition at the end of the struct) should
> > have gone into that mbuf rework, along with your changes.
> >
> > However, since the mbuf rework didn't happen we need to add the field
> > in this release.
> 
> So we don't care the mbuf ABI breakage in the next release. This wasn't
> the message I got earlier for ARM's mbuf change.
> 
> http://dpdk.org/dev/patchwork/patch/12878/


Hi Jerin,

We do care about ABI breakage but I was under the impression that the
timestamp change wasn't breaking the ABI since it was at the end of the
struct. I also ran the ABI validator against the change and it didn't show any
breakage.

http://dpdk.org/doc/guides/contributing/versioning.html#running-the-abi-validator

The rearm_data alignment patch, on the other hand, does break ABI. I think
that is the main difference between the two patches.

If the timestamp change does break ABI then it should also wait until the mbuf
restructuring.


> ...
> 
> There is nothing against you or this feature. The only part concerns me
> that some set of patches can always override any rule and include in the
> release (even as marking as EXPERIMENTAL) because of its important for
> some set of consumers.
> Another set has to wait in the queue because its not important for some
> people.
> For me, it is not a sign of vendor neutral open source project.

To be fair I don't think we are trying to override any rule here. 

Also, we aren't the only vendor looking for a timestamp in the mbuf.
Mellanox also submitted a patch:

    http://dpdk.org/ml/archives/dev/2016-October/048809.html

However, it is also fair to acknowledge that the rearm_data alignment patch
shouldn't have had to wait so long. I can't really answer for that directly.
My feeling is that it was targeted for the mbuf rework but got forgotten
when that work slipped.

John

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

* Re: [PATCH v7 3/6] lib: add bitrate statistics library
  2017-01-17 11:16               ` Van Haaren, Harry
@ 2017-01-17 15:37                 ` Remy Horton
  0 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-17 15:37 UTC (permalink / raw)
  To: Van Haaren, Harry, dev; +Cc: Thomas Monjalon


On 17/01/2017 11:16, Van Haaren, Harry wrote:
[..]
>> +struct rte_stats_bitrates_s *
>> +rte_stats_bitrate_create(void)
>> +{
>> +	return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s),
>> +		RTE_CACHE_LINE_SIZE);
>> +}
>
> Is the socket relevant here? Perhaps pass socket_id to the function,
> and use rte_zmalloc_socket(). This function has no way of
> initializing bitrate structs on two different sockets, using one a
> single setup thread.

Not an issue in this case. It is expected that the thread that calls 
this creator will also be the thread that clocks the library (i.e. 
calling rte_stats_bitrate_calc()), and that one instance handles all 
ports. The memory block is not accessed outside of rte_stats_bitrate_calc().


>> +	/* The +-50 fixes integer rounding during divison */
>> +	if (delta > 0)
>> +		delta = (delta * alpha_percent + 50) / 100;
>> +	else
>> +		delta = (delta * alpha_percent - 50) / 100;
>> +	port_data->ewma_ibits += delta;
>
> The integer +50 feels a bit odd, I'm not opposed to this if it works though.

It was based on feedback regarding roundoffs when doing integer divides. 
Something about rounding to nearest integer rather than towards zero if 
I remember correctly..


>> +/**
>> + *  Bitrate statistics data structure.
>> + *  This data structure is intentionally opaque.
>> + */
>> +struct rte_stats_bitrates_s;
>
> _s question as previously highlighted.

Since this is a public structure, removed the _s prefix in this case. 
Looking over the coding guidelines I can't see anything explicitly 
against the notation, but existing structures have not used it.

..Remy

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

* Re: [PATCH v7 5/6] lib: added new library for latency stats
  2017-01-17 14:53                     ` Mcnamara, John
@ 2017-01-17 16:25                       ` Jerin Jacob
  2017-01-18 20:11                         ` Olivier Matz
  0 siblings, 1 reply; 115+ messages in thread
From: Jerin Jacob @ 2017-01-17 16:25 UTC (permalink / raw)
  To: Mcnamara, John
  Cc: Horton, Remy, dev, Pattan, Reshma, Thomas Monjalon, olivier.matz,
	Richardson, Bruce

On Tue, Jan 17, 2017 at 02:53:55PM +0000, Mcnamara, John wrote:
> 
> 
> > -----Original Message-----
> > From: Jerin Jacob [mailto:jerin.jacob@caviumnetworks.com]
> > Sent: Tuesday, January 17, 2017 12:34 PM
> > To: Mcnamara, John <john.mcnamara@intel.com>
> > Cc: Horton, Remy <remy.horton@intel.com>; dev@dpdk.org; Pattan, Reshma
> > <reshma.pattan@intel.com>; Thomas Monjalon <thomas.monjalon@6wind.com>;
> > olivier.matz@6wind.com
> > Subject: Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency
> > stats
> > 
> > On Tue, Jan 17, 2017 at 11:19:24AM +0000, Mcnamara, John wrote:
> > > > -----Original Message-----
> > > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Jerin Jacob
> > > > Sent: Tuesday, January 17, 2017 4:30 AM
> > > > To: Horton, Remy <remy.horton@intel.com>
> > > > Cc: dev@dpdk.org; Pattan, Reshma <reshma.pattan@intel.com>; Thomas
> > > > Monjalon <thomas.monjalon@6wind.com>
> > > > Subject: Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for
> > > > latency stats
> > > >
> > > > On Mon, Jan 16, 2017 at 04:19:32PM +0000, Remy Horton wrote:
> > > > > From: Reshma Pattan <reshma.pattan@intel.com>
> > > > >
> > > > > Add a library designed to calculate latency statistics and report
> > > > > them to the application when queried. The library measures
> > > > > minimum, average and maximum latencies, and jitter in nano
> > > > > seconds. The current implementation supports global latency stats,
> > > > > i.e. per application
> > > > stats.
> > > > >
> > > > > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
> > > > > Signed-off-by: Remy Horton <remy.horton@intel.com>
> > > > > ---
> > > > >  MAINTAINERS                                        |   4 +
> > > > >  config/common_base                                 |   5 +
> > > > >  doc/api/doxy-api-index.md                          |   1 +
> > > > >  doc/api/doxy-api.conf                              |   1 +
> > > > >  doc/guides/rel_notes/release_17_02.rst             |   5 +
> > > > >  lib/Makefile                                       |   1 +
> > > > >  lib/librte_latencystats/Makefile                   |  57 +++
> > > > >  lib/librte_latencystats/rte_latencystats.c         | 389
> > > > +++++++++++++++++++++
> > > > >  lib/librte_latencystats/rte_latencystats.h         | 146 ++++++++
> > > > >  .../rte_latencystats_version.map                   |  10 +
> > > > >  lib/librte_mbuf/rte_mbuf.h                         |   3 +
> > > >
> > > > It is a value added feature for DPDK. But what is the plan for
> > > > incorporating the mbuf change? I have 8 month old mbuf change for
> > > > ARM for natural alignment. If we are accepting any mbuf change then
> > > > we need to include outstanding mbuf changes to avoid future ABI
> > breakage.
> > > >
> > > > http://dpdk.org/dev/patchwork/patch/12878/
> > > >
> > >
> > > Hi Jerin,
> > 
> > Hi John,
> > 
> > >
> > > As far as I know the plan was to reach some sort of consensus on the
> > > mbuf structure at the DPDK Userspace 2016, during and after Olivier's
> > > presentation and then to make those changes during 17.02.
> > >
> > > However, I believe Olivier had other work commitments in this release
> > > and wasn't able to work on the mbuf changes.
> > >
> > > The above mbuf change (and addition at the end of the struct) should
> > > have gone into that mbuf rework, along with your changes.
> > >
> > > However, since the mbuf rework didn't happen we need to add the field
> > > in this release.
> > 
> > So we don't care the mbuf ABI breakage in the next release. This wasn't
> > the message I got earlier for ARM's mbuf change.
> > 
> > http://dpdk.org/dev/patchwork/patch/12878/
> 
> 
> Hi Jerin,
> 
> We do care about ABI breakage but I was under the impression that the
> timestamp change wasn't breaking the ABI since it was at the end of the
> struct. I also ran the ABI validator against the change and it didn't show any
> breakage.
> 
> http://dpdk.org/doc/guides/contributing/versioning.html#running-the-abi-validator
> 
> The rearm_data alignment patch, on the other hand, does break ABI. I think
> that is the main difference between the two patches.
> 
> If the timestamp change does break ABI then it should also wait until the mbuf
> restructuring.

I agree on ABI part.

If understand it correctly, Oliver would like to group all the mbuf modification
in one version and postponed the rearm_data change.

Here is the email
---------------------------------------------------------
Changing the mbuf topology is something that should happen as rarely as
possible, so I think we should group all mbuf modifications in one
version.

Your issue (mbuf->rearm alignment), the removing of uneeded fields (port
id, maybe nb_segs), and possibly other things should be addressed for
next version (16.11). I'll send a deprecation notice before the 16.07 is
out if there is no opposition.
---------------------------------------------------------

> 
> 
> > ...
> > 
> > There is nothing against you or this feature. The only part concerns me
> > that some set of patches can always override any rule and include in the
> > release (even as marking as EXPERIMENTAL) because of its important for
> > some set of consumers.
> > Another set has to wait in the queue because its not important for some
> > people.
> > For me, it is not a sign of vendor neutral open source project.
> 
> To be fair I don't think we are trying to override any rule here. 
> 
> Also, we aren't the only vendor looking for a timestamp in the mbuf.
> Mellanox also submitted a patch:
> 
>     http://dpdk.org/ml/archives/dev/2016-October/048809.html

We don't have any issue in adding timestamp in mbuf either.
The point, I was trying to make some changes like rearm_data only need for
ARM architecture.In those cases, postponing the changes due to some other
non direct dependency change is not good a specific architecture/vendor.

> 
> However, it is also fair to acknowledge that the rearm_data alignment patch
> shouldn't have had to wait so long. I can't really answer for that directly.
> My feeling is that it was targeted for the mbuf rework but got forgotten
> when that work slipped.

Oliver,

Could you please suggest how to proceed further?

> 
> John
> 
> 

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

* [PATCH v8 0/7] Expanded statistics reporting
  2017-01-16 16:19           ` [PATCH v7 0/6] " Remy Horton
                               ` (5 preceding siblings ...)
  2017-01-16 16:19             ` [PATCH v7 6/6] app/test-pmd: add latency statistics calculation Remy Horton
@ 2017-01-17 23:24             ` Remy Horton
  2017-01-17 23:24               ` [PATCH v8 1/7] lib: add information metrics library Remy Horton
                                 ` (7 more replies)
  6 siblings, 8 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patchset extends statistics reporting to include peak and
average data-rate metrics. It comes in two parts: a statistics
reporting library, and a bitrate calculation library that uses
it. This structure is intended to seperate statistic reporting
from ethdev and allow more flexible metric registration.

--

v8 changes:
* Release notes correction
* Updated copyright years
* rte_metric_init() takes socket id & must be explicitly called
* rte_metrics_reg_metric renamed to rte_metrics_reg_name()
* rte_metrics_update_metric() renamed to rte_metrics_update_value()
* Doxygen updates
* Changed malloc()/free() to rte_malloc()/rte_free()
* Removed redundant memset()
* rte_stats_bitrates_s renamed to rte_stats_bitrates_s
* Split mbuf change to own patch for visibility
* CYCLES_PER_NS now a static inline function
* latency: "hidden" pthread creation now has polling API instead.
* Struct declarations and variable definitions cleaned up
* Double initialization of the latency library now returns -EEXIST
* MAINTAINERS entry for layenctstats in correct section

v7 changes:
* RTE_METRICS_NONPORT renamed to RTE_METRICS_GLOBAL
* Multiple changes to rte_metrics.h doxygen documentation
* Split apart latency patch into lib, test-pmd, & proc_info parts
* Reordered patches by functionality
* Insufficent capacity return value changed from -ERANGE to actual size
* Cache alignment in bitrate library
* Tightened up const usage to avoid STATIC_CONST_CHAR_ARRAY warning
* Reshma reinstated as author for (now split) latency patch
* Rebase to master

v6 changes:
* Metrics display now has "Non port specific" rather than "port -1"
* Fixed sign issue in EWMA delta calculation
* Rebased to master

v5 changes:
* Updated Shared Library Versions in release notes
* Merged in Reshma's latencystats library

v4 changes:
* References to 16.11 changed to 17.02
* Fetching of non-port values was broken
* Added sanity checks to value fetching
* rte_stat_value renamed to rte_metric_value
* Corrected doxygen descriptions
* Added MAINTAINERS entries
* Added #ifdef directives to bitrate code in test-pmd

v3 changes:
* Marked rte_stats_bitrate_s as internal
* Minor integer roundoff correction
* Coding style corrections
* Removed spurious object allocation
* Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3.
* Reintroduced non-port values (RTE_METRICS_NONPORT)
* Added spinlocks to metric library
* Removed spurious test registration/update
* Added release notes entries

v2 changes:
* Uses a new metrics library rather than being part of ethdev


Harry van Haaren (3):
  mbuf: add a timestamp to the mbuf for latencystats
  lib: added new library for latency stats
  app/test-pmd: add latency statistics calculation

Remy Horton (3):
  lib: add information metrics library
  lib: add bitrate statistics library
  app/test-pmd: add bitrate statistics calculation

Reshma Pattan (1):
  app/proc_info: add metrics displaying

 MAINTAINERS                                        |  12 +
 app/proc_info/main.c                               |  74 ++++-
 app/test-pmd/parameters.c                          |  20 +-
 app/test-pmd/testpmd.c                             |  75 ++++-
 app/test-pmd/testpmd.h                             |   6 +-
 config/common_base                                 |  15 +
 doc/api/doxy-api-index.md                          |   3 +
 doc/api/doxy-api.conf                              |   3 +
 doc/guides/rel_notes/release_17_02.rst             |  18 +
 lib/Makefile                                       |   3 +
 lib/librte_bitratestats/Makefile                   |  53 +++
 lib/librte_bitratestats/rte_bitrate.c              | 132 ++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++
 .../rte_bitratestats_version.map                   |   9 +
 lib/librte_latencystats/Makefile                   |  56 ++++
 lib/librte_latencystats/rte_latencystats.c         | 366 +++++++++++++++++++++
 lib/librte_latencystats/rte_latencystats.h         | 154 +++++++++
 .../rte_latencystats_version.map                   |  10 +
 lib/librte_mbuf/rte_mbuf.h                         |   3 +
 lib/librte_metrics/Makefile                        |  51 +++
 lib/librte_metrics/rte_metrics.c                   | 308 +++++++++++++++++
 lib/librte_metrics/rte_metrics.h                   | 231 +++++++++++++
 lib/librte_metrics/rte_metrics_version.map         |  13 +
 mk/rte.app.mk                                      |   3 +
 24 files changed, 1694 insertions(+), 4 deletions(-)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map
 create mode 100644 lib/librte_latencystats/Makefile
 create mode 100644 lib/librte_latencystats/rte_latencystats.c
 create mode 100644 lib/librte_latencystats/rte_latencystats.h
 create mode 100644 lib/librte_latencystats/rte_latencystats_version.map
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

-- 
2.5.5

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

* [PATCH v8 1/7] lib: add information metrics library
  2017-01-17 23:24             ` [PATCH v8 0/7] Expanded statistics reporting Remy Horton
@ 2017-01-17 23:24               ` Remy Horton
  2017-01-17 23:24               ` [PATCH v8 2/7] app/proc_info: add metrics displaying Remy Horton
                                 ` (6 subsequent siblings)
  7 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patch adds a new information metric library that allows other
modules to register named metrics and update their values. It is
intended to be independent of ethdev, rather than mixing ethdev
and non-ethdev information in xstats.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                |   4 +
 config/common_base                         |   5 +
 doc/api/doxy-api-index.md                  |   1 +
 doc/api/doxy-api.conf                      |   1 +
 doc/guides/rel_notes/release_17_02.rst     |   8 +
 lib/Makefile                               |   1 +
 lib/librte_metrics/Makefile                |  51 +++++
 lib/librte_metrics/rte_metrics.c           | 308 +++++++++++++++++++++++++++++
 lib/librte_metrics/rte_metrics.h           | 231 ++++++++++++++++++++++
 lib/librte_metrics/rte_metrics_version.map |  13 ++
 mk/rte.app.mk                              |   2 +
 11 files changed, 625 insertions(+)
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 9645c9b..95836a2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -596,6 +596,10 @@ F: lib/librte_jobstats/
 F: examples/l2fwd-jobstats/
 F: doc/guides/sample_app_ug/l2_forward_job_stats.rst
 
+Metrics
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_metrics/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index 8e9dcfa..0eb3866 100644
--- a/config/common_base
+++ b/config/common_base
@@ -593,3 +593,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
 CONFIG_RTE_TEST_PMD=y
 CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
 CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+
+#
+# Compile the device metrics library
+#
+CONFIG_RTE_LIBRTE_METRICS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 72d59b2..94f0f69 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -150,4 +150,5 @@ There are many libraries, so their headers may be grouped by topics:
   [common]             (@ref rte_common.h),
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
+  [Device Metrics]     (@ref rte_metrics.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index b340fcf..194b670 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -50,6 +50,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_mbuf \
                           lib/librte_mempool \
                           lib/librte_meter \
+                          lib/librte_metrics \
                           lib/librte_net \
                           lib/librte_pdump \
                           lib/librte_pipeline \
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index d445d64..4fca29b 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -34,6 +34,12 @@ New Features
 
      Refer to the previous release notes for examples.
 
+   * **Added information metric library.**
+
+     A library that allows information metrics to be added and update. It is
+     intended to provide a reporting mechanism that is independent of the
+     ethdev library.
+
      This section is a comment. do not overwrite or remove it.
      Also, make sure to start the actual text at the margin.
      =========================================================
@@ -161,6 +167,7 @@ The libraries prepended with a plus sign were incremented in this version.
 .. code-block:: diff
 
      librte_acl.so.2
+   + librte_bitratestats.so.1
      librte_cfgfile.so.2
      librte_cmdline.so.2
      librte_cryptodev.so.2
@@ -176,6 +183,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_mbuf.so.2
      librte_mempool.so.2
      librte_meter.so.1
+   + librte_metrics.so.1
      librte_net.so.1
      librte_pdump.so.1
      librte_pipeline.so.3
diff --git a/lib/Makefile b/lib/Makefile
index 990f23a..5d85dcf 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table
 DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
+DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile
new file mode 100644
index 0000000..8d6e23a
--- /dev/null
+++ b/lib/librte_metrics/Makefile
@@ -0,0 +1,51 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_metrics.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_metrics_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c
new file mode 100644
index 0000000..5a67c85
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.c
@@ -0,0 +1,308 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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 <string.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_lcore.h>
+#include <rte_memzone.h>
+#include <rte_spinlock.h>
+
+#define RTE_METRICS_MAX_METRICS 256
+#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS"
+
+/**
+ * Internal stats metadata and value entry.
+ *
+ * @internal
+ * @param name
+ *   Name of metric
+ * @param value
+ *   Current value for metric
+ * @param idx_next_set
+ *   Index of next root element (zero for none)
+ * @param idx_next_metric
+ *   Index of next metric in set (zero for none)
+ *
+ * Only the root of each set needs idx_next_set but since it has to be
+ * assumed that number of sets could equal total number of metrics,
+ * having a separate set metadata table doesn't save any memory.
+ */
+struct rte_metrics_meta_s {
+	char name[RTE_METRICS_MAX_NAME_LEN];
+	uint64_t value[RTE_MAX_ETHPORTS];
+	uint64_t nonport_value;
+	uint16_t idx_next_set;
+	uint16_t idx_next_stat;
+};
+
+/**
+ * Internal stats info structure.
+ *
+ * @internal
+ * @param idx_last_set
+ *   Index of last metadata entry with valid data. This value is
+ *   not valid if cnt_stats is zero.
+ * @param cnt_stats
+ *   Number of metrics.
+ * @param metadata
+ *   Stat data memory block.
+ *
+ * Offsets into metadata are used instead of pointers because ASLR
+ * means that having the same physical addresses in different
+ * processes is not guaranteed.
+ */
+struct rte_metrics_data_s {
+	uint16_t idx_last_set;
+	uint16_t cnt_stats;
+	struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS];
+	rte_spinlock_t lock;
+};
+
+void
+rte_metrics_init(int socket_id)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone != NULL)
+		return;
+	memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME,
+		sizeof(struct rte_metrics_data_s), socket_id, 0);
+	if (memzone == NULL)
+		rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
+	stats = memzone->addr;
+	memset(stats, 0, sizeof(struct rte_metrics_data_s));
+	rte_spinlock_init(&stats->lock);
+}
+
+int
+rte_metrics_reg_name(const char *name)
+{
+	const char * const list_names[] = {name};
+
+	return rte_metrics_reg_names(list_names, 1);
+}
+
+int
+rte_metrics_reg_names(const char * const *names, uint16_t cnt_names)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	uint16_t idx_base;
+
+	/* Some sanity checks */
+	if (cnt_names < 1 || names == NULL)
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS)
+		return -ENOMEM;
+
+	rte_spinlock_lock(&stats->lock);
+
+	/* Overwritten later if this is actually first set.. */
+	stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats;
+
+	stats->idx_last_set = idx_base = stats->cnt_stats;
+
+	for (idx_name = 0; idx_name < cnt_names; idx_name++) {
+		entry = &stats->metadata[idx_name + stats->cnt_stats];
+		strncpy(entry->name, names[idx_name],
+			RTE_METRICS_MAX_NAME_LEN);
+		memset(entry->value, 0, sizeof(entry->value));
+		entry->idx_next_stat = idx_name + stats->cnt_stats + 1;
+	}
+	entry->idx_next_stat = 0;
+	entry->idx_next_set = 0;
+	stats->cnt_stats += cnt_names;
+
+	rte_spinlock_unlock(&stats->lock);
+
+	return idx_base;
+}
+
+int
+rte_metrics_update_value(int port_id, uint16_t key, const uint64_t value)
+{
+	return rte_metrics_update_values(port_id, key, &value, 1);
+}
+
+int
+rte_metrics_update_values(int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_metric;
+	uint16_t idx_value;
+	uint16_t cnt_setsize;
+
+	if (port_id != RTE_METRICS_GLOBAL &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	rte_spinlock_lock(&stats->lock);
+	idx_metric = key;
+	cnt_setsize = 1;
+	while (idx_metric < stats->cnt_stats) {
+		entry = &stats->metadata[idx_metric];
+		if (entry->idx_next_stat == 0)
+			break;
+		cnt_setsize++;
+		idx_metric++;
+	}
+	/* Check update does not cross set border */
+	if (count > cnt_setsize) {
+		rte_spinlock_unlock(&stats->lock);
+		return -ERANGE;
+	}
+
+	if (port_id == RTE_METRICS_GLOBAL)
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].nonport_value =
+				values[idx_value];
+		}
+	else
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].value[port_id] =
+				values[idx_value];
+		}
+	rte_spinlock_unlock(&stats->lock);
+	return 0;
+}
+
+int
+rte_metrics_get_names(struct rte_metric_name *names,
+	uint16_t capacity)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+	if (names != NULL) {
+		if (capacity < stats->cnt_stats) {
+			return_value = stats->cnt_stats;
+			rte_spinlock_unlock(&stats->lock);
+			return return_value;
+		}
+		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
+			strncpy(names[idx_name].name,
+				stats->metadata[idx_name].name,
+				RTE_METRICS_MAX_NAME_LEN);
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
+
+int
+rte_metrics_get_values(int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	if (port_id != RTE_METRICS_GLOBAL &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+
+	if (values != NULL) {
+		if (capacity < stats->cnt_stats) {
+			return_value = stats->cnt_stats;
+			rte_spinlock_unlock(&stats->lock);
+			return return_value;
+		}
+		if (port_id == RTE_METRICS_GLOBAL)
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->nonport_value;
+			}
+		else
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->value[port_id];
+			}
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
new file mode 100644
index 0000000..871a8f9
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.h
@@ -0,0 +1,231 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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.
+ */
+
+/**
+ * @file
+ *
+ * RTE Metrics module
+ *
+ * Metric information is populated using a push model, where the
+ * information provider calls an update function on the relevant
+ * metrics. Currently only bulk querying of metrics is supported.
+ */
+
+#ifndef _RTE_METRICS_H_
+#define _RTE_METRICS_H_
+
+/** Maximum length of metric name (including null-terminator) */
+#define RTE_METRICS_MAX_NAME_LEN 64
+
+/**
+ * Global (rather than port-specific) metric.
+ *
+ * When used instead of port number by rte_metrics_update_metric()
+ * or rte_metrics_update_metric(), the global metrics, which are
+ * not associated with any specific port, are updated.
+ */
+#define RTE_METRICS_GLOBAL -1
+
+
+/**
+ * A name-key lookup for metrics.
+ *
+ * An array of this structure is returned by rte_metrics_get_names().
+ * The struct rte_eth_stats references these names via their array index.
+ */
+struct rte_metric_name {
+	/** String describing metric */
+	char name[RTE_METRICS_MAX_NAME_LEN];
+};
+
+
+/**
+ * Metric value structure.
+ *
+ * This structure is used by rte_metrics_get_values() to return metrics,
+ * which are statistics that are not generated by PMDs. It maps a name key,
+ * which corresponds to an index in the array returned by
+ * rte_metrics_get_names().
+ */
+struct rte_metric_value {
+	/** Numeric identifier of metric. */
+	uint16_t key;
+	/** Value for metric */
+	uint64_t value;
+};
+
+
+/**
+ * Initializes metric module. This function must be called from
+ * a primary process before metrics are used.
+ *
+ * @param socket_id
+ *   Socket to use for shared memory allocation.
+ */
+void rte_metrics_init(int socket_id);
+
+/**
+ * Register a metric, making it available as a reporting parameter.
+ *
+ * Registering a metric is the way third-parties declare a parameter
+ * that they wish to be reported. Once registered, the associated
+ * numeric key can be obtained via rte_metrics_get_names(), which
+ * is required for updating said metric's value.
+ *
+ * @param name
+ *   Metric name
+ *
+ * @return
+ *  - Zero or positive: Success (index key of new metric)
+ *  - \b -EIO: Error, unable to access metrics shared memory
+ *    (rte_metrics_init() not called)
+ *  - \b -EINVAL: Error, invalid parameters
+ *  - \b -ENOMEM: Error, maximum metrics reached
+ */
+int rte_metrics_reg_name(const char *name);
+
+/**
+ * Register a set of metrics.
+ *
+ * This is a bulk version of rte_metrics_reg_metrics() and aside from
+ * handling multiple keys at once is functionally identical.
+ *
+ * @param names
+ *   List of metric names
+ *
+ * @param cnt_names
+ *   Number of metrics in set
+ *
+ * @return
+ *  - Zero or positive: Success (index key of start of set)
+ *  - \b -EIO: Error, unable to access metrics shared memory
+ *    (rte_metrics_init() not called)
+ *  - \b -EINVAL: Error, invalid parameters
+ *  - \b -ENOMEM: Error, maximum metrics reached
+ */
+int rte_metrics_reg_names(const char * const *names, uint16_t cnt_names);
+
+/**
+ * Get metric name-key lookup table.
+ *
+ * @param names
+ *   A struct rte_metric_name array of at least *capacity* in size to
+ *   receive key names. If this is NULL, function returns the required
+ *   number of elements for this array.
+ *
+ * @param capacity
+ *   Size (number of elements) of struct rte_metric_name array.
+ *   Disregarded if names is NULL.
+ *
+ * @return
+ *   - Positive value above capacity: error, *names* is too small.
+ *     Return value is required size.
+ *   - Positive value equal or less than capacity: Success. Return
+ *     value is number of elements filled in.
+ *   - Negative value: error.
+ */
+int rte_metrics_get_names(
+	struct rte_metric_name *names,
+	uint16_t capacity);
+
+/**
+ * Get metric value table.
+ *
+ * @param port_id
+ *   Port id to query
+ *
+ * @param values
+ *   A struct rte_metric_value array of at least *capacity* in size to
+ *   receive metric ids and values. If this is NULL, function returns
+ *   the required number of elements for this array.
+ *
+ * @param capacity
+ *   Size (number of elements) of struct rte_metric_value array.
+ *   Disregarded if names is NULL.
+ *
+ * @return
+ *   - Positive value above capacity: error, *values* is too small.
+ *     Return value is required size.
+ *   - Positive value equal or less than capacity: Success. Return
+ *     value is number of elements filled in.
+ *   - Negative value: error.
+ */
+int rte_metrics_get_values(
+	int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity);
+
+/**
+ * Updates a metric
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Id of metric to update
+ * @param value
+ *   New value
+ *
+ * @return
+ *   - -EIO if unable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_value(
+	int port_id,
+	uint16_t key,
+	const uint64_t value);
+
+/**
+ * Updates a metric set. Note that it is an error to try to
+ * update across a set boundary.
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Base id of metrics set to update
+ * @param values
+ *   Set of new values
+ * @param count
+ *   Number of new values
+ *
+ * @return
+ *   - -ERANGE if count exceeds metric set size
+ *   - -EIO if upable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_values(
+	int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count);
+
+#endif
diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map
new file mode 100644
index 0000000..f904814
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics_version.map
@@ -0,0 +1,13 @@
+DPDK_17.02 {
+	global:
+
+	rte_metrics_get_names;
+	rte_metrics_get_values;
+	rte_metrics_init;
+	rte_metrics_reg_metric;
+	rte_metrics_reg_metrics;
+	rte_metrics_update_metric;
+	rte_metrics_update_metrics;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index f75f0e2..40fcf33 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -98,6 +98,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING)           += -lrte_ring
 _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
+_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* [PATCH v8 2/7] app/proc_info: add metrics displaying
  2017-01-17 23:24             ` [PATCH v8 0/7] Expanded statistics reporting Remy Horton
  2017-01-17 23:24               ` [PATCH v8 1/7] lib: add information metrics library Remy Horton
@ 2017-01-17 23:24               ` Remy Horton
  2017-01-17 23:24               ` [PATCH v8 3/7] lib: add bitrate statistics library Remy Horton
                                 ` (5 subsequent siblings)
  7 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw)
  To: dev; +Cc: Reshma Pattan, Thomas Monjalon

From: Reshma Pattan <reshma.pattan@intel.com>

Modify the dpdk-procinfo process to display the newly added metrics.
Added new command line option "--metrics" to display metrics.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/proc_info/main.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 73 insertions(+), 1 deletion(-)

diff --git a/app/proc_info/main.c b/app/proc_info/main.c
index 2c56d10..64fa2d3 100644
--- a/app/proc_info/main.c
+++ b/app/proc_info/main.c
@@ -1,7 +1,7 @@
 /*
  *   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
@@ -57,6 +57,7 @@
 #include <rte_atomic.h>
 #include <rte_branch_prediction.h>
 #include <rte_string_fns.h>
+#include <rte_metrics.h>
 
 /* Maximum long option length for option parsing. */
 #define MAX_LONG_OPT_SZ 64
@@ -68,6 +69,8 @@ static uint32_t enabled_port_mask;
 static uint32_t enable_stats;
 /**< Enable xstats. */
 static uint32_t enable_xstats;
+/**< Enable metrics. */
+static uint32_t enable_metrics;
 /**< Enable stats reset. */
 static uint32_t reset_stats;
 /**< Enable xstats reset. */
@@ -85,6 +88,8 @@ proc_info_usage(const char *prgname)
 		"  --stats: to display port statistics, enabled by default\n"
 		"  --xstats: to display extended port statistics, disabled by "
 			"default\n"
+		"  --metrics: to display derived metrics of the ports, disabled by "
+			"default\n"
 		"  --stats-reset: to reset port statistics\n"
 		"  --xstats-reset: to reset port extended statistics\n",
 		prgname);
@@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv)
 		{"stats", 0, NULL, 0},
 		{"stats-reset", 0, NULL, 0},
 		{"xstats", 0, NULL, 0},
+		{"metrics", 0, NULL, 0},
 		{"xstats-reset", 0, NULL, 0},
 		{NULL, 0, 0, 0}
 	};
@@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv)
 			else if (!strncmp(long_option[option_index].name, "xstats",
 					MAX_LONG_OPT_SZ))
 				enable_xstats = 1;
+			else if (!strncmp(long_option[option_index].name,
+					"metrics",
+					MAX_LONG_OPT_SZ))
+				enable_metrics = 1;
 			/* Reset stats */
 			if (!strncmp(long_option[option_index].name, "stats-reset",
 					MAX_LONG_OPT_SZ))
@@ -301,6 +311,62 @@ nic_xstats_clear(uint8_t port_id)
 	printf("\n  NIC extended statistics for port %d cleared\n", port_id);
 }
 
+static void
+metrics_display(int port_id)
+{
+	struct rte_metric_value *metrics;
+	struct rte_metric_name *names;
+	int len, ret;
+	static const char *nic_stats_border = "########################";
+
+	len = rte_metrics_get_names(NULL, 0);
+	if (len < 0) {
+		printf("Cannot get metrics count\n");
+		return;
+	}
+
+	metrics = rte_malloc(NULL, sizeof(struct rte_metric_value) * len, 0);
+	if (metrics == NULL) {
+		printf("Cannot allocate memory for metrics\n");
+		return;
+	}
+
+	names =  rte_malloc(NULL, sizeof(struct rte_metric_name) * len, 0);
+	if (names == NULL) {
+		printf("Cannot allocate memory for metrcis names\n");
+		rte_free(metrics);
+		return;
+	}
+
+	if (len != rte_metrics_get_names(names, len)) {
+		printf("Cannot get metrics names\n");
+		rte_free(metrics);
+		rte_free(names);
+		return;
+	}
+
+	if (port_id == RTE_METRICS_GLOBAL)
+		printf("###### Non port specific metrics  #########\n");
+	else
+		printf("###### metrics for port %-2d #########\n", port_id);
+	printf("%s############################\n", nic_stats_border);
+	ret = rte_metrics_get_values(port_id, metrics, len);
+	if (ret < 0 || ret > len) {
+		printf("Cannot get metrics values\n");
+		rte_free(metrics);
+		rte_free(names);
+		return;
+	}
+
+	int i;
+	for (i = 0; i < len; i++)
+		printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value);
+
+	printf("%s############################\n", nic_stats_border);
+	rte_free(metrics);
+	rte_free(names);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -360,8 +426,14 @@ main(int argc, char **argv)
 				nic_stats_clear(i);
 			else if (reset_xstats)
 				nic_xstats_clear(i);
+			else if (enable_metrics)
+				metrics_display(i);
 		}
 	}
 
+	/* print port independent stats */
+	if (enable_metrics)
+		metrics_display(RTE_METRICS_GLOBAL);
+
 	return 0;
 }
-- 
2.5.5

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

* [PATCH v8 3/7] lib: add bitrate statistics library
  2017-01-17 23:24             ` [PATCH v8 0/7] Expanded statistics reporting Remy Horton
  2017-01-17 23:24               ` [PATCH v8 1/7] lib: add information metrics library Remy Horton
  2017-01-17 23:24               ` [PATCH v8 2/7] app/proc_info: add metrics displaying Remy Horton
@ 2017-01-17 23:24               ` Remy Horton
  2017-01-17 23:24               ` [PATCH v8 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton
                                 ` (4 subsequent siblings)
  7 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patch adds a library that calculates peak and average data-rate
statistics. For ethernet devices. These statistics are reported using
the metrics library.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                        |   4 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/rel_notes/release_17_02.rst             |   5 +
 lib/Makefile                                       |   1 +
 lib/librte_bitratestats/Makefile                   |  53 +++++++++
 lib/librte_bitratestats/rte_bitrate.c              | 132 +++++++++++++++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++++++++++
 .../rte_bitratestats_version.map                   |   9 ++
 mk/rte.app.mk                                      |   1 +
 11 files changed, 292 insertions(+)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 95836a2..d9423cb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -600,6 +600,10 @@ Metrics
 M: Remy Horton <remy.horton@intel.com>
 F: lib/librte_metrics/
 
+Bit-rate statistica
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_bitratestats/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index 0eb3866..decebe5 100644
--- a/config/common_base
+++ b/config/common_base
@@ -598,3 +598,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
 # Compile the device metrics library
 #
 CONFIG_RTE_LIBRTE_METRICS=y
+
+#
+# Compile the bitrate statistics library
+#
+CONFIG_RTE_LIBRTE_BITRATE=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 94f0f69..5e194b0 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -151,4 +151,5 @@ There are many libraries, so their headers may be grouped by topics:
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
   [Device Metrics]     (@ref rte_metrics.h),
+  [Bitrate Statistics] (@ref rte_bitrate.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index 194b670..6e6ab5c 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -35,6 +35,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_eal/common/include \
                           lib/librte_eal/common/include/generic \
                           lib/librte_acl \
+                          lib/librte_bitratestats \
                           lib/librte_cfgfile \
                           lib/librte_cmdline \
                           lib/librte_compat \
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 4fca29b..44012c8 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -40,6 +40,11 @@ New Features
      intended to provide a reporting mechanism that is independent of the
      ethdev library.
 
+   * **Added bit-rate calculation library.**
+
+     A library that can be used to calculate device bit-rates. Calculated
+     bitrates are reported using the metrics library.
+
      This section is a comment. do not overwrite or remove it.
      Also, make sure to start the actual text at the margin.
      =========================================================
diff --git a/lib/Makefile b/lib/Makefile
index 5d85dcf..e211bc0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
+DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile
new file mode 100644
index 0000000..743b62c
--- /dev/null
+++ b/lib/librte_bitratestats/Makefile
@@ -0,0 +1,53 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016-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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_bitratestats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_bitratestats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c
new file mode 100644
index 0000000..2c20272
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.c
@@ -0,0 +1,132 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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 <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
+
+/*
+ * Persistent bit-rate data.
+ * @internal
+ */
+struct rte_stats_bitrate {
+	uint64_t last_ibytes;
+	uint64_t last_obytes;
+	uint64_t peak_ibits;
+	uint64_t peak_obits;
+	uint64_t ewma_ibits;
+	uint64_t ewma_obits;
+};
+
+struct rte_stats_bitrates {
+	struct rte_stats_bitrate port_stats[RTE_MAX_ETHPORTS];
+	uint16_t id_stats_set;
+};
+
+struct rte_stats_bitrates *
+rte_stats_bitrate_create(void)
+{
+	return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates),
+		RTE_CACHE_LINE_SIZE);
+}
+
+int
+rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data)
+{
+	const char * const names[] = {
+		"mean_bits_in", "mean_bits_out",
+		"peak_bits_in", "peak_bits_out",
+	};
+	int return_value;
+
+	return_value = rte_metrics_reg_names(&names[0], 4);
+	if (return_value >= 0)
+		bitrate_data->id_stats_set = return_value;
+	return return_value;
+}
+
+int
+rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data,
+	uint8_t port_id)
+{
+	struct rte_stats_bitrate *port_data;
+	struct rte_eth_stats eth_stats;
+	int ret_code;
+	uint64_t cnt_bits;
+	int64_t delta;
+	const int64_t alpha_percent = 20;
+	uint64_t values[4];
+
+	ret_code = rte_eth_stats_get(port_id, &eth_stats);
+	if (ret_code != 0)
+		return ret_code;
+
+	port_data = &bitrate_data->port_stats[port_id];
+
+	/* Incoming bitrate. This is an iteratively calculated EWMA
+	 * (Expomentially Weighted Moving Average) that uses a
+	 * weighting factor of alpha_percent.
+	 */
+	cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3;
+	port_data->last_ibytes = eth_stats.ibytes;
+	if (cnt_bits > port_data->peak_ibits)
+		port_data->peak_ibits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_ibits;
+	/* The +-50 fixes integer rounding during divison */
+	if (delta > 0)
+		delta = (delta * alpha_percent + 50) / 100;
+	else
+		delta = (delta * alpha_percent - 50) / 100;
+	port_data->ewma_ibits += delta;
+
+	/* Outgoing bitrate (also EWMA) */
+	cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3;
+	port_data->last_obytes = eth_stats.obytes;
+	if (cnt_bits > port_data->peak_obits)
+		port_data->peak_obits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_obits;
+	delta = (delta * alpha_percent + 50) / 100;
+	port_data->ewma_obits += delta;
+
+	values[0] = port_data->ewma_ibits;
+	values[1] = port_data->ewma_obits;
+	values[2] = port_data->peak_ibits;
+	values[3] = port_data->peak_obits;
+	rte_metrics_update_values(port_id, bitrate_data->id_stats_set,
+		values, 4);
+	return 0;
+}
diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h
new file mode 100644
index 0000000..564e4f7
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.h
@@ -0,0 +1,80 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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.
+ */
+
+
+/**
+ *  Bitrate statistics data structure.
+ *  This data structure is intentionally opaque.
+ */
+struct rte_stats_bitrates;
+
+
+/**
+ * Allocate a bitrate statistics structure
+ *
+ * @return
+ *   - Pointer to structure on success
+ *   - NULL on error (zmalloc failure)
+ */
+struct rte_stats_bitrates *rte_stats_bitrate_create(void);
+
+
+/**
+ * Register bitrate statistics with the metric library.
+ *
+ * @param bitrate_data
+ *   Pointer allocated by rte_stats_create()
+ *
+ * @return
+ *   Zero on success
+ *   Negative on error
+ */
+int rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data);
+
+
+/**
+ * Calculate statistics for current time window. The period with which
+ * this function is called should be the intended sampling window width.
+ *
+ * @param bitrate_data
+ *   Bitrate statistics data pointer
+ *
+ * @param port_id
+ *   Port id to calculate statistics for
+ *
+ * @return
+ *  - Zero on success
+ *  - Negative value on error
+ */
+int rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data,
+	uint8_t port_id);
diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map
new file mode 100644
index 0000000..66f232f
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitratestats_version.map
@@ -0,0 +1,9 @@
+DPDK_17.02 {
+	global:
+
+	rte_stats_bitrate_calc;
+	rte_stats_bitrate_create;
+	rte_stats_bitrate_reg;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 40fcf33..6aac5ac 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -99,6 +99,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
 
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
-- 
2.5.5

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

* [PATCH v8 4/7] app/test-pmd: add bitrate statistics calculation
  2017-01-17 23:24             ` [PATCH v8 0/7] Expanded statistics reporting Remy Horton
                                 ` (2 preceding siblings ...)
  2017-01-17 23:24               ` [PATCH v8 3/7] lib: add bitrate statistics library Remy Horton
@ 2017-01-17 23:24               ` Remy Horton
  2017-01-17 23:24               ` [PATCH v8 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton
                                 ` (3 subsequent siblings)
  7 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

Calculate bitrate statistics using the bitrate stats library. The
resulting statistics can be viewed via proc_info.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/testpmd.c | 38 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index bfb2f8e..de60c09 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -1,7 +1,7 @@
 /*-
  *   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
@@ -79,6 +79,10 @@
 #include <rte_pdump.h>
 #endif
 #include <rte_flow.h>
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_BITRATE
+#include <rte_bitrate.h>
+#endif
 
 #include "testpmd.h"
 
@@ -323,6 +327,9 @@ uint16_t nb_rx_queue_stats_mappings = 0;
 
 unsigned max_socket = 0;
 
+/* Bitrate statistics */
+struct rte_stats_bitrates *bitrate_data;
+
 /* Forward function declarations */
 static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -922,12 +929,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
 	struct fwd_stream **fsm;
 	streamid_t nb_fs;
 	streamid_t sm_id;
+#ifdef RTE_LIBRTE_BITRATE
+	uint64_t tics_per_1sec;
+	uint64_t tics_datum;
+	uint64_t tics_current;
+	uint8_t idx_port, cnt_ports;
+#endif
 
+#ifdef RTE_LIBRTE_BITRATE
+	cnt_ports = rte_eth_dev_count();
+	tics_datum = rte_rdtsc();
+	tics_per_1sec = rte_get_timer_hz();
+#endif
 	fsm = &fwd_streams[fc->stream_idx];
 	nb_fs = fc->stream_nb;
 	do {
 		for (sm_id = 0; sm_id < nb_fs; sm_id++)
 			(*pkt_fwd)(fsm[sm_id]);
+#ifdef RTE_LIBRTE_BITRATE
+		tics_current = rte_rdtsc();
+		if (tics_current - tics_datum >= tics_per_1sec) {
+			/* Periodic bitrate calculation */
+			for (idx_port = 0; idx_port < cnt_ports; idx_port++)
+				rte_stats_bitrate_calc(bitrate_data, idx_port);
+			tics_datum = tics_current;
+		}
+#endif
 	} while (! fc->stopped);
 }
 
@@ -2139,6 +2166,15 @@ main(int argc, char** argv)
 	FOREACH_PORT(port_id, ports)
 		rte_eth_promiscuous_enable(port_id);
 
+	/* Setup bitrate stats */
+#ifdef RTE_LIBRTE_BITRATE
+	bitrate_data = rte_stats_bitrate_create();
+	if (bitrate_data == NULL)
+		rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n");
+	rte_stats_bitrate_reg(bitrate_data);
+#endif
+
+
 #ifdef RTE_LIBRTE_CMDLINE
 	if (interactive == 1) {
 		if (auto_start) {
-- 
2.5.5

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

* [PATCH v8 5/7] mbuf: add a timestamp to the mbuf for latencystats
  2017-01-17 23:24             ` [PATCH v8 0/7] Expanded statistics reporting Remy Horton
                                 ` (3 preceding siblings ...)
  2017-01-17 23:24               ` [PATCH v8 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton
@ 2017-01-17 23:24               ` Remy Horton
  2017-01-17 23:24               ` [PATCH v8 6/7] lib: added new library for latency stats Remy Horton
                                 ` (2 subsequent siblings)
  7 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw)
  To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan

From: Harry van Haaren <harry.van.haaren@intel.com>

This commit adds a uint64_t to the mbuf struct,
allowing collection of latency and jitter statistics
by measuring packet I/O timestamps. This change is
required by the latencystats library.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
---
 lib/librte_mbuf/rte_mbuf.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index bfce9f4..c35ba0a 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -512,6 +512,9 @@ struct rte_mbuf {
 
 	/** Timesync flags for use with IEEE1588. */
 	uint16_t timesync;
+
+	/** Timestamp for measuring latency. */
+	uint64_t timestamp;
 } __rte_cache_aligned;
 
 /**
-- 
2.5.5

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

* [PATCH v8 6/7] lib: added new library for latency stats
  2017-01-17 23:24             ` [PATCH v8 0/7] Expanded statistics reporting Remy Horton
                                 ` (4 preceding siblings ...)
  2017-01-17 23:24               ` [PATCH v8 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton
@ 2017-01-17 23:24               ` Remy Horton
  2017-01-17 23:24               ` [PATCH v8 7/7] app/test-pmd: add latency statistics calculation Remy Horton
  2017-01-18 15:05               ` [PATCH v9 0/7] Expanded statistics reporting Remy Horton
  7 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw)
  To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan

From: Harry van Haaren <harry.van.haaren@intel.com>

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
---

v7 to v8 changes:
- CYCLES_PER_NS now a static inline function
- "hidden" pthread creation now has polling API instead. The application
  must call rte_latencystats_update() to refresh the values.
- Struct declarations and variable definitions cleaned up
- Double initialization of the library now returns -EEXIST
- MAINTAINERS entry in correct section
- License year updates
---
 MAINTAINERS                                        |   4 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/rel_notes/release_17_02.rst             |   5 +
 lib/Makefile                                       |   1 +
 lib/librte_latencystats/Makefile                   |  56 ++++
 lib/librte_latencystats/rte_latencystats.c         | 366 +++++++++++++++++++++
 lib/librte_latencystats/rte_latencystats.h         | 154 +++++++++
 .../rte_latencystats_version.map                   |  10 +
 mk/rte.app.mk                                      |   2 +-
 11 files changed, 604 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_latencystats/Makefile
 create mode 100644 lib/librte_latencystats/rte_latencystats.c
 create mode 100644 lib/librte_latencystats/rte_latencystats.h
 create mode 100644 lib/librte_latencystats/rte_latencystats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index d9423cb..03f53b7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -604,6 +604,10 @@ Bit-rate statistica
 M: Remy Horton <remy.horton@intel.com>
 F: lib/librte_bitratestats/
 
+Latency Stats
+M: Reshma Pattan <reshma.pattan@intel.com>
+F: lib/librte_latencystats/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index decebe5..762a54c 100644
--- a/config/common_base
+++ b/config/common_base
@@ -603,3 +603,8 @@ CONFIG_RTE_LIBRTE_METRICS=y
 # Compile the bitrate statistics library
 #
 CONFIG_RTE_LIBRTE_BITRATE=y
+
+#
+# Compile the latency statistics library
+#
+CONFIG_RTE_LIBRTE_LATENCY_STATS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 5e194b0..1cacacc 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -152,4 +152,5 @@ There are many libraries, so their headers may be grouped by topics:
   [keepalive]          (@ref rte_keepalive.h),
   [Device Metrics]     (@ref rte_metrics.h),
   [Bitrate Statistics] (@ref rte_bitrate.h),
+  [Latency stats]      (@ref rte_latencystats.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index 6e6ab5c..0effece 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -47,6 +47,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_jobstats \
                           lib/librte_kni \
                           lib/librte_kvargs \
+                          lib/librte_latencystats \
                           lib/librte_lpm \
                           lib/librte_mbuf \
                           lib/librte_mempool \
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 44012c8..29bbd74 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -68,6 +68,10 @@ New Features
   Six new APIs have been added to the ixgbe PMD for MACsec offload support.
   The declarations for the APIs can be found in ``rte_pmd_ixgbe.h``.
 
+* **Added latency stats library.**
+
+  A library that measures packet latency. The collected statistics are jitter
+  and latency. For latency the minimum, average, and maximum is measured.
 
 Resolved Issues
 ---------------
@@ -184,6 +188,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_jobstats.so.1
      librte_kni.so.2
      librte_kvargs.so.1
+   + librte_latencystats.so.1
      librte_lpm.so.2
      librte_mbuf.so.2
      librte_mempool.so.2
diff --git a/lib/Makefile b/lib/Makefile
index e211bc0..6fffa88 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -60,6 +60,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
+DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_latencystats/Makefile b/lib/librte_latencystats/Makefile
new file mode 100644
index 0000000..fd145d3
--- /dev/null
+++ b/lib/librte_latencystats/Makefile
@@ -0,0 +1,56 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016-2017 Intel Corporation. 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_latencystats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
+LDLIBS += -lm
+LDLIBS += -lpthread
+
+EXPORT_MAP := rte_latencystats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) := rte_latencystats.c
+
+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)-include := rte_latencystats.h
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_latencystats/rte_latencystats.c b/lib/librte_latencystats/rte_latencystats.c
new file mode 100644
index 0000000..5334b8b
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats.c
@@ -0,0 +1,366 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-2017 Intel Corporation. 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 <unistd.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <math.h>
+
+#include <rte_mbuf.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_metrics.h>
+#include <rte_memzone.h>
+#include <rte_lcore.h>
+#include <rte_timer.h>
+
+#include "rte_latencystats.h"
+
+/** Nano seconds per second */
+#define NS_PER_SEC 1E9
+
+/** Clock cycles per nano second */
+static uint64_t
+latencystat_cycles_per_ns(void)
+{
+	return rte_get_timer_hz() / NS_PER_SEC;
+}
+
+/* Macros for printing using RTE_LOG */
+#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1
+
+static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats";
+static int latency_stats_index;
+static uint64_t samp_intvl;
+static uint64_t timer_tsc;
+static uint64_t prev_tsc;
+
+struct rte_latency_stats {
+	float min_latency; /**< Minimum latency in nano seconds */
+	float avg_latency; /**< Average latency in nano seconds */
+	float max_latency; /**< Maximum latency in nano seconds */
+	float jitter; /** Latency variation */
+};
+
+static struct rte_latency_stats *glob_stats;
+
+struct rxtx_cbs {
+	struct rte_eth_rxtx_callback *cb;
+};
+
+static struct rxtx_cbs rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
+static struct rxtx_cbs tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
+
+struct latency_stats_nameoff {
+	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	unsigned int offset;
+};
+
+static const struct latency_stats_nameoff lat_stats_strings[] = {
+	{"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)},
+	{"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)},
+	{"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)},
+	{"jitter_ns", offsetof(struct rte_latency_stats, jitter)},
+};
+
+#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \
+				sizeof(lat_stats_strings[0]))
+
+int32_t
+rte_latencystats_update(void)
+{
+	unsigned int i;
+	float *stats_ptr = NULL;
+	uint64_t values[NUM_LATENCY_STATS] = {0};
+	int ret;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++) {
+		stats_ptr = RTE_PTR_ADD(glob_stats,
+				lat_stats_strings[i].offset);
+		values[i] = (uint64_t)floor((*stats_ptr)/
+				latencystat_cycles_per_ns());
+	}
+
+	ret = rte_metrics_update_values(RTE_METRICS_GLOBAL,
+					latency_stats_index,
+					values, NUM_LATENCY_STATS);
+	if (ret < 0)
+		RTE_LOG(INFO, LATENCY_STATS, "Failed to push the stats\n");
+
+	return ret;
+}
+
+static void
+rte_latencystats_fill_values(struct rte_metric_value *values)
+{
+	unsigned int i;
+	float *stats_ptr = NULL;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++) {
+		stats_ptr = RTE_PTR_ADD(glob_stats,
+				lat_stats_strings[i].offset);
+		values[i].key = i;
+		values[i].value = (uint64_t)floor((*stats_ptr)/
+						latencystat_cycles_per_ns());
+	}
+}
+
+static uint16_t
+add_time_stamps(uint8_t pid __rte_unused,
+		uint16_t qid __rte_unused,
+		struct rte_mbuf **pkts,
+		uint16_t nb_pkts,
+		uint16_t max_pkts __rte_unused,
+		void *user_cb __rte_unused)
+{
+	unsigned int i;
+	uint64_t diff_tsc, now;
+
+	/*
+	 * For every sample interval,
+	 * time stamp is marked on one received packet.
+	 */
+	now = rte_rdtsc();
+	for (i = 0; i < nb_pkts; i++) {
+		diff_tsc = now - prev_tsc;
+		timer_tsc += diff_tsc;
+		if (timer_tsc >= samp_intvl) {
+			/*
+			 * TBD: Mark the timestamp only
+			 * if not already marked by the
+			 * hardware or the PMD.
+			 */
+			pkts[i]->timestamp = now;
+			timer_tsc = 0;
+		}
+		prev_tsc = now;
+		now = rte_rdtsc();
+	}
+
+	return nb_pkts;
+}
+
+static uint16_t
+calc_latency(uint8_t pid __rte_unused,
+		uint16_t qid __rte_unused,
+		struct rte_mbuf **pkts,
+		uint16_t nb_pkts,
+		void *_ __rte_unused)
+{
+	unsigned int i, cnt = 0;
+	uint64_t now;
+	float latency[nb_pkts];
+	static float prev_latency;
+	/*
+	 * Alpha represents degree of weighting decrease in EWMA,
+	 * a constant smoothing factor between 0 and 1. The value
+	 * is used below for measuring average latency.
+	 */
+	const float alpha = 0.2;
+
+	now = rte_rdtsc();
+	for (i = 0; i < nb_pkts; i++) {
+		if (pkts[i]->timestamp)
+			latency[cnt++] = now - pkts[i]->timestamp;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		/*
+		 * The jitter is calculated as statistical mean of interpacket
+		 * delay variation. The "jitter estimate" is computed by taking
+		 * the absolute values of the ipdv sequence and applying an
+		 * exponential filter with parameter 1/16 to generate the
+		 * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter,
+		 * D(i-1,i) is difference in latency of two consecutive packets
+		 * i-1 and i.
+		 * Reference: Calculated as per RFC 5481, sec 4.1,
+		 * RFC 3393 sec 4.5, RFC 1889 sec.
+		 */
+		glob_stats->jitter +=  (abs(prev_latency - latency[i])
+					- glob_stats->jitter)/16;
+		if (glob_stats->min_latency == 0)
+			glob_stats->min_latency = latency[i];
+		else if (latency[i] < glob_stats->min_latency)
+			glob_stats->min_latency = latency[i];
+		else if (latency[i] > glob_stats->max_latency)
+			glob_stats->max_latency = latency[i];
+		/*
+		 * The average latency is measured using exponential moving
+		 * average, i.e. using EWMA
+		 * https://en.wikipedia.org/wiki/Moving_average
+		 */
+		glob_stats->avg_latency +=
+			alpha * (latency[i] - glob_stats->avg_latency);
+		prev_latency = latency[i];
+	}
+
+	return nb_pkts;
+}
+
+int
+rte_latencystats_init(uint64_t app_samp_intvl,
+		rte_latency_stats_flow_type_fn user_cb)
+{
+	unsigned int i;
+	uint8_t pid;
+	uint16_t qid;
+	struct rxtx_cbs *cbs = NULL;
+	const uint8_t nb_ports = rte_eth_dev_count();
+	const char *ptr_strings[NUM_LATENCY_STATS] = {0};
+	const struct rte_memzone *mz = NULL;
+	const unsigned int flags = 0;
+
+	if (rte_memzone_lookup(MZ_RTE_LATENCY_STATS))
+		return -EEXIST;
+
+	/** Allocate stats in shared memory fo multi process support */
+	mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats),
+					rte_socket_id(), flags);
+	if (mz == NULL) {
+		RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n",
+			__func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	glob_stats = mz->addr;
+	samp_intvl = app_samp_intvl * latencystat_cycles_per_ns();
+
+	/** Register latency stats with stats library */
+	for (i = 0; i < NUM_LATENCY_STATS; i++)
+		ptr_strings[i] = lat_stats_strings[i].name;
+
+	latency_stats_index = rte_metrics_reg_names(ptr_strings,
+							NUM_LATENCY_STATS);
+	if (latency_stats_index < 0) {
+		RTE_LOG(DEBUG, LATENCY_STATS,
+			"Failed to register latency stats names\n");
+		return -1;
+	}
+
+	/** Register Rx/Tx callbacks */
+	for (pid = 0; pid < nb_ports; pid++) {
+		struct rte_eth_dev_info dev_info;
+		rte_eth_dev_info_get(pid, &dev_info);
+		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
+			cbs = &rx_cbs[pid][qid];
+			cbs->cb = rte_eth_add_first_rx_callback(pid, qid,
+					add_time_stamps, user_cb);
+			if (!cbs->cb)
+				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
+					"register Rx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
+			cbs = &tx_cbs[pid][qid];
+			cbs->cb =  rte_eth_add_tx_callback(pid, qid,
+					calc_latency, user_cb);
+			if (!cbs->cb)
+				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
+					"register Tx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+	}
+	return 0;
+}
+
+int
+rte_latencystats_uninit(void)
+{
+	uint8_t pid;
+	uint16_t qid;
+	int ret = 0;
+	struct rxtx_cbs *cbs = NULL;
+	const uint8_t nb_ports = rte_eth_dev_count();
+
+	/** De register Rx/Tx callbacks */
+	for (pid = 0; pid < nb_ports; pid++) {
+		struct rte_eth_dev_info dev_info;
+		rte_eth_dev_info_get(pid, &dev_info);
+		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
+			cbs = &rx_cbs[pid][qid];
+			ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb);
+			if (ret)
+				RTE_LOG(INFO, LATENCY_STATS, "failed to "
+					"remove Rx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
+			cbs = &tx_cbs[pid][qid];
+			ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb);
+			if (ret)
+				RTE_LOG(INFO, LATENCY_STATS, "failed to "
+					"remove Tx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+	}
+
+	return 0;
+}
+
+int
+rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size)
+{
+	unsigned int i;
+
+	if (names == NULL || size < NUM_LATENCY_STATS)
+		return NUM_LATENCY_STATS;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++)
+		snprintf(names[i].name, sizeof(names[i].name),
+				"%s", lat_stats_strings[i].name);
+
+	return NUM_LATENCY_STATS;
+}
+
+int
+rte_latencystats_get(struct rte_metric_value *values, uint16_t size)
+{
+	if (size < NUM_LATENCY_STATS || values == NULL)
+		return NUM_LATENCY_STATS;
+
+	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		const struct rte_memzone *mz;
+		mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS);
+		if (mz == NULL) {
+			RTE_LOG(ERR, LATENCY_STATS,
+				"Latency stats memzone not found\n");
+			return -ENOMEM;
+		}
+		glob_stats =  mz->addr;
+	}
+
+	/* Retrieve latency stats */
+	rte_latencystats_fill_values(values);
+
+	return NUM_LATENCY_STATS;
+}
diff --git a/lib/librte_latencystats/rte_latencystats.h b/lib/librte_latencystats/rte_latencystats.h
new file mode 100644
index 0000000..28c6dcf
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats.h
@@ -0,0 +1,154 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-2017 Intel Corporation. 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 _RTE_LATENCYSTATS_H_
+#define _RTE_LATENCYSTATS_H_
+
+/**
+ * @file
+ * RTE latency stats
+ *
+ * library to provide application and flow based latency stats.
+ */
+
+#include <rte_metrics.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  Note: This function pointer is for future flow based latency stats
+ *  implementation.
+ *
+ * Function type used for identifting flow types of a Rx packet.
+ *
+ * The callback function is called on Rx for each packet.
+ * This function is used for flow based latency calculations.
+ *
+ * @param pkt
+ *   Packet that has to be identified with its flow types.
+ * @param user_param
+ *   The arbitrary user parameter passed in by the application when
+ *   the callback was originally configured.
+ * @return
+ *   The flow_mask, representing the multiple flow types of a packet.
+ */
+typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt,
+							void *user_param);
+
+/**
+ *  Registers Rx/Tx callbacks for each active port, queue.
+ *
+ * @param samp_intvl
+ *  Sampling time period in nano seconds, at which packet
+ *  should be marked with time stamp.
+ * @param user_cb
+ *  Note: This param is for future flow based latency stats
+ *  implementation.
+ *  User callback to be called to get flow types of a packet.
+ *  Used for flow based latency calculation.
+ *  If the value is NULL, global stats will be calculated,
+ *  else flow based latency stats will be calculated.
+ *  For now just pass on the NULL value to this param.
+ *  @return
+ *   -1     : On error
+ *   -ENOMEM: On error
+ *    0     : On success
+ */
+int rte_latencystats_init(uint64_t samp_intvl,
+			rte_latency_stats_flow_type_fn user_cb);
+
+/**
+ * Calculates the latency and jitter values internally, exposing the updated
+ * values via *rte_latencystats_get* or the rte_metrics API.
+ * @return:
+ *  0      : on Success
+ *  < 0    : Error in updating values.
+ */
+int32_t rte_latencystats_update(void);
+
+/**
+ *  Removes registered Rx/Tx callbacks for each active port, queue.
+ *
+ *  @return
+ *   -1: On error
+ *    0: On success
+ */
+int rte_latencystats_uninit(void);
+
+/**
+ * Retrieve names of latency statistics
+ *
+ * @param names
+ *  Block of memory to insert names into. Must be at least size in capacity.
+ *  If set to NULL, function returns required capacity.
+ * @param size
+ *  Capacity of latency stats names (number of names).
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ */
+int rte_latencystats_get_names(struct rte_metric_name *names,
+				uint16_t size);
+
+/**
+ * Retrieve latency statistics.
+ *
+ * @param values
+ *   A pointer to a table of structure of type *rte_metric_value*
+ *   to be filled with latency statistics ids and values.
+ *   This parameter can be set to NULL if size is 0.
+ * @param size
+ *   The size of the stats table, which should be large enough to store
+ *   all the latency stats.
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ *   -ENOMEM: On failure.
+ */
+int rte_latencystats_get(struct rte_metric_value *values,
+			uint16_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_LATENCYSTATS_H_ */
diff --git a/lib/librte_latencystats/rte_latencystats_version.map b/lib/librte_latencystats/rte_latencystats_version.map
new file mode 100644
index 0000000..502018e
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats_version.map
@@ -0,0 +1,10 @@
+DPDK_17.02 {
+	global:
+
+	rte_latencystats_get;
+	rte_latencystats_get_names;
+	rte_latencystats_init;
+	rte_latencystats_uninit;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 6aac5ac..1d36fad 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -100,7 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
 _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
-
+_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)  += -lrte_latencystats
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* [PATCH v8 7/7] app/test-pmd: add latency statistics calculation
  2017-01-17 23:24             ` [PATCH v8 0/7] Expanded statistics reporting Remy Horton
                                 ` (5 preceding siblings ...)
  2017-01-17 23:24               ` [PATCH v8 6/7] lib: added new library for latency stats Remy Horton
@ 2017-01-17 23:24               ` Remy Horton
  2017-01-18 15:05               ` [PATCH v9 0/7] Expanded statistics reporting Remy Horton
  7 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw)
  To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan

From: Harry van Haaren <harry.van.haaren@intel.com>

This patch adds latency stats commandline argument to testpmd,
allowing to specify the lcore to use for latencystats updates.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
---

v7 -> v8 changes:
- add optarg to enable latencystats, and which core to use for polling.
- implement polling of rte_latencystats_update() from lcore
- license year updates
---
 app/test-pmd/parameters.c | 20 +++++++++++++++++++-
 app/test-pmd/testpmd.c    | 37 +++++++++++++++++++++++++++++++++++++
 app/test-pmd/testpmd.h    |  6 +++++-
 3 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 28db8cd..30b60ba 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -1,7 +1,7 @@
 /*-
  *   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
@@ -149,6 +149,10 @@ usage(char* progname)
 	       "the packet will be enqueued into the rx drop-queue. "
 	       "If the drop-queue doesn't exist, the packet is dropped. "
 	       "By default drop-queue=127.\n");
+#ifdef RTE_LIBRTE_LATENCY_STATS
+	printf("  --latencystats=N: enable latency and jitter statistcs "
+	       "monitoring on lcore id N.\n");
+#endif
 	printf("  --crc-strip: enable CRC stripping by hardware.\n");
 	printf("  --enable-lro: enable large receive offload.\n");
 	printf("  --enable-rx-cksum: enable rx hardware checksum offload.\n");
@@ -526,6 +530,7 @@ launch_args_parse(int argc, char** argv)
 		{ "pkt-filter-report-hash",     1, 0, 0 },
 		{ "pkt-filter-size",            1, 0, 0 },
 		{ "pkt-filter-drop-queue",      1, 0, 0 },
+		{ "latencystats",               1, 0, 0 },
 		{ "crc-strip",                  0, 0, 0 },
 		{ "enable-lro",                 0, 0, 0 },
 		{ "enable-rx-cksum",            0, 0, 0 },
@@ -766,6 +771,19 @@ launch_args_parse(int argc, char** argv)
 						 "drop queue %d invalid - must"
 						 "be >= 0 \n", n);
 			}
+#ifdef RTE_LIBRTE_LATENCY_STATS
+			if (!strcmp(lgopts[opt_idx].name,
+				    "latencystats")) {
+				n = atoi(optarg);
+				if (n >= 0) {
+					latencystats_lcore_id = (lcoreid_t) n;
+					latencystats_enabled = 1;
+				} else
+					rte_exit(EXIT_FAILURE,
+						 "invalid lcore id %d for latencystats"
+						 " must be >= 0\n", n);
+			}
+#endif
 			if (!strcmp(lgopts[opt_idx].name, "crc-strip"))
 				rx_mode.hw_strip_crc = 1;
 			if (!strcmp(lgopts[opt_idx].name, "enable-lro"))
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index de60c09..70218bc 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -83,6 +83,10 @@
 #ifdef RTE_LIBRTE_BITRATE
 #include <rte_bitrate.h>
 #endif
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_LATENCY_STATS
+#include <rte_latencystats.h>
+#endif
 
 #include "testpmd.h"
 
@@ -276,6 +280,20 @@ uint32_t bypass_timeout = RTE_BYPASS_TMT_OFF;
 
 #endif
 
+#ifdef RTE_LIBRTE_LATENCY_STATS
+
+/*
+ * Set when latency stats is enabled in the commandline
+ */
+uint8_t latencystats_enabled;
+
+/*
+ * Lcore ID to serive latency statistics.
+ */
+lcoreid_t latencystats_lcore_id = -1;
+
+#endif
+
 /*
  * Ethernet device configuration.
  */
@@ -955,6 +973,11 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
 			tics_datum = tics_current;
 		}
 #endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+		if (latencystats_lcore_id == rte_lcore_id())
+			rte_latencystats_update();
+#endif
+
 	} while (! fc->stopped);
 }
 
@@ -2108,6 +2131,9 @@ signal_handler(int signum)
 		/* uninitialize packet capture framework */
 		rte_pdump_uninit();
 #endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+		rte_latencystats_uninit();
+#endif
 		force_quit();
 		/* exit with the expected status */
 		signal(signum, SIG_DFL);
@@ -2166,6 +2192,17 @@ main(int argc, char** argv)
 	FOREACH_PORT(port_id, ports)
 		rte_eth_promiscuous_enable(port_id);
 
+#ifdef RTE_LIBRTE_LATENCY_STATS
+	if (latencystats_enabled != 0) {
+		int ret = rte_latencystats_init(1, NULL);
+		if (ret)
+			printf("Warning: latencystats init()"
+				" returned error %d\n",	ret);
+		printf("Latencystats running on lcore %d\n",
+			latencystats_lcore_id);
+	}
+#endif
+
 	/* Setup bitrate stats */
 #ifdef RTE_LIBRTE_BITRATE
 	bitrate_data = rte_stats_bitrate_create();
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 0a9a1af..35f7477 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -1,7 +1,7 @@
 /*-
  *   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
@@ -381,6 +381,10 @@ extern enum dcb_queue_mapping_mode dcb_q_mapping;
 extern uint16_t mbuf_data_size; /**< Mbuf data space size. */
 extern uint32_t param_total_num_mbufs;
 
+
+extern uint8_t latencystats_enabled;
+extern lcoreid_t latencystats_lcore_id;
+
 extern struct rte_fdir_conf fdir_conf;
 
 /*
-- 
2.5.5

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

* [PATCH v9 0/7] Expanded statistics reporting
  2017-01-17 23:24             ` [PATCH v8 0/7] Expanded statistics reporting Remy Horton
                                 ` (6 preceding siblings ...)
  2017-01-17 23:24               ` [PATCH v8 7/7] app/test-pmd: add latency statistics calculation Remy Horton
@ 2017-01-18 15:05               ` Remy Horton
  2017-01-18 15:05                 ` [PATCH v9 1/7] lib: add information metrics library Remy Horton
                                   ` (7 more replies)
  7 siblings, 8 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patchset extends statistics reporting to include peak and
average data-rate metrics. It comes in two parts: a statistics
reporting library, and a bitrate calculation library that uses
it. This structure is intended to seperate statistic reporting
from ethdev and allow more flexible metric registration.

--

v9 changes:
* Updated .map files to reflect function changes in v8
* Fixed rte_malloc() of zero bytes in proc_info when no metrics exist
* Fixed rte_metrics_init not being called explicitly in testpmd

v8 changes:
* Release notes correction
* Updated copyright years
* rte_metric_init() takes socket id & must be explicitly called
* rte_metrics_reg_metric renamed to rte_metrics_reg_name()
* rte_metrics_update_metric() renamed to rte_metrics_update_value()
* Doxygen updates
* Changed malloc()/free() to rte_malloc()/rte_free()
* Removed redundant memset()
* rte_stats_bitrates_s renamed to rte_stats_bitrates_s
* Split mbuf change to own patch for visibility
* CYCLES_PER_NS now a static inline function
* latency: "hidden" pthread creation now has polling API instead.
* Struct declarations and variable definitions cleaned up
* Double initialization of the latency library now returns -EEXIST
* MAINTAINERS entry for layenctstats in correct section

v7 changes:
* RTE_METRICS_NONPORT renamed to RTE_METRICS_GLOBAL
* Multiple changes to rte_metrics.h doxygen documentation
* Split apart latency patch into lib, test-pmd, & proc_info parts
* Reordered patches by functionality
* Insufficent capacity return value changed from -ERANGE to actual size
* Cache alignment in bitrate library
* Tightened up const usage to avoid STATIC_CONST_CHAR_ARRAY warning
* Reshma reinstated as author for (now split) latency patch
* Rebase to master

v6 changes:
* Metrics display now has "Non port specific" rather than "port -1"
* Fixed sign issue in EWMA delta calculation
* Rebased to master

v5 changes:
* Updated Shared Library Versions in release notes
* Merged in Reshma's latencystats library

v4 changes:
* References to 16.11 changed to 17.02
* Fetching of non-port values was broken
* Added sanity checks to value fetching
* rte_stat_value renamed to rte_metric_value
* Corrected doxygen descriptions
* Added MAINTAINERS entries
* Added #ifdef directives to bitrate code in test-pmd

v3 changes:
* Marked rte_stats_bitrate_s as internal
* Minor integer roundoff correction
* Coding style corrections
* Removed spurious object allocation
* Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3.
* Reintroduced non-port values (RTE_METRICS_NONPORT)
* Added spinlocks to metric library
* Removed spurious test registration/update
* Added release notes entries

v2 changes:
* Uses a new metrics library rather than being part of ethdev


Harry van Haaren (3):
  mbuf: add a timestamp to the mbuf for latencystats
  lib: added new library for latency stats
  app/test-pmd: add latency statistics calculation

Remy Horton (3):
  lib: add information metrics library
  lib: add bitrate statistics library
  app/test-pmd: add bitrate statistics calculation

Reshma Pattan (1):
  app/proc_info: add metrics displaying

 MAINTAINERS                                        |  12 +
 app/proc_info/main.c                               |  79 ++++-
 app/test-pmd/parameters.c                          |  20 +-
 app/test-pmd/testpmd.c                             |  78 ++++-
 app/test-pmd/testpmd.h                             |   6 +-
 config/common_base                                 |  15 +
 doc/api/doxy-api-index.md                          |   3 +
 doc/api/doxy-api.conf                              |   3 +
 doc/guides/rel_notes/release_17_02.rst             |  18 +
 lib/Makefile                                       |   3 +
 lib/librte_bitratestats/Makefile                   |  53 +++
 lib/librte_bitratestats/rte_bitrate.c              | 132 ++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++
 .../rte_bitratestats_version.map                   |   9 +
 lib/librte_latencystats/Makefile                   |  56 ++++
 lib/librte_latencystats/rte_latencystats.c         | 366 +++++++++++++++++++++
 lib/librte_latencystats/rte_latencystats.h         | 154 +++++++++
 .../rte_latencystats_version.map                   |  11 +
 lib/librte_mbuf/rte_mbuf.h                         |   3 +
 lib/librte_metrics/Makefile                        |  51 +++
 lib/librte_metrics/rte_metrics.c                   | 308 +++++++++++++++++
 lib/librte_metrics/rte_metrics.h                   | 231 +++++++++++++
 lib/librte_metrics/rte_metrics_version.map         |  13 +
 mk/rte.app.mk                                      |   3 +
 24 files changed, 1703 insertions(+), 4 deletions(-)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map
 create mode 100644 lib/librte_latencystats/Makefile
 create mode 100644 lib/librte_latencystats/rte_latencystats.c
 create mode 100644 lib/librte_latencystats/rte_latencystats.h
 create mode 100644 lib/librte_latencystats/rte_latencystats_version.map
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

-- 
2.5.5

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

* [PATCH v9 1/7] lib: add information metrics library
  2017-01-18 15:05               ` [PATCH v9 0/7] Expanded statistics reporting Remy Horton
@ 2017-01-18 15:05                 ` Remy Horton
  2017-01-30 15:50                   ` Thomas Monjalon
  2017-01-18 15:05                 ` [PATCH v9 2/7] app/proc_info: add metrics displaying Remy Horton
                                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patch adds a new information metric library that allows other
modules to register named metrics and update their values. It is
intended to be independent of ethdev, rather than mixing ethdev
and non-ethdev information in xstats.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                |   4 +
 config/common_base                         |   5 +
 doc/api/doxy-api-index.md                  |   1 +
 doc/api/doxy-api.conf                      |   1 +
 doc/guides/rel_notes/release_17_02.rst     |   8 +
 lib/Makefile                               |   1 +
 lib/librte_metrics/Makefile                |  51 +++++
 lib/librte_metrics/rte_metrics.c           | 308 +++++++++++++++++++++++++++++
 lib/librte_metrics/rte_metrics.h           | 231 ++++++++++++++++++++++
 lib/librte_metrics/rte_metrics_version.map |  13 ++
 mk/rte.app.mk                              |   2 +
 11 files changed, 625 insertions(+)
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 9645c9b..95836a2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -596,6 +596,10 @@ F: lib/librte_jobstats/
 F: examples/l2fwd-jobstats/
 F: doc/guides/sample_app_ug/l2_forward_job_stats.rst
 
+Metrics
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_metrics/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index 8e9dcfa..0eb3866 100644
--- a/config/common_base
+++ b/config/common_base
@@ -593,3 +593,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
 CONFIG_RTE_TEST_PMD=y
 CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
 CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+
+#
+# Compile the device metrics library
+#
+CONFIG_RTE_LIBRTE_METRICS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 72d59b2..94f0f69 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -150,4 +150,5 @@ There are many libraries, so their headers may be grouped by topics:
   [common]             (@ref rte_common.h),
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
+  [Device Metrics]     (@ref rte_metrics.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index b340fcf..194b670 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -50,6 +50,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_mbuf \
                           lib/librte_mempool \
                           lib/librte_meter \
+                          lib/librte_metrics \
                           lib/librte_net \
                           lib/librte_pdump \
                           lib/librte_pipeline \
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 4a3b947..abbfe4a 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -34,6 +34,12 @@ New Features
 
      Refer to the previous release notes for examples.
 
+   * **Added information metric library.**
+
+     A library that allows information metrics to be added and update. It is
+     intended to provide a reporting mechanism that is independent of the
+     ethdev library.
+
      This section is a comment. do not overwrite or remove it.
      Also, make sure to start the actual text at the margin.
      =========================================================
@@ -205,6 +211,7 @@ The libraries prepended with a plus sign were incremented in this version.
 .. code-block:: diff
 
      librte_acl.so.2
+   + librte_bitratestats.so.1
      librte_cfgfile.so.2
      librte_cmdline.so.2
      librte_cryptodev.so.2
@@ -220,6 +227,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_mbuf.so.2
      librte_mempool.so.2
      librte_meter.so.1
+   + librte_metrics.so.1
      librte_net.so.1
      librte_pdump.so.1
      librte_pipeline.so.3
diff --git a/lib/Makefile b/lib/Makefile
index 990f23a..5d85dcf 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table
 DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
+DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile
new file mode 100644
index 0000000..8d6e23a
--- /dev/null
+++ b/lib/librte_metrics/Makefile
@@ -0,0 +1,51 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_metrics.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_metrics_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c
new file mode 100644
index 0000000..5a67c85
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.c
@@ -0,0 +1,308 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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 <string.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_lcore.h>
+#include <rte_memzone.h>
+#include <rte_spinlock.h>
+
+#define RTE_METRICS_MAX_METRICS 256
+#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS"
+
+/**
+ * Internal stats metadata and value entry.
+ *
+ * @internal
+ * @param name
+ *   Name of metric
+ * @param value
+ *   Current value for metric
+ * @param idx_next_set
+ *   Index of next root element (zero for none)
+ * @param idx_next_metric
+ *   Index of next metric in set (zero for none)
+ *
+ * Only the root of each set needs idx_next_set but since it has to be
+ * assumed that number of sets could equal total number of metrics,
+ * having a separate set metadata table doesn't save any memory.
+ */
+struct rte_metrics_meta_s {
+	char name[RTE_METRICS_MAX_NAME_LEN];
+	uint64_t value[RTE_MAX_ETHPORTS];
+	uint64_t nonport_value;
+	uint16_t idx_next_set;
+	uint16_t idx_next_stat;
+};
+
+/**
+ * Internal stats info structure.
+ *
+ * @internal
+ * @param idx_last_set
+ *   Index of last metadata entry with valid data. This value is
+ *   not valid if cnt_stats is zero.
+ * @param cnt_stats
+ *   Number of metrics.
+ * @param metadata
+ *   Stat data memory block.
+ *
+ * Offsets into metadata are used instead of pointers because ASLR
+ * means that having the same physical addresses in different
+ * processes is not guaranteed.
+ */
+struct rte_metrics_data_s {
+	uint16_t idx_last_set;
+	uint16_t cnt_stats;
+	struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS];
+	rte_spinlock_t lock;
+};
+
+void
+rte_metrics_init(int socket_id)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone != NULL)
+		return;
+	memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME,
+		sizeof(struct rte_metrics_data_s), socket_id, 0);
+	if (memzone == NULL)
+		rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
+	stats = memzone->addr;
+	memset(stats, 0, sizeof(struct rte_metrics_data_s));
+	rte_spinlock_init(&stats->lock);
+}
+
+int
+rte_metrics_reg_name(const char *name)
+{
+	const char * const list_names[] = {name};
+
+	return rte_metrics_reg_names(list_names, 1);
+}
+
+int
+rte_metrics_reg_names(const char * const *names, uint16_t cnt_names)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	uint16_t idx_base;
+
+	/* Some sanity checks */
+	if (cnt_names < 1 || names == NULL)
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS)
+		return -ENOMEM;
+
+	rte_spinlock_lock(&stats->lock);
+
+	/* Overwritten later if this is actually first set.. */
+	stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats;
+
+	stats->idx_last_set = idx_base = stats->cnt_stats;
+
+	for (idx_name = 0; idx_name < cnt_names; idx_name++) {
+		entry = &stats->metadata[idx_name + stats->cnt_stats];
+		strncpy(entry->name, names[idx_name],
+			RTE_METRICS_MAX_NAME_LEN);
+		memset(entry->value, 0, sizeof(entry->value));
+		entry->idx_next_stat = idx_name + stats->cnt_stats + 1;
+	}
+	entry->idx_next_stat = 0;
+	entry->idx_next_set = 0;
+	stats->cnt_stats += cnt_names;
+
+	rte_spinlock_unlock(&stats->lock);
+
+	return idx_base;
+}
+
+int
+rte_metrics_update_value(int port_id, uint16_t key, const uint64_t value)
+{
+	return rte_metrics_update_values(port_id, key, &value, 1);
+}
+
+int
+rte_metrics_update_values(int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_metric;
+	uint16_t idx_value;
+	uint16_t cnt_setsize;
+
+	if (port_id != RTE_METRICS_GLOBAL &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	rte_spinlock_lock(&stats->lock);
+	idx_metric = key;
+	cnt_setsize = 1;
+	while (idx_metric < stats->cnt_stats) {
+		entry = &stats->metadata[idx_metric];
+		if (entry->idx_next_stat == 0)
+			break;
+		cnt_setsize++;
+		idx_metric++;
+	}
+	/* Check update does not cross set border */
+	if (count > cnt_setsize) {
+		rte_spinlock_unlock(&stats->lock);
+		return -ERANGE;
+	}
+
+	if (port_id == RTE_METRICS_GLOBAL)
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].nonport_value =
+				values[idx_value];
+		}
+	else
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].value[port_id] =
+				values[idx_value];
+		}
+	rte_spinlock_unlock(&stats->lock);
+	return 0;
+}
+
+int
+rte_metrics_get_names(struct rte_metric_name *names,
+	uint16_t capacity)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+	if (names != NULL) {
+		if (capacity < stats->cnt_stats) {
+			return_value = stats->cnt_stats;
+			rte_spinlock_unlock(&stats->lock);
+			return return_value;
+		}
+		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
+			strncpy(names[idx_name].name,
+				stats->metadata[idx_name].name,
+				RTE_METRICS_MAX_NAME_LEN);
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
+
+int
+rte_metrics_get_values(int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	if (port_id != RTE_METRICS_GLOBAL &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+
+	if (values != NULL) {
+		if (capacity < stats->cnt_stats) {
+			return_value = stats->cnt_stats;
+			rte_spinlock_unlock(&stats->lock);
+			return return_value;
+		}
+		if (port_id == RTE_METRICS_GLOBAL)
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->nonport_value;
+			}
+		else
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->value[port_id];
+			}
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
new file mode 100644
index 0000000..871a8f9
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.h
@@ -0,0 +1,231 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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.
+ */
+
+/**
+ * @file
+ *
+ * RTE Metrics module
+ *
+ * Metric information is populated using a push model, where the
+ * information provider calls an update function on the relevant
+ * metrics. Currently only bulk querying of metrics is supported.
+ */
+
+#ifndef _RTE_METRICS_H_
+#define _RTE_METRICS_H_
+
+/** Maximum length of metric name (including null-terminator) */
+#define RTE_METRICS_MAX_NAME_LEN 64
+
+/**
+ * Global (rather than port-specific) metric.
+ *
+ * When used instead of port number by rte_metrics_update_metric()
+ * or rte_metrics_update_metric(), the global metrics, which are
+ * not associated with any specific port, are updated.
+ */
+#define RTE_METRICS_GLOBAL -1
+
+
+/**
+ * A name-key lookup for metrics.
+ *
+ * An array of this structure is returned by rte_metrics_get_names().
+ * The struct rte_eth_stats references these names via their array index.
+ */
+struct rte_metric_name {
+	/** String describing metric */
+	char name[RTE_METRICS_MAX_NAME_LEN];
+};
+
+
+/**
+ * Metric value structure.
+ *
+ * This structure is used by rte_metrics_get_values() to return metrics,
+ * which are statistics that are not generated by PMDs. It maps a name key,
+ * which corresponds to an index in the array returned by
+ * rte_metrics_get_names().
+ */
+struct rte_metric_value {
+	/** Numeric identifier of metric. */
+	uint16_t key;
+	/** Value for metric */
+	uint64_t value;
+};
+
+
+/**
+ * Initializes metric module. This function must be called from
+ * a primary process before metrics are used.
+ *
+ * @param socket_id
+ *   Socket to use for shared memory allocation.
+ */
+void rte_metrics_init(int socket_id);
+
+/**
+ * Register a metric, making it available as a reporting parameter.
+ *
+ * Registering a metric is the way third-parties declare a parameter
+ * that they wish to be reported. Once registered, the associated
+ * numeric key can be obtained via rte_metrics_get_names(), which
+ * is required for updating said metric's value.
+ *
+ * @param name
+ *   Metric name
+ *
+ * @return
+ *  - Zero or positive: Success (index key of new metric)
+ *  - \b -EIO: Error, unable to access metrics shared memory
+ *    (rte_metrics_init() not called)
+ *  - \b -EINVAL: Error, invalid parameters
+ *  - \b -ENOMEM: Error, maximum metrics reached
+ */
+int rte_metrics_reg_name(const char *name);
+
+/**
+ * Register a set of metrics.
+ *
+ * This is a bulk version of rte_metrics_reg_metrics() and aside from
+ * handling multiple keys at once is functionally identical.
+ *
+ * @param names
+ *   List of metric names
+ *
+ * @param cnt_names
+ *   Number of metrics in set
+ *
+ * @return
+ *  - Zero or positive: Success (index key of start of set)
+ *  - \b -EIO: Error, unable to access metrics shared memory
+ *    (rte_metrics_init() not called)
+ *  - \b -EINVAL: Error, invalid parameters
+ *  - \b -ENOMEM: Error, maximum metrics reached
+ */
+int rte_metrics_reg_names(const char * const *names, uint16_t cnt_names);
+
+/**
+ * Get metric name-key lookup table.
+ *
+ * @param names
+ *   A struct rte_metric_name array of at least *capacity* in size to
+ *   receive key names. If this is NULL, function returns the required
+ *   number of elements for this array.
+ *
+ * @param capacity
+ *   Size (number of elements) of struct rte_metric_name array.
+ *   Disregarded if names is NULL.
+ *
+ * @return
+ *   - Positive value above capacity: error, *names* is too small.
+ *     Return value is required size.
+ *   - Positive value equal or less than capacity: Success. Return
+ *     value is number of elements filled in.
+ *   - Negative value: error.
+ */
+int rte_metrics_get_names(
+	struct rte_metric_name *names,
+	uint16_t capacity);
+
+/**
+ * Get metric value table.
+ *
+ * @param port_id
+ *   Port id to query
+ *
+ * @param values
+ *   A struct rte_metric_value array of at least *capacity* in size to
+ *   receive metric ids and values. If this is NULL, function returns
+ *   the required number of elements for this array.
+ *
+ * @param capacity
+ *   Size (number of elements) of struct rte_metric_value array.
+ *   Disregarded if names is NULL.
+ *
+ * @return
+ *   - Positive value above capacity: error, *values* is too small.
+ *     Return value is required size.
+ *   - Positive value equal or less than capacity: Success. Return
+ *     value is number of elements filled in.
+ *   - Negative value: error.
+ */
+int rte_metrics_get_values(
+	int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity);
+
+/**
+ * Updates a metric
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Id of metric to update
+ * @param value
+ *   New value
+ *
+ * @return
+ *   - -EIO if unable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_value(
+	int port_id,
+	uint16_t key,
+	const uint64_t value);
+
+/**
+ * Updates a metric set. Note that it is an error to try to
+ * update across a set boundary.
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Base id of metrics set to update
+ * @param values
+ *   Set of new values
+ * @param count
+ *   Number of new values
+ *
+ * @return
+ *   - -ERANGE if count exceeds metric set size
+ *   - -EIO if upable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_values(
+	int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count);
+
+#endif
diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map
new file mode 100644
index 0000000..ee28fa0
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics_version.map
@@ -0,0 +1,13 @@
+DPDK_17.02 {
+	global:
+
+	rte_metrics_get_names;
+	rte_metrics_get_values;
+	rte_metrics_init;
+	rte_metrics_reg_name;
+	rte_metrics_reg_names;
+	rte_metrics_update_value;
+	rte_metrics_update_values;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index f75f0e2..40fcf33 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -98,6 +98,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING)           += -lrte_ring
 _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
+_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* [PATCH v9 2/7] app/proc_info: add metrics displaying
  2017-01-18 15:05               ` [PATCH v9 0/7] Expanded statistics reporting Remy Horton
  2017-01-18 15:05                 ` [PATCH v9 1/7] lib: add information metrics library Remy Horton
@ 2017-01-18 15:05                 ` Remy Horton
  2017-01-18 15:05                 ` [PATCH v9 3/7] lib: add bitrate statistics library Remy Horton
                                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw)
  To: dev; +Cc: Reshma Pattan, Thomas Monjalon

From: Reshma Pattan <reshma.pattan@intel.com>

Modify the dpdk-procinfo process to display the newly added metrics.
Added new command line option "--metrics" to display metrics.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/proc_info/main.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 78 insertions(+), 1 deletion(-)

diff --git a/app/proc_info/main.c b/app/proc_info/main.c
index 2c56d10..f513669 100644
--- a/app/proc_info/main.c
+++ b/app/proc_info/main.c
@@ -1,7 +1,7 @@
 /*
  *   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
@@ -57,6 +57,7 @@
 #include <rte_atomic.h>
 #include <rte_branch_prediction.h>
 #include <rte_string_fns.h>
+#include <rte_metrics.h>
 
 /* Maximum long option length for option parsing. */
 #define MAX_LONG_OPT_SZ 64
@@ -68,6 +69,8 @@ static uint32_t enabled_port_mask;
 static uint32_t enable_stats;
 /**< Enable xstats. */
 static uint32_t enable_xstats;
+/**< Enable metrics. */
+static uint32_t enable_metrics;
 /**< Enable stats reset. */
 static uint32_t reset_stats;
 /**< Enable xstats reset. */
@@ -85,6 +88,8 @@ proc_info_usage(const char *prgname)
 		"  --stats: to display port statistics, enabled by default\n"
 		"  --xstats: to display extended port statistics, disabled by "
 			"default\n"
+		"  --metrics: to display derived metrics of the ports, disabled by "
+			"default\n"
 		"  --stats-reset: to reset port statistics\n"
 		"  --xstats-reset: to reset port extended statistics\n",
 		prgname);
@@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv)
 		{"stats", 0, NULL, 0},
 		{"stats-reset", 0, NULL, 0},
 		{"xstats", 0, NULL, 0},
+		{"metrics", 0, NULL, 0},
 		{"xstats-reset", 0, NULL, 0},
 		{NULL, 0, 0, 0}
 	};
@@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv)
 			else if (!strncmp(long_option[option_index].name, "xstats",
 					MAX_LONG_OPT_SZ))
 				enable_xstats = 1;
+			else if (!strncmp(long_option[option_index].name,
+					"metrics",
+					MAX_LONG_OPT_SZ))
+				enable_metrics = 1;
 			/* Reset stats */
 			if (!strncmp(long_option[option_index].name, "stats-reset",
 					MAX_LONG_OPT_SZ))
@@ -301,6 +311,67 @@ nic_xstats_clear(uint8_t port_id)
 	printf("\n  NIC extended statistics for port %d cleared\n", port_id);
 }
 
+static void
+metrics_display(int port_id)
+{
+	struct rte_metric_value *metrics;
+	struct rte_metric_name *names;
+	int len, ret;
+	static const char *nic_stats_border = "########################";
+
+	len = rte_metrics_get_names(NULL, 0);
+	if (len < 0) {
+		printf("Cannot get metrics count\n");
+		return;
+	}
+	if (len == 0) {
+		printf("No metrics to display (none have been registered)\n");
+		return;
+	}
+
+	metrics = rte_malloc("proc_info_metrics",
+		sizeof(struct rte_metric_value) * len, 0);
+	if (metrics == NULL) {
+		printf("Cannot allocate memory for metrics\n");
+		return;
+	}
+
+	names =  rte_malloc(NULL, sizeof(struct rte_metric_name) * len, 0);
+	if (names == NULL) {
+		printf("Cannot allocate memory for metrcis names\n");
+		rte_free(metrics);
+		return;
+	}
+
+	if (len != rte_metrics_get_names(names, len)) {
+		printf("Cannot get metrics names\n");
+		rte_free(metrics);
+		rte_free(names);
+		return;
+	}
+
+	if (port_id == RTE_METRICS_GLOBAL)
+		printf("###### Non port specific metrics  #########\n");
+	else
+		printf("###### metrics for port %-2d #########\n", port_id);
+	printf("%s############################\n", nic_stats_border);
+	ret = rte_metrics_get_values(port_id, metrics, len);
+	if (ret < 0 || ret > len) {
+		printf("Cannot get metrics values\n");
+		rte_free(metrics);
+		rte_free(names);
+		return;
+	}
+
+	int i;
+	for (i = 0; i < len; i++)
+		printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value);
+
+	printf("%s############################\n", nic_stats_border);
+	rte_free(metrics);
+	rte_free(names);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -360,8 +431,14 @@ main(int argc, char **argv)
 				nic_stats_clear(i);
 			else if (reset_xstats)
 				nic_xstats_clear(i);
+			else if (enable_metrics)
+				metrics_display(i);
 		}
 	}
 
+	/* print port independent stats */
+	if (enable_metrics)
+		metrics_display(RTE_METRICS_GLOBAL);
+
 	return 0;
 }
-- 
2.5.5

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

* [PATCH v9 3/7] lib: add bitrate statistics library
  2017-01-18 15:05               ` [PATCH v9 0/7] Expanded statistics reporting Remy Horton
  2017-01-18 15:05                 ` [PATCH v9 1/7] lib: add information metrics library Remy Horton
  2017-01-18 15:05                 ` [PATCH v9 2/7] app/proc_info: add metrics displaying Remy Horton
@ 2017-01-18 15:05                 ` Remy Horton
  2017-01-18 15:05                 ` [PATCH v9 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton
                                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patch adds a library that calculates peak and average data-rate
statistics. For ethernet devices. These statistics are reported using
the metrics library.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                        |   4 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/rel_notes/release_17_02.rst             |   5 +
 lib/Makefile                                       |   1 +
 lib/librte_bitratestats/Makefile                   |  53 +++++++++
 lib/librte_bitratestats/rte_bitrate.c              | 132 +++++++++++++++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++++++++++
 .../rte_bitratestats_version.map                   |   9 ++
 mk/rte.app.mk                                      |   1 +
 11 files changed, 292 insertions(+)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 95836a2..d9423cb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -600,6 +600,10 @@ Metrics
 M: Remy Horton <remy.horton@intel.com>
 F: lib/librte_metrics/
 
+Bit-rate statistica
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_bitratestats/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index 0eb3866..decebe5 100644
--- a/config/common_base
+++ b/config/common_base
@@ -598,3 +598,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
 # Compile the device metrics library
 #
 CONFIG_RTE_LIBRTE_METRICS=y
+
+#
+# Compile the bitrate statistics library
+#
+CONFIG_RTE_LIBRTE_BITRATE=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 94f0f69..5e194b0 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -151,4 +151,5 @@ There are many libraries, so their headers may be grouped by topics:
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
   [Device Metrics]     (@ref rte_metrics.h),
+  [Bitrate Statistics] (@ref rte_bitrate.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index 194b670..6e6ab5c 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -35,6 +35,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_eal/common/include \
                           lib/librte_eal/common/include/generic \
                           lib/librte_acl \
+                          lib/librte_bitratestats \
                           lib/librte_cfgfile \
                           lib/librte_cmdline \
                           lib/librte_compat \
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index abbfe4a..421270c 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -40,6 +40,11 @@ New Features
      intended to provide a reporting mechanism that is independent of the
      ethdev library.
 
+   * **Added bit-rate calculation library.**
+
+     A library that can be used to calculate device bit-rates. Calculated
+     bitrates are reported using the metrics library.
+
      This section is a comment. do not overwrite or remove it.
      Also, make sure to start the actual text at the margin.
      =========================================================
diff --git a/lib/Makefile b/lib/Makefile
index 5d85dcf..e211bc0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
 DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
+DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile
new file mode 100644
index 0000000..743b62c
--- /dev/null
+++ b/lib/librte_bitratestats/Makefile
@@ -0,0 +1,53 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016-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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_bitratestats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_bitratestats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c
new file mode 100644
index 0000000..2c20272
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.c
@@ -0,0 +1,132 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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 <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
+
+/*
+ * Persistent bit-rate data.
+ * @internal
+ */
+struct rte_stats_bitrate {
+	uint64_t last_ibytes;
+	uint64_t last_obytes;
+	uint64_t peak_ibits;
+	uint64_t peak_obits;
+	uint64_t ewma_ibits;
+	uint64_t ewma_obits;
+};
+
+struct rte_stats_bitrates {
+	struct rte_stats_bitrate port_stats[RTE_MAX_ETHPORTS];
+	uint16_t id_stats_set;
+};
+
+struct rte_stats_bitrates *
+rte_stats_bitrate_create(void)
+{
+	return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates),
+		RTE_CACHE_LINE_SIZE);
+}
+
+int
+rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data)
+{
+	const char * const names[] = {
+		"mean_bits_in", "mean_bits_out",
+		"peak_bits_in", "peak_bits_out",
+	};
+	int return_value;
+
+	return_value = rte_metrics_reg_names(&names[0], 4);
+	if (return_value >= 0)
+		bitrate_data->id_stats_set = return_value;
+	return return_value;
+}
+
+int
+rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data,
+	uint8_t port_id)
+{
+	struct rte_stats_bitrate *port_data;
+	struct rte_eth_stats eth_stats;
+	int ret_code;
+	uint64_t cnt_bits;
+	int64_t delta;
+	const int64_t alpha_percent = 20;
+	uint64_t values[4];
+
+	ret_code = rte_eth_stats_get(port_id, &eth_stats);
+	if (ret_code != 0)
+		return ret_code;
+
+	port_data = &bitrate_data->port_stats[port_id];
+
+	/* Incoming bitrate. This is an iteratively calculated EWMA
+	 * (Expomentially Weighted Moving Average) that uses a
+	 * weighting factor of alpha_percent.
+	 */
+	cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3;
+	port_data->last_ibytes = eth_stats.ibytes;
+	if (cnt_bits > port_data->peak_ibits)
+		port_data->peak_ibits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_ibits;
+	/* The +-50 fixes integer rounding during divison */
+	if (delta > 0)
+		delta = (delta * alpha_percent + 50) / 100;
+	else
+		delta = (delta * alpha_percent - 50) / 100;
+	port_data->ewma_ibits += delta;
+
+	/* Outgoing bitrate (also EWMA) */
+	cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3;
+	port_data->last_obytes = eth_stats.obytes;
+	if (cnt_bits > port_data->peak_obits)
+		port_data->peak_obits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_obits;
+	delta = (delta * alpha_percent + 50) / 100;
+	port_data->ewma_obits += delta;
+
+	values[0] = port_data->ewma_ibits;
+	values[1] = port_data->ewma_obits;
+	values[2] = port_data->peak_ibits;
+	values[3] = port_data->peak_obits;
+	rte_metrics_update_values(port_id, bitrate_data->id_stats_set,
+		values, 4);
+	return 0;
+}
diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h
new file mode 100644
index 0000000..564e4f7
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.h
@@ -0,0 +1,80 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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.
+ */
+
+
+/**
+ *  Bitrate statistics data structure.
+ *  This data structure is intentionally opaque.
+ */
+struct rte_stats_bitrates;
+
+
+/**
+ * Allocate a bitrate statistics structure
+ *
+ * @return
+ *   - Pointer to structure on success
+ *   - NULL on error (zmalloc failure)
+ */
+struct rte_stats_bitrates *rte_stats_bitrate_create(void);
+
+
+/**
+ * Register bitrate statistics with the metric library.
+ *
+ * @param bitrate_data
+ *   Pointer allocated by rte_stats_create()
+ *
+ * @return
+ *   Zero on success
+ *   Negative on error
+ */
+int rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data);
+
+
+/**
+ * Calculate statistics for current time window. The period with which
+ * this function is called should be the intended sampling window width.
+ *
+ * @param bitrate_data
+ *   Bitrate statistics data pointer
+ *
+ * @param port_id
+ *   Port id to calculate statistics for
+ *
+ * @return
+ *  - Zero on success
+ *  - Negative value on error
+ */
+int rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data,
+	uint8_t port_id);
diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map
new file mode 100644
index 0000000..66f232f
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitratestats_version.map
@@ -0,0 +1,9 @@
+DPDK_17.02 {
+	global:
+
+	rte_stats_bitrate_calc;
+	rte_stats_bitrate_create;
+	rte_stats_bitrate_reg;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 40fcf33..6aac5ac 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -99,6 +99,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
 
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
-- 
2.5.5

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

* [PATCH v9 4/7] app/test-pmd: add bitrate statistics calculation
  2017-01-18 15:05               ` [PATCH v9 0/7] Expanded statistics reporting Remy Horton
                                   ` (2 preceding siblings ...)
  2017-01-18 15:05                 ` [PATCH v9 3/7] lib: add bitrate statistics library Remy Horton
@ 2017-01-18 15:05                 ` Remy Horton
  2017-01-18 15:05                 ` [PATCH v9 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton
                                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

Calculate bitrate statistics using the bitrate stats library. The
resulting statistics can be viewed via proc_info.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/testpmd.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index bfb2f8e..b31a300 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -1,7 +1,7 @@
 /*-
  *   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
@@ -79,6 +79,10 @@
 #include <rte_pdump.h>
 #endif
 #include <rte_flow.h>
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_BITRATE
+#include <rte_bitrate.h>
+#endif
 
 #include "testpmd.h"
 
@@ -323,6 +327,9 @@ uint16_t nb_rx_queue_stats_mappings = 0;
 
 unsigned max_socket = 0;
 
+/* Bitrate statistics */
+struct rte_stats_bitrates *bitrate_data;
+
 /* Forward function declarations */
 static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -922,12 +929,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
 	struct fwd_stream **fsm;
 	streamid_t nb_fs;
 	streamid_t sm_id;
+#ifdef RTE_LIBRTE_BITRATE
+	uint64_t tics_per_1sec;
+	uint64_t tics_datum;
+	uint64_t tics_current;
+	uint8_t idx_port, cnt_ports;
+#endif
 
+#ifdef RTE_LIBRTE_BITRATE
+	cnt_ports = rte_eth_dev_count();
+	tics_datum = rte_rdtsc();
+	tics_per_1sec = rte_get_timer_hz();
+#endif
 	fsm = &fwd_streams[fc->stream_idx];
 	nb_fs = fc->stream_nb;
 	do {
 		for (sm_id = 0; sm_id < nb_fs; sm_id++)
 			(*pkt_fwd)(fsm[sm_id]);
+#ifdef RTE_LIBRTE_BITRATE
+		tics_current = rte_rdtsc();
+		if (tics_current - tics_datum >= tics_per_1sec) {
+			/* Periodic bitrate calculation */
+			for (idx_port = 0; idx_port < cnt_ports; idx_port++)
+				rte_stats_bitrate_calc(bitrate_data, idx_port);
+			tics_datum = tics_current;
+		}
+#endif
 	} while (! fc->stopped);
 }
 
@@ -2139,6 +2166,18 @@ main(int argc, char** argv)
 	FOREACH_PORT(port_id, ports)
 		rte_eth_promiscuous_enable(port_id);
 
+	/* Init metrics library */
+	rte_metrics_init(rte_socket_id());
+
+	/* Setup bitrate stats */
+#ifdef RTE_LIBRTE_BITRATE
+	bitrate_data = rte_stats_bitrate_create();
+	if (bitrate_data == NULL)
+		rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n");
+	rte_stats_bitrate_reg(bitrate_data);
+#endif
+
+
 #ifdef RTE_LIBRTE_CMDLINE
 	if (interactive == 1) {
 		if (auto_start) {
-- 
2.5.5

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

* [PATCH v9 5/7] mbuf: add a timestamp to the mbuf for latencystats
  2017-01-18 15:05               ` [PATCH v9 0/7] Expanded statistics reporting Remy Horton
                                   ` (3 preceding siblings ...)
  2017-01-18 15:05                 ` [PATCH v9 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton
@ 2017-01-18 15:05                 ` Remy Horton
  2017-01-18 15:05                 ` [PATCH v9 6/7] lib: added new library for latency stats Remy Horton
                                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw)
  To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan

From: Harry van Haaren <harry.van.haaren@intel.com>

This commit adds a uint64_t to the mbuf struct,
allowing collection of latency and jitter statistics
by measuring packet I/O timestamps. This change is
required by the latencystats library.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
---
 lib/librte_mbuf/rte_mbuf.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index bfce9f4..c35ba0a 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -512,6 +512,9 @@ struct rte_mbuf {
 
 	/** Timesync flags for use with IEEE1588. */
 	uint16_t timesync;
+
+	/** Timestamp for measuring latency. */
+	uint64_t timestamp;
 } __rte_cache_aligned;
 
 /**
-- 
2.5.5

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

* [PATCH v9 6/7] lib: added new library for latency stats
  2017-01-18 15:05               ` [PATCH v9 0/7] Expanded statistics reporting Remy Horton
                                   ` (4 preceding siblings ...)
  2017-01-18 15:05                 ` [PATCH v9 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton
@ 2017-01-18 15:05                 ` Remy Horton
  2017-01-18 15:05                 ` [PATCH v9 7/7] app/test-pmd: add latency statistics calculation Remy Horton
  2017-02-03 10:33                 ` [PATCH v10 0/7] Expanded statistics reporting Remy Horton
  7 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw)
  To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan

From: Harry van Haaren <harry.van.haaren@intel.com>

Add a library designed to calculate latency statistics and report them
to the application when queried. The library measures minimum, average and
maximum latencies, and jitter in nano seconds. The current implementation
supports global latency stats, i.e. per application stats.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
---
 MAINTAINERS                                        |   4 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/rel_notes/release_17_02.rst             |   5 +
 lib/Makefile                                       |   1 +
 lib/librte_latencystats/Makefile                   |  56 ++++
 lib/librte_latencystats/rte_latencystats.c         | 366 +++++++++++++++++++++
 lib/librte_latencystats/rte_latencystats.h         | 154 +++++++++
 .../rte_latencystats_version.map                   |  11 +
 mk/rte.app.mk                                      |   2 +-
 11 files changed, 605 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_latencystats/Makefile
 create mode 100644 lib/librte_latencystats/rte_latencystats.c
 create mode 100644 lib/librte_latencystats/rte_latencystats.h
 create mode 100644 lib/librte_latencystats/rte_latencystats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index d9423cb..03f53b7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -604,6 +604,10 @@ Bit-rate statistica
 M: Remy Horton <remy.horton@intel.com>
 F: lib/librte_bitratestats/
 
+Latency Stats
+M: Reshma Pattan <reshma.pattan@intel.com>
+F: lib/librte_latencystats/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index decebe5..762a54c 100644
--- a/config/common_base
+++ b/config/common_base
@@ -603,3 +603,8 @@ CONFIG_RTE_LIBRTE_METRICS=y
 # Compile the bitrate statistics library
 #
 CONFIG_RTE_LIBRTE_BITRATE=y
+
+#
+# Compile the latency statistics library
+#
+CONFIG_RTE_LIBRTE_LATENCY_STATS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 5e194b0..1cacacc 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -152,4 +152,5 @@ There are many libraries, so their headers may be grouped by topics:
   [keepalive]          (@ref rte_keepalive.h),
   [Device Metrics]     (@ref rte_metrics.h),
   [Bitrate Statistics] (@ref rte_bitrate.h),
+  [Latency stats]      (@ref rte_latencystats.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index 6e6ab5c..0effece 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -47,6 +47,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_jobstats \
                           lib/librte_kni \
                           lib/librte_kvargs \
+                          lib/librte_latencystats \
                           lib/librte_lpm \
                           lib/librte_mbuf \
                           lib/librte_mempool \
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 421270c..2203593 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -107,6 +107,10 @@ New Features
   See the :ref:`Virtio Interrupt Mode <virtio_interrupt_mode>` documentation
   for more information.
 
+* **Added latency stats library.**
+
+  A library that measures packet latency. The collected statistics are jitter
+  and latency. For latency the minimum, average, and maximum is measured.
 
 Resolved Issues
 ---------------
@@ -228,6 +232,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_jobstats.so.1
      librte_kni.so.2
      librte_kvargs.so.1
+   + librte_latencystats.so.1
      librte_lpm.so.2
      librte_mbuf.so.2
      librte_mempool.so.2
diff --git a/lib/Makefile b/lib/Makefile
index e211bc0..6fffa88 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -60,6 +60,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
 DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
+DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
diff --git a/lib/librte_latencystats/Makefile b/lib/librte_latencystats/Makefile
new file mode 100644
index 0000000..fd145d3
--- /dev/null
+++ b/lib/librte_latencystats/Makefile
@@ -0,0 +1,56 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016-2017 Intel Corporation. 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_latencystats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
+LDLIBS += -lm
+LDLIBS += -lpthread
+
+EXPORT_MAP := rte_latencystats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) := rte_latencystats.c
+
+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)-include := rte_latencystats.h
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_latencystats/rte_latencystats.c b/lib/librte_latencystats/rte_latencystats.c
new file mode 100644
index 0000000..5334b8b
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats.c
@@ -0,0 +1,366 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-2017 Intel Corporation. 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 <unistd.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <math.h>
+
+#include <rte_mbuf.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_metrics.h>
+#include <rte_memzone.h>
+#include <rte_lcore.h>
+#include <rte_timer.h>
+
+#include "rte_latencystats.h"
+
+/** Nano seconds per second */
+#define NS_PER_SEC 1E9
+
+/** Clock cycles per nano second */
+static uint64_t
+latencystat_cycles_per_ns(void)
+{
+	return rte_get_timer_hz() / NS_PER_SEC;
+}
+
+/* Macros for printing using RTE_LOG */
+#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1
+
+static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats";
+static int latency_stats_index;
+static uint64_t samp_intvl;
+static uint64_t timer_tsc;
+static uint64_t prev_tsc;
+
+struct rte_latency_stats {
+	float min_latency; /**< Minimum latency in nano seconds */
+	float avg_latency; /**< Average latency in nano seconds */
+	float max_latency; /**< Maximum latency in nano seconds */
+	float jitter; /** Latency variation */
+};
+
+static struct rte_latency_stats *glob_stats;
+
+struct rxtx_cbs {
+	struct rte_eth_rxtx_callback *cb;
+};
+
+static struct rxtx_cbs rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
+static struct rxtx_cbs tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
+
+struct latency_stats_nameoff {
+	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	unsigned int offset;
+};
+
+static const struct latency_stats_nameoff lat_stats_strings[] = {
+	{"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)},
+	{"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)},
+	{"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)},
+	{"jitter_ns", offsetof(struct rte_latency_stats, jitter)},
+};
+
+#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \
+				sizeof(lat_stats_strings[0]))
+
+int32_t
+rte_latencystats_update(void)
+{
+	unsigned int i;
+	float *stats_ptr = NULL;
+	uint64_t values[NUM_LATENCY_STATS] = {0};
+	int ret;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++) {
+		stats_ptr = RTE_PTR_ADD(glob_stats,
+				lat_stats_strings[i].offset);
+		values[i] = (uint64_t)floor((*stats_ptr)/
+				latencystat_cycles_per_ns());
+	}
+
+	ret = rte_metrics_update_values(RTE_METRICS_GLOBAL,
+					latency_stats_index,
+					values, NUM_LATENCY_STATS);
+	if (ret < 0)
+		RTE_LOG(INFO, LATENCY_STATS, "Failed to push the stats\n");
+
+	return ret;
+}
+
+static void
+rte_latencystats_fill_values(struct rte_metric_value *values)
+{
+	unsigned int i;
+	float *stats_ptr = NULL;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++) {
+		stats_ptr = RTE_PTR_ADD(glob_stats,
+				lat_stats_strings[i].offset);
+		values[i].key = i;
+		values[i].value = (uint64_t)floor((*stats_ptr)/
+						latencystat_cycles_per_ns());
+	}
+}
+
+static uint16_t
+add_time_stamps(uint8_t pid __rte_unused,
+		uint16_t qid __rte_unused,
+		struct rte_mbuf **pkts,
+		uint16_t nb_pkts,
+		uint16_t max_pkts __rte_unused,
+		void *user_cb __rte_unused)
+{
+	unsigned int i;
+	uint64_t diff_tsc, now;
+
+	/*
+	 * For every sample interval,
+	 * time stamp is marked on one received packet.
+	 */
+	now = rte_rdtsc();
+	for (i = 0; i < nb_pkts; i++) {
+		diff_tsc = now - prev_tsc;
+		timer_tsc += diff_tsc;
+		if (timer_tsc >= samp_intvl) {
+			/*
+			 * TBD: Mark the timestamp only
+			 * if not already marked by the
+			 * hardware or the PMD.
+			 */
+			pkts[i]->timestamp = now;
+			timer_tsc = 0;
+		}
+		prev_tsc = now;
+		now = rte_rdtsc();
+	}
+
+	return nb_pkts;
+}
+
+static uint16_t
+calc_latency(uint8_t pid __rte_unused,
+		uint16_t qid __rte_unused,
+		struct rte_mbuf **pkts,
+		uint16_t nb_pkts,
+		void *_ __rte_unused)
+{
+	unsigned int i, cnt = 0;
+	uint64_t now;
+	float latency[nb_pkts];
+	static float prev_latency;
+	/*
+	 * Alpha represents degree of weighting decrease in EWMA,
+	 * a constant smoothing factor between 0 and 1. The value
+	 * is used below for measuring average latency.
+	 */
+	const float alpha = 0.2;
+
+	now = rte_rdtsc();
+	for (i = 0; i < nb_pkts; i++) {
+		if (pkts[i]->timestamp)
+			latency[cnt++] = now - pkts[i]->timestamp;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		/*
+		 * The jitter is calculated as statistical mean of interpacket
+		 * delay variation. The "jitter estimate" is computed by taking
+		 * the absolute values of the ipdv sequence and applying an
+		 * exponential filter with parameter 1/16 to generate the
+		 * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter,
+		 * D(i-1,i) is difference in latency of two consecutive packets
+		 * i-1 and i.
+		 * Reference: Calculated as per RFC 5481, sec 4.1,
+		 * RFC 3393 sec 4.5, RFC 1889 sec.
+		 */
+		glob_stats->jitter +=  (abs(prev_latency - latency[i])
+					- glob_stats->jitter)/16;
+		if (glob_stats->min_latency == 0)
+			glob_stats->min_latency = latency[i];
+		else if (latency[i] < glob_stats->min_latency)
+			glob_stats->min_latency = latency[i];
+		else if (latency[i] > glob_stats->max_latency)
+			glob_stats->max_latency = latency[i];
+		/*
+		 * The average latency is measured using exponential moving
+		 * average, i.e. using EWMA
+		 * https://en.wikipedia.org/wiki/Moving_average
+		 */
+		glob_stats->avg_latency +=
+			alpha * (latency[i] - glob_stats->avg_latency);
+		prev_latency = latency[i];
+	}
+
+	return nb_pkts;
+}
+
+int
+rte_latencystats_init(uint64_t app_samp_intvl,
+		rte_latency_stats_flow_type_fn user_cb)
+{
+	unsigned int i;
+	uint8_t pid;
+	uint16_t qid;
+	struct rxtx_cbs *cbs = NULL;
+	const uint8_t nb_ports = rte_eth_dev_count();
+	const char *ptr_strings[NUM_LATENCY_STATS] = {0};
+	const struct rte_memzone *mz = NULL;
+	const unsigned int flags = 0;
+
+	if (rte_memzone_lookup(MZ_RTE_LATENCY_STATS))
+		return -EEXIST;
+
+	/** Allocate stats in shared memory fo multi process support */
+	mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats),
+					rte_socket_id(), flags);
+	if (mz == NULL) {
+		RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n",
+			__func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	glob_stats = mz->addr;
+	samp_intvl = app_samp_intvl * latencystat_cycles_per_ns();
+
+	/** Register latency stats with stats library */
+	for (i = 0; i < NUM_LATENCY_STATS; i++)
+		ptr_strings[i] = lat_stats_strings[i].name;
+
+	latency_stats_index = rte_metrics_reg_names(ptr_strings,
+							NUM_LATENCY_STATS);
+	if (latency_stats_index < 0) {
+		RTE_LOG(DEBUG, LATENCY_STATS,
+			"Failed to register latency stats names\n");
+		return -1;
+	}
+
+	/** Register Rx/Tx callbacks */
+	for (pid = 0; pid < nb_ports; pid++) {
+		struct rte_eth_dev_info dev_info;
+		rte_eth_dev_info_get(pid, &dev_info);
+		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
+			cbs = &rx_cbs[pid][qid];
+			cbs->cb = rte_eth_add_first_rx_callback(pid, qid,
+					add_time_stamps, user_cb);
+			if (!cbs->cb)
+				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
+					"register Rx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
+			cbs = &tx_cbs[pid][qid];
+			cbs->cb =  rte_eth_add_tx_callback(pid, qid,
+					calc_latency, user_cb);
+			if (!cbs->cb)
+				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
+					"register Tx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+	}
+	return 0;
+}
+
+int
+rte_latencystats_uninit(void)
+{
+	uint8_t pid;
+	uint16_t qid;
+	int ret = 0;
+	struct rxtx_cbs *cbs = NULL;
+	const uint8_t nb_ports = rte_eth_dev_count();
+
+	/** De register Rx/Tx callbacks */
+	for (pid = 0; pid < nb_ports; pid++) {
+		struct rte_eth_dev_info dev_info;
+		rte_eth_dev_info_get(pid, &dev_info);
+		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
+			cbs = &rx_cbs[pid][qid];
+			ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb);
+			if (ret)
+				RTE_LOG(INFO, LATENCY_STATS, "failed to "
+					"remove Rx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
+			cbs = &tx_cbs[pid][qid];
+			ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb);
+			if (ret)
+				RTE_LOG(INFO, LATENCY_STATS, "failed to "
+					"remove Tx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+	}
+
+	return 0;
+}
+
+int
+rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size)
+{
+	unsigned int i;
+
+	if (names == NULL || size < NUM_LATENCY_STATS)
+		return NUM_LATENCY_STATS;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++)
+		snprintf(names[i].name, sizeof(names[i].name),
+				"%s", lat_stats_strings[i].name);
+
+	return NUM_LATENCY_STATS;
+}
+
+int
+rte_latencystats_get(struct rte_metric_value *values, uint16_t size)
+{
+	if (size < NUM_LATENCY_STATS || values == NULL)
+		return NUM_LATENCY_STATS;
+
+	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		const struct rte_memzone *mz;
+		mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS);
+		if (mz == NULL) {
+			RTE_LOG(ERR, LATENCY_STATS,
+				"Latency stats memzone not found\n");
+			return -ENOMEM;
+		}
+		glob_stats =  mz->addr;
+	}
+
+	/* Retrieve latency stats */
+	rte_latencystats_fill_values(values);
+
+	return NUM_LATENCY_STATS;
+}
diff --git a/lib/librte_latencystats/rte_latencystats.h b/lib/librte_latencystats/rte_latencystats.h
new file mode 100644
index 0000000..28c6dcf
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats.h
@@ -0,0 +1,154 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-2017 Intel Corporation. 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 _RTE_LATENCYSTATS_H_
+#define _RTE_LATENCYSTATS_H_
+
+/**
+ * @file
+ * RTE latency stats
+ *
+ * library to provide application and flow based latency stats.
+ */
+
+#include <rte_metrics.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  Note: This function pointer is for future flow based latency stats
+ *  implementation.
+ *
+ * Function type used for identifting flow types of a Rx packet.
+ *
+ * The callback function is called on Rx for each packet.
+ * This function is used for flow based latency calculations.
+ *
+ * @param pkt
+ *   Packet that has to be identified with its flow types.
+ * @param user_param
+ *   The arbitrary user parameter passed in by the application when
+ *   the callback was originally configured.
+ * @return
+ *   The flow_mask, representing the multiple flow types of a packet.
+ */
+typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt,
+							void *user_param);
+
+/**
+ *  Registers Rx/Tx callbacks for each active port, queue.
+ *
+ * @param samp_intvl
+ *  Sampling time period in nano seconds, at which packet
+ *  should be marked with time stamp.
+ * @param user_cb
+ *  Note: This param is for future flow based latency stats
+ *  implementation.
+ *  User callback to be called to get flow types of a packet.
+ *  Used for flow based latency calculation.
+ *  If the value is NULL, global stats will be calculated,
+ *  else flow based latency stats will be calculated.
+ *  For now just pass on the NULL value to this param.
+ *  @return
+ *   -1     : On error
+ *   -ENOMEM: On error
+ *    0     : On success
+ */
+int rte_latencystats_init(uint64_t samp_intvl,
+			rte_latency_stats_flow_type_fn user_cb);
+
+/**
+ * Calculates the latency and jitter values internally, exposing the updated
+ * values via *rte_latencystats_get* or the rte_metrics API.
+ * @return:
+ *  0      : on Success
+ *  < 0    : Error in updating values.
+ */
+int32_t rte_latencystats_update(void);
+
+/**
+ *  Removes registered Rx/Tx callbacks for each active port, queue.
+ *
+ *  @return
+ *   -1: On error
+ *    0: On success
+ */
+int rte_latencystats_uninit(void);
+
+/**
+ * Retrieve names of latency statistics
+ *
+ * @param names
+ *  Block of memory to insert names into. Must be at least size in capacity.
+ *  If set to NULL, function returns required capacity.
+ * @param size
+ *  Capacity of latency stats names (number of names).
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ */
+int rte_latencystats_get_names(struct rte_metric_name *names,
+				uint16_t size);
+
+/**
+ * Retrieve latency statistics.
+ *
+ * @param values
+ *   A pointer to a table of structure of type *rte_metric_value*
+ *   to be filled with latency statistics ids and values.
+ *   This parameter can be set to NULL if size is 0.
+ * @param size
+ *   The size of the stats table, which should be large enough to store
+ *   all the latency stats.
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ *   -ENOMEM: On failure.
+ */
+int rte_latencystats_get(struct rte_metric_value *values,
+			uint16_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_LATENCYSTATS_H_ */
diff --git a/lib/librte_latencystats/rte_latencystats_version.map b/lib/librte_latencystats/rte_latencystats_version.map
new file mode 100644
index 0000000..d240563
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats_version.map
@@ -0,0 +1,11 @@
+DPDK_17.02 {
+	global:
+
+	rte_latencystats_get;
+	rte_latencystats_get_names;
+	rte_latencystats_init;
+	rte_latencystats_uninit;
+	rte_latencystats_update;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 6aac5ac..1d36fad 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -100,7 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
 _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
-
+_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)  += -lrte_latencystats
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* [PATCH v9 7/7] app/test-pmd: add latency statistics calculation
  2017-01-18 15:05               ` [PATCH v9 0/7] Expanded statistics reporting Remy Horton
                                   ` (5 preceding siblings ...)
  2017-01-18 15:05                 ` [PATCH v9 6/7] lib: added new library for latency stats Remy Horton
@ 2017-01-18 15:05                 ` Remy Horton
  2017-02-03 10:33                 ` [PATCH v10 0/7] Expanded statistics reporting Remy Horton
  7 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw)
  To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan

From: Harry van Haaren <harry.van.haaren@intel.com>

This patch adds latency stats commandline argument to testpmd,
allowing to specify the lcore to use for latencystats updates.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/parameters.c | 20 +++++++++++++++++++-
 app/test-pmd/testpmd.c    | 37 +++++++++++++++++++++++++++++++++++++
 app/test-pmd/testpmd.h    |  6 +++++-
 3 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 28db8cd..30b60ba 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -1,7 +1,7 @@
 /*-
  *   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
@@ -149,6 +149,10 @@ usage(char* progname)
 	       "the packet will be enqueued into the rx drop-queue. "
 	       "If the drop-queue doesn't exist, the packet is dropped. "
 	       "By default drop-queue=127.\n");
+#ifdef RTE_LIBRTE_LATENCY_STATS
+	printf("  --latencystats=N: enable latency and jitter statistcs "
+	       "monitoring on lcore id N.\n");
+#endif
 	printf("  --crc-strip: enable CRC stripping by hardware.\n");
 	printf("  --enable-lro: enable large receive offload.\n");
 	printf("  --enable-rx-cksum: enable rx hardware checksum offload.\n");
@@ -526,6 +530,7 @@ launch_args_parse(int argc, char** argv)
 		{ "pkt-filter-report-hash",     1, 0, 0 },
 		{ "pkt-filter-size",            1, 0, 0 },
 		{ "pkt-filter-drop-queue",      1, 0, 0 },
+		{ "latencystats",               1, 0, 0 },
 		{ "crc-strip",                  0, 0, 0 },
 		{ "enable-lro",                 0, 0, 0 },
 		{ "enable-rx-cksum",            0, 0, 0 },
@@ -766,6 +771,19 @@ launch_args_parse(int argc, char** argv)
 						 "drop queue %d invalid - must"
 						 "be >= 0 \n", n);
 			}
+#ifdef RTE_LIBRTE_LATENCY_STATS
+			if (!strcmp(lgopts[opt_idx].name,
+				    "latencystats")) {
+				n = atoi(optarg);
+				if (n >= 0) {
+					latencystats_lcore_id = (lcoreid_t) n;
+					latencystats_enabled = 1;
+				} else
+					rte_exit(EXIT_FAILURE,
+						 "invalid lcore id %d for latencystats"
+						 " must be >= 0\n", n);
+			}
+#endif
 			if (!strcmp(lgopts[opt_idx].name, "crc-strip"))
 				rx_mode.hw_strip_crc = 1;
 			if (!strcmp(lgopts[opt_idx].name, "enable-lro"))
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index b31a300..524e758 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -83,6 +83,10 @@
 #ifdef RTE_LIBRTE_BITRATE
 #include <rte_bitrate.h>
 #endif
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_LATENCY_STATS
+#include <rte_latencystats.h>
+#endif
 
 #include "testpmd.h"
 
@@ -276,6 +280,20 @@ uint32_t bypass_timeout = RTE_BYPASS_TMT_OFF;
 
 #endif
 
+#ifdef RTE_LIBRTE_LATENCY_STATS
+
+/*
+ * Set when latency stats is enabled in the commandline
+ */
+uint8_t latencystats_enabled;
+
+/*
+ * Lcore ID to serive latency statistics.
+ */
+lcoreid_t latencystats_lcore_id = -1;
+
+#endif
+
 /*
  * Ethernet device configuration.
  */
@@ -955,6 +973,11 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
 			tics_datum = tics_current;
 		}
 #endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+		if (latencystats_lcore_id == rte_lcore_id())
+			rte_latencystats_update();
+#endif
+
 	} while (! fc->stopped);
 }
 
@@ -2108,6 +2131,9 @@ signal_handler(int signum)
 		/* uninitialize packet capture framework */
 		rte_pdump_uninit();
 #endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+		rte_latencystats_uninit();
+#endif
 		force_quit();
 		/* exit with the expected status */
 		signal(signum, SIG_DFL);
@@ -2169,6 +2195,17 @@ main(int argc, char** argv)
 	/* Init metrics library */
 	rte_metrics_init(rte_socket_id());
 
+#ifdef RTE_LIBRTE_LATENCY_STATS
+	if (latencystats_enabled != 0) {
+		int ret = rte_latencystats_init(1, NULL);
+		if (ret)
+			printf("Warning: latencystats init()"
+				" returned error %d\n",	ret);
+		printf("Latencystats running on lcore %d\n",
+			latencystats_lcore_id);
+	}
+#endif
+
 	/* Setup bitrate stats */
 #ifdef RTE_LIBRTE_BITRATE
 	bitrate_data = rte_stats_bitrate_create();
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 0a9a1af..35f7477 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -1,7 +1,7 @@
 /*-
  *   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
@@ -381,6 +381,10 @@ extern enum dcb_queue_mapping_mode dcb_q_mapping;
 extern uint16_t mbuf_data_size; /**< Mbuf data space size. */
 extern uint32_t param_total_num_mbufs;
 
+
+extern uint8_t latencystats_enabled;
+extern lcoreid_t latencystats_lcore_id;
+
 extern struct rte_fdir_conf fdir_conf;
 
 /*
-- 
2.5.5

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

* Re: [PATCH v7 5/6] lib: added new library for latency stats
  2017-01-17 16:25                       ` Jerin Jacob
@ 2017-01-18 20:11                         ` Olivier Matz
  2017-01-24 15:24                           ` Olivier MATZ
  0 siblings, 1 reply; 115+ messages in thread
From: Olivier Matz @ 2017-01-18 20:11 UTC (permalink / raw)
  To: Jerin Jacob
  Cc: Mcnamara, John, Horton, Remy, dev, Pattan, Reshma,
	Thomas Monjalon, Richardson, Bruce

Hi guys,

On Tue, 17 Jan 2017 21:55:16 +0530, Jerin Jacob
> Oliver,
> 
> Could you please suggest how to proceed further?
> 

Sorry for the lack of response. I know people are waiting for
me, but these days I have too many things to do at the same time, and
it's difficult to find time.

In few words (I'll provide more detailed answers to the thread by
friday): I expected to post the mbuf rework patchset for this release,
which includes the structure changes (Jerin's patch for arm access,
timestamp, port, nb_segs, refcnt changes). But the patchset is clearly
not ready yet, it needs a rebase, and it lacks test.

Jerin, I know that you submitted your patch a long time ago, and I'm
the only one to blame, please do not see any vendor preference in it.

I'll check friday what's the effective state of the patchset in my
workspace. If I can extract a minimal patch that only change the
structure, I'll send it for discussion. But from what I remember, the
mbuf structure rework depends on changing the way we access the refcnt,
so it can be moved to the 2nd cache line.

If that's not possible, I'll try propose some alternatives.

Regards,
Olivier

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

* Re: [PATCH v7 5/6] lib: added new library for latency stats
  2017-01-18 20:11                         ` Olivier Matz
@ 2017-01-24 15:24                           ` Olivier MATZ
  0 siblings, 0 replies; 115+ messages in thread
From: Olivier MATZ @ 2017-01-24 15:24 UTC (permalink / raw)
  To: Olivier Matz
  Cc: Jerin Jacob, Mcnamara, John, Horton, Remy, dev, Pattan, Reshma,
	Thomas Monjalon, Richardson, Bruce

On Wed, 18 Jan 2017 21:11:28 +0100, Olivier Matz
<olivier.matz@6wind.com> wrote:
> Hi guys,
> 
> On Tue, 17 Jan 2017 21:55:16 +0530, Jerin Jacob
> > Oliver,
> > 
> > Could you please suggest how to proceed further?
> >   
> 
> Sorry for the lack of response. I know people are waiting for
> me, but these days I have too many things to do at the same time, and
> it's difficult to find time.
> 
> In few words (I'll provide more detailed answers to the thread by
> friday): I expected to post the mbuf rework patchset for this release,
> which includes the structure changes (Jerin's patch for arm access,
> timestamp, port, nb_segs, refcnt changes). But the patchset is clearly
> not ready yet, it needs a rebase, and it lacks test.
> 
> Jerin, I know that you submitted your patch a long time ago, and I'm
> the only one to blame, please do not see any vendor preference in it.
> 
> I'll check friday what's the effective state of the patchset in my
> workspace. If I can extract a minimal patch that only change the
> structure, I'll send it for discussion. But from what I remember, the
> mbuf structure rework depends on changing the way we access the
> refcnt, so it can be moved to the 2nd cache line.
> 
> If that's not possible, I'll try propose some alternatives.

I just posted a mbuf RFC patchset [1]. I think it contains most
things that were mentioned on the ML. As checked with Thomas, it's too
late to have it included in 17.02.

I'll tend to agree with John that having the timestamp in the mbuf for
latency is not an ABI break, since it is added at the end of the
structure. So I won't oppose to add this field in the mbuf structure
for the release.

The mbuf rearm patch was not forgotten, but it took clearly too long to
be integrated. With the benefit of hindsight, it should have been
pushed without waiting the mbuf rework. Again, apologies for that, I
understand it's quite frustrating.

Anyway, tests or comments on my RFC patchset are welcome, so we can
integrate it at the beginning of the 17.05 cycle.

Regards,
Olivier

[1] http://dpdk.org/ml/archives/dev/2017-January/056187.html

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

* Re: [PATCH v9 1/7] lib: add information metrics library
  2017-01-18 15:05                 ` [PATCH v9 1/7] lib: add information metrics library Remy Horton
@ 2017-01-30 15:50                   ` Thomas Monjalon
  2017-01-30 21:44                     ` Remy Horton
  2017-01-31 13:13                     ` Mcnamara, John
  0 siblings, 2 replies; 115+ messages in thread
From: Thomas Monjalon @ 2017-01-30 15:50 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev

Hi Remy,

> This patch adds a new information metric library that allows other
> modules to register named metrics and update their values. It is
> intended to be independent of ethdev, rather than mixing ethdev
> and non-ethdev information in xstats.

I'm still not convinced by this library, and this introduction does
not help a lot.

I would like to thanks Harry for the review of this series.
If we had more opinions or enthousiasm about this patch, it would
be easier to accept this new library and assert it is the way to go.

It could be a matter of technical board discussion if we had a clear
explanation of the needs, the pros and cons of this design.

The overview for using this library should be given in the prog guide.


2017-01-18 15:05, Remy Horton:
> --- a/config/common_base
> +++ b/config/common_base
> @@ -593,3 +593,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
>  CONFIG_RTE_TEST_PMD=y
>  CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
>  CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
> +
> +#
> +# Compile the device metrics library
> +#
> +CONFIG_RTE_LIBRTE_METRICS=y

I know the config file is not so well sorted.
However it would be a bit more logical below CONFIG_RTE_LIBRTE_JOBSTATS.

> diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
> index 72d59b2..94f0f69 100644
> --- a/doc/api/doxy-api-index.md
> +++ b/doc/api/doxy-api-index.md
> @@ -150,4 +150,5 @@ There are many libraries, so their headers may be grouped by topics:
>    [common]             (@ref rte_common.h),
>    [ABI compat]         (@ref rte_compat.h),
>    [keepalive]          (@ref rte_keepalive.h),
> +  [Device Metrics]     (@ref rte_metrics.h),

No first letter uppercase in this list.

> --- a/doc/guides/rel_notes/release_17_02.rst
> +++ b/doc/guides/rel_notes/release_17_02.rst
> @@ -34,6 +34,12 @@ New Features
>  
>       Refer to the previous release notes for examples.
>  
> +   * **Added information metric library.**
> +
> +     A library that allows information metrics to be added and update. It is

update -> updated

added and updated by who?

> +     intended to provide a reporting mechanism that is independent of the
> +     ethdev library.

and independent of the cryptodev library?
Does it apply to other types of devices (cryptodev/eventdev)?

> +
>       This section is a comment. do not overwrite or remove it.
>       Also, make sure to start the actual text at the margin.
>       =========================================================

Your text should start below this line, and indented at the margin.

> @@ -205,6 +211,7 @@ The libraries prepended with a plus sign were incremented in this version.
>  .. code-block:: diff
>  
>       librte_acl.so.2
> +   + librte_bitratestats.so.1

not part of this patch

> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table
>  DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
>  DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
>  DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
> +DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics

insert it below librte_jobstats is a better choice

> --- /dev/null
> +++ b/lib/librte_metrics/rte_metrics.c
> +/**
> + * Internal stats metadata and value entry.
> + *
> + * @internal
> + * @param name
> + *   Name of metric
> + * @param value
> + *   Current value for metric
> + * @param idx_next_set
> + *   Index of next root element (zero for none)
> + * @param idx_next_metric
> + *   Index of next metric in set (zero for none)
> + *
> + * Only the root of each set needs idx_next_set but since it has to be
> + * assumed that number of sets could equal total number of metrics,
> + * having a separate set metadata table doesn't save any memory.
> + */
> +struct rte_metrics_meta_s {
> +	char name[RTE_METRICS_MAX_NAME_LEN];
> +	uint64_t value[RTE_MAX_ETHPORTS];
> +	uint64_t nonport_value;
> +	uint16_t idx_next_set;
> +	uint16_t idx_next_stat;
> +};

It would be a lot easier to read with comments near each field.
It would avoid to forget some fields like nonport_value in this struct.
You do not need to use a doxygen syntax in a .c file.

> --- /dev/null
> +++ b/lib/librte_metrics/rte_metrics.h
> +/**
> + * @file
> + *
> + * RTE Metrics module

RTE is not meaningful here.
Please prefer DPDK.

> + *
> + * Metric information is populated using a push model, where the
> + * information provider calls an update function on the relevant
> + * metrics. Currently only bulk querying of metrics is supported.
> + */

This description should explain who is a provider (drivers?) and who
is the reader (registered thread?).
What do you mean by "push model"? A callback is used?

> +/**
> + * Global (rather than port-specific) metric.

It does not say what kind of constant it is. A special metric id?

> + *
> + * When used instead of port number by rte_metrics_update_metric()
> + * or rte_metrics_update_metric(), the global metrics, which are
> + * not associated with any specific port, are updated.
> + */
> +#define RTE_METRICS_GLOBAL -1

I thought you agreed that "port" is not really a good wording.

> +/**
> + * A name-key lookup for metrics.
> + *
> + * An array of this structure is returned by rte_metrics_get_names().
> + * The struct rte_eth_stats references these names via their array index.

rte_eth_stats?

> + */
> +struct rte_metric_name {
> +	/** String describing metric */
> +	char name[RTE_METRICS_MAX_NAME_LEN];
> +};
[...]
> +/**
> + * Metric value structure.
> + *
> + * This structure is used by rte_metrics_get_values() to return metrics,
> + * which are statistics that are not generated by PMDs. It maps a name key,

Here we have a definition of what is a metric:
"statistics that are not generated by PMDs"
It could help in the introduction.

> + * which corresponds to an index in the array returned by
> + * rte_metrics_get_names().
> + */
> +struct rte_metric_value {
> +	/** Numeric identifier of metric. */
> +	uint16_t key;
> +	/** Value for metric */
> +	uint64_t value;
> +};
> +
> +
> +/**
> + * Initializes metric module. This function must be called from
> + * a primary process before metrics are used.

Why not integrating it in the global init?
Is there some performance drawbacks?

> + *
> + * @param socket_id
> + *   Socket to use for shared memory allocation.
> + */
> +void rte_metrics_init(int socket_id);
> +
> +/**
> + * Register a metric, making it available as a reporting parameter.
> + *
> + * Registering a metric is the way third-parties declare a parameter

third-party? You mean the provider?

> + * that they wish to be reported. Once registered, the associated
> + * numeric key can be obtained via rte_metrics_get_names(), which
> + * is required for updating said metric's value.
> + *
> + * @param name
> + *   Metric name
> + *
> + * @return
> + *  - Zero or positive: Success (index key of new metric)
> + *  - \b -EIO: Error, unable to access metrics shared memory
> + *    (rte_metrics_init() not called)
> + *  - \b -EINVAL: Error, invalid parameters
> + *  - \b -ENOMEM: Error, maximum metrics reached

Please, no extra formatting in doxygen.

> + */
> +int rte_metrics_reg_name(const char *name);
> +

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

* Re: [PATCH v9 1/7] lib: add information metrics library
  2017-01-30 15:50                   ` Thomas Monjalon
@ 2017-01-30 21:44                     ` Remy Horton
  2017-01-31 13:13                     ` Mcnamara, John
  1 sibling, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-01-30 21:44 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev


Some points addressed. Will cover other ones later.

On 30/01/2017 15:50, Thomas Monjalon wrote:
[..]

>> +CONFIG_RTE_LIBRTE_METRICS=y
> I know the config file is not so well sorted.
> However it would be a bit more logical below CONFIG_RTE_LIBRTE_JOBSTATS.

Done. Rebase merging doesn't help with sorting here.


>> +  [Device Metrics]     (@ref rte_metrics.h),
> No first letter uppercase in this list.
Fixed.

>> +     A library that allows information metrics to be added and update. It is
> update -> updated
Fixed.

> added and updated by who?
Elaborated.

>> +     intended to provide a reporting mechanism that is independent of the
>> +     ethdev library.
> and independent of the cryptodev library?

Yes. The aim is to have no sub-dependencies.

My original plan was to introduce some form of parameter registration 
scheme into xstats to replace the current hard-coded tables, since I 
suspected libbitrate/liblatency would not be the last additions. I 
decided to spin it out into a library in its own right, as it seemed 
cleaner than shoving a load of non-driver stuff into xstats.


> Does it apply to other types of devices (cryptodev/eventdev)?

I've not been following cryptodev/eventdev, but short answer yes.


>>       This section is a comment. do not overwrite or remove it.
>>       Also, make sure to start the actual text at the margin.
>>       =========================================================
> Your text should start below this line, and indented at the margin.

Fixed.


>> +   + librte_bitratestats.so.1
> not part of this patch

Fixed. Artefact of sorting out a merge mess-up.


>> +DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
> insert it below librte_jobstats is a better choice

Done.


>> +struct rte_metrics_meta_s {
>> +	char name[RTE_METRICS_MAX_NAME_LEN];
>> +	uint64_t value[RTE_MAX_ETHPORTS];
>> +	uint64_t nonport_value;
>> +	uint16_t idx_next_set;
>> +	uint16_t idx_next_stat;
>> +};
> It would be a lot easier to read with comments near each field.
> It would avoid to forget some fields like nonport_value in this struct.
> You do not need to use a doxygen syntax in a .c file.

Noted. Even though Doxygen isn't required, I think it preferable to use 
a consistent style in both .c and .h files.


>> + * RTE Metrics module
> RTE is not meaningful here.
> Please prefer DPDK.

Fixed.

>> + * Metric information is populated using a push model, where the
>> + * information provider calls an update function on the relevant
>> + * metrics. Currently only bulk querying of metrics is supported.
>> + */
> This description should explain who is a provider (drivers?) and who
> is the reader (registered thread?).

Noted. Will elaborate.


> What do you mean by "push model"? A callback is used?

Updating is done in response to producers having new information. In 
contrast in a pull model an update would happen in response to a polling 
by a consumer.

Originally (back in August I think) I used a pull model where producers 
would register callbacks that were called in response to 
rte_metrics_get() by a consumer, but that assumed that producers and 
consumers were within the same process. Using shared memory and making 
it ASLR-safe means not using pointers.

Aside: In this former pull model, port_id was passed verbatim to the 
producers' callbacks to interpret in whatever way they saw fit, so there 
was no inherant need to stop "magic" values outside the usual 0-255 used 
for port ids. Hence where the next thing originally came from...


>> +/**
>> + * Global (rather than port-specific) metric.
> It does not say what kind of constant it is. A special metric id?

Yes. Elaborated.


>> + *
>> + * When used instead of port number by rte_metrics_update_metric()
>> + * or rte_metrics_update_metric(), the global metrics, which are
>> + * not associated with any specific port, are updated.
>> + */
>> +#define RTE_METRICS_GLOBAL -1
>
> I thought you agreed that "port" is not really a good wording.

Certainly within the constant name. Don't see what's wrong with 
referring to it in description though.


>> + * An array of this structure is returned by rte_metrics_get_names().
>> + * The struct rte_eth_stats references these names via their array index.
> rte_eth_stats?

Good question - was going to put it down to cut'n'paste while baseing 
the descriptions on Olivier Matz's rewording, but that was for xstats..


>> + * Initializes metric module. This function must be called from
>> + * a primary process before metrics are used.
>
> Why not integrating it in the global init?
> Is there some performance drawbacks?

There shouldn't be any significant performance penalities, but I am not 
particularly fond in principle of initalising component libraries 
regardless of whether they are used. (Actually it was previously 
initalised on first use, but that had a race condition.)


>> + * Registering a metric is the way third-parties declare a parameter
> third-party? You mean the provider?

Yes.


>> + *  - \b -EINVAL: Error, invalid parameters
>> + *  - \b -ENOMEM: Error, maximum metrics reached
> Please, no extra formatting in doxygen.

Fixed.

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

* Re: [PATCH v9 1/7] lib: add information metrics library
  2017-01-30 15:50                   ` Thomas Monjalon
  2017-01-30 21:44                     ` Remy Horton
@ 2017-01-31 13:13                     ` Mcnamara, John
  2017-01-31 13:28                       ` Bruce Richardson
  1 sibling, 1 reply; 115+ messages in thread
From: Mcnamara, John @ 2017-01-31 13:13 UTC (permalink / raw)
  To: Thomas Monjalon, Horton, Remy; +Cc: dev



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Thomas Monjalon
> Sent: Monday, January 30, 2017 3:50 PM
> To: Horton, Remy <remy.horton@intel.com>
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v9 1/7] lib: add information metrics
> library
> 
> Hi Remy,
> 
> > This patch adds a new information metric library that allows other
> > modules to register named metrics and update their values. It is
> > intended to be independent of ethdev, rather than mixing ethdev and
> > non-ethdev information in xstats.
> 
> I'm still not convinced by this library, and this introduction does not
> help a lot.
> 
> I would like to thanks Harry for the review of this series.
> If we had more opinions or enthousiasm about this patch, it would be
> easier to accept this new library and assert it is the way to go.

Hi,

The RFCs for this library (initially two, merged into one) have been up since October, during the 16.11 timeframe. Comments were made and applied.

   http://dpdk.org/ml/archives/dev/2016-October/049571.html
   http://dpdk.org/ml/archives/dev/2016-October/048390.html

I'm concerned that these new comments/reservations are coming in very, very late in the 17.02 release cycle.

If there hasn't been a lot of opinions or enthusiasm then equally there hasn't been other reservations. If there had been we would have addressed them.


> It could be a matter of technical board discussion if we had a clear
> explanation of the needs, the pros and cons of this design.

We are happy to have the design discussed at the Technical Board. We would also like the inclusion of this library in RC3 to be discussed since that is still our desired outcome. 

We have, as any other company would have, customers awaiting features, developers committed to timelines, and testing and integration roadmaps. Blocking or delaying features at the last moment isn't an effective model that we, and I'm sure other companies, can work with.

As such, it is probably best, that all current and future RFCs are reviewed at the Technical Board and that the board gives an indication on whether the proposal is acceptable for upstreaming or not. 

> The overview for using this library should be given in the prog guide.

We will add a section to the Programmers Guide.

John

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

* Re: [PATCH v9 1/7] lib: add information metrics library
  2017-01-31 13:13                     ` Mcnamara, John
@ 2017-01-31 13:28                       ` Bruce Richardson
  2017-02-02 17:22                         ` Thomas Monjalon
  0 siblings, 1 reply; 115+ messages in thread
From: Bruce Richardson @ 2017-01-31 13:28 UTC (permalink / raw)
  To: Mcnamara, John; +Cc: Thomas Monjalon, Horton, Remy, dev

On Tue, Jan 31, 2017 at 01:13:11PM +0000, Mcnamara, John wrote:
> 
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Thomas Monjalon
> > Sent: Monday, January 30, 2017 3:50 PM
> > To: Horton, Remy <remy.horton@intel.com>
> > Cc: dev@dpdk.org
> > Subject: Re: [dpdk-dev] [PATCH v9 1/7] lib: add information metrics
> > library
> > 
> > Hi Remy,
> > 
> > > This patch adds a new information metric library that allows other
> > > modules to register named metrics and update their values. It is
> > > intended to be independent of ethdev, rather than mixing ethdev and
> > > non-ethdev information in xstats.
> > 
> > I'm still not convinced by this library, and this introduction does not
> > help a lot.
> > 
> > I would like to thanks Harry for the review of this series.
> > If we had more opinions or enthousiasm about this patch, it would be
> > easier to accept this new library and assert it is the way to go.
> 
> Hi,
> 
> The RFCs for this library (initially two, merged into one) have been up since October, during the 16.11 timeframe. Comments were made and applied.
> 
>    http://dpdk.org/ml/archives/dev/2016-October/049571.html
>    http://dpdk.org/ml/archives/dev/2016-October/048390.html
> 
> I'm concerned that these new comments/reservations are coming in very, very late in the 17.02 release cycle.
> 
> If there hasn't been a lot of opinions or enthusiasm then equally there hasn't been other reservations. If there had been we would have addressed them.
> 
> 
> > It could be a matter of technical board discussion if we had a clear
> > explanation of the needs, the pros and cons of this design.
> 
> We are happy to have the design discussed at the Technical Board. We would also like the inclusion of this library in RC3 to be discussed since that is still our desired outcome. 
> 
> We have, as any other company would have, customers awaiting features, developers committed to timelines, and testing and integration roadmaps. Blocking or delaying features at the last moment isn't an effective model that we, and I'm sure other companies, can work with.
> 
> As such, it is probably best, that all current and future RFCs are reviewed at the Technical Board and that the board gives an indication on whether the proposal is acceptable for upstreaming or not. 
> 

I would tend to agree with this. The tech board should indeed look to
insure that all RFCs and V1s have had some feedback on them well before
the merge deadline.

I don't believe it's fair on developers to suddenly give feedback at
merge-time and thereby prevent the patch making it into a release,
without giving time to do any rework.  This is especially true if the
patch had already been reviewed and acked, and so could be considered
"ready for merge".

The tech board should also discuss some reasonable guidelines
for this area. My opinion is that by the time RC1 is released, any
patches that have been reviewed, acked and have no outstanding
comments on them for e.g. 1 week, must be merged in for the release. Any
additional feedback thereafter should be considered "too late", and
should be addressed in the following release. This will help to
incentivize reviewers to review early, and also give developers some
degree of confidence that their patches will be merged in. We have
deadlines for submitters to get patches in, we should also have
deadlines for reviewers to object to those patches.

Regards,
/Bruce

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

* Re: [PATCH v9 1/7] lib: add information metrics library
  2017-01-31 13:28                       ` Bruce Richardson
@ 2017-02-02 17:22                         ` Thomas Monjalon
  0 siblings, 0 replies; 115+ messages in thread
From: Thomas Monjalon @ 2017-02-02 17:22 UTC (permalink / raw)
  To: Bruce Richardson, Mcnamara, John, Horton, Remy; +Cc: dev

2017-01-31 13:28, Bruce Richardson:
> On Tue, Jan 31, 2017 at 01:13:11PM +0000, Mcnamara, John wrote:
> > From: Thomas Monjalon
> > > Hi Remy,
> > > 
> > > > This patch adds a new information metric library that allows other
> > > > modules to register named metrics and update their values. It is
> > > > intended to be independent of ethdev, rather than mixing ethdev and
> > > > non-ethdev information in xstats.
> > > 
> > > I'm still not convinced by this library, and this introduction does not
> > > help a lot.
> > > 
> > > I would like to thanks Harry for the review of this series.
> > > If we had more opinions or enthousiasm about this patch, it would be
> > > easier to accept this new library and assert it is the way to go.
> > 
> > Hi,
> > 
> > The RFCs for this library (initially two, merged into one) have been up since October, during the 16.11 timeframe. Comments were made and applied.
> > 
> >    http://dpdk.org/ml/archives/dev/2016-October/049571.html
> >    http://dpdk.org/ml/archives/dev/2016-October/048390.html
> > 
> > I'm concerned that these new comments/reservations are coming in very, very late in the 17.02 release cycle.
> > 
> > If there hasn't been a lot of opinions or enthusiasm then equally there hasn't been other reservations. If there had been we would have addressed them.
> > 
> > 
> > > It could be a matter of technical board discussion if we had a clear
> > > explanation of the needs, the pros and cons of this design.
> > 
> > We are happy to have the design discussed at the Technical Board. We would also like the inclusion of this library in RC3 to be discussed since that is still our desired outcome. 
> > 
> > We have, as any other company would have, customers awaiting features, developers committed to timelines, and testing and integration roadmaps. Blocking or delaying features at the last moment isn't an effective model that we, and I'm sure other companies, can work with.
> > 
> > As such, it is probably best, that all current and future RFCs are reviewed at the Technical Board and that the board gives an indication on whether the proposal is acceptable for upstreaming or not. 
> > 
> 
> I would tend to agree with this. The tech board should indeed look to
> insure that all RFCs and V1s have had some feedback on them well before
> the merge deadline.
> 
> I don't believe it's fair on developers to suddenly give feedback at
> merge-time and thereby prevent the patch making it into a release,
> without giving time to do any rework.  This is especially true if the
> patch had already been reviewed and acked, and so could be considered
> "ready for merge".
> 
> The tech board should also discuss some reasonable guidelines
> for this area. My opinion is that by the time RC1 is released, any
> patches that have been reviewed, acked and have no outstanding
> comments on them for e.g. 1 week, must be merged in for the release. Any
> additional feedback thereafter should be considered "too late", and
> should be addressed in the following release. This will help to
> incentivize reviewers to review early, and also give developers some
> degree of confidence that their patches will be merged in. We have
> deadlines for submitters to get patches in, we should also have
> deadlines for reviewers to object to those patches.

We are talking about adding some new libraries in DPDK.
I think it is a special case where the submitter should make sure other
contributors agree to add such new capabilities in DPDK.

Saying there are some customers waiting for this feature to be upstreamed is
not a good argument. But it could help to explain what the goal of this series.

I agree this kind of comment should happen earlier and I'm sorry to not have
explicit them in earlier stages. That's why I suggest the Technical Board
could monitor this kind of proposal and make sure the discussion is progressing.

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

* [PATCH v10 0/7] Expanded statistics reporting
  2017-01-18 15:05               ` [PATCH v9 0/7] Expanded statistics reporting Remy Horton
                                   ` (6 preceding siblings ...)
  2017-01-18 15:05                 ` [PATCH v9 7/7] app/test-pmd: add latency statistics calculation Remy Horton
@ 2017-02-03 10:33                 ` Remy Horton
  2017-02-03 10:33                   ` [PATCH v10 1/7] lib: add information metrics library Remy Horton
                                     ` (8 more replies)
  7 siblings, 9 replies; 115+ messages in thread
From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patchset extends statistics reporting to include peak and
average data-rate metrics. It comes in two parts: a statistics
reporting library, and a bitrate calculation library that uses
it. This structure is intended to seperate statistic reporting
from ethdev and allow more flexible metric registration.

--
v10 changes:
* Rebased
* Relocated some config-related directives.
* Removed incorrect capitalisations in API docs.
* Formatting & detail corrections in release notes.
* Moved around struct member descriptions.
* Rewritten rte_metrics.h file description.
* Rewritten description of RTE_METRICS_GLOBAL.
* Used 'producers' and 'consumers' as terms.
* Removed markup (bold text) in Doxygen tags.
* Added programming guide section.

v9 changes:
* Updated .map files to reflect function changes in v8
* Fixed rte_malloc() of zero bytes in proc_info when no metrics exist
* Fixed rte_metrics_init not being called explicitly in testpmd

v8 changes:
* Release notes correction
* Updated copyright years
* rte_metric_init() takes socket id & must be explicitly called
* rte_metrics_reg_metric renamed to rte_metrics_reg_name()
* rte_metrics_update_metric() renamed to rte_metrics_update_value()
* Doxygen updates
* Changed malloc()/free() to rte_malloc()/rte_free()
* Removed redundant memset()
* rte_stats_bitrates_s renamed to rte_stats_bitrates_s
* Split mbuf change to own patch for visibility
* CYCLES_PER_NS now a static inline function
* latency: "hidden" pthread creation now has polling API instead.
* Struct declarations and variable definitions cleaned up
* Double initialization of the latency library now returns -EEXIST
* MAINTAINERS entry for layenctstats in correct section

v7 changes:
* RTE_METRICS_NONPORT renamed to RTE_METRICS_GLOBAL
* Multiple changes to rte_metrics.h doxygen documentation
* Split apart latency patch into lib, test-pmd, & proc_info parts
* Reordered patches by functionality
* Insufficent capacity return value changed from -ERANGE to actual size
* Cache alignment in bitrate library
* Tightened up const usage to avoid STATIC_CONST_CHAR_ARRAY warning
* Reshma reinstated as author for (now split) latency patch
* Rebase to master

v6 changes:
* Metrics display now has "Non port specific" rather than "port -1"
* Fixed sign issue in EWMA delta calculation
* Rebased to master

v5 changes:
* Updated Shared Library Versions in release notes
* Merged in Reshma's latencystats library

v4 changes:
* References to 16.11 changed to 17.02
* Fetching of non-port values was broken
* Added sanity checks to value fetching
* rte_stat_value renamed to rte_metric_value
* Corrected doxygen descriptions
* Added MAINTAINERS entries
* Added #ifdef directives to bitrate code in test-pmd

v3 changes:
* Marked rte_stats_bitrate_s as internal
* Minor integer roundoff correction
* Coding style corrections
* Removed spurious object allocation
* Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3.
* Reintroduced non-port values (RTE_METRICS_NONPORT)
* Added spinlocks to metric library
* Removed spurious test registration/update
* Added release notes entries

v2 changes:
* Uses a new metrics library rather than being part of ethdev


Harry van Haaren (3):
  mbuf: add a timestamp to the mbuf for latencystats
  lib: added new library for latency stats
  app/test-pmd: add latency statistics calculation

Remy Horton (3):
  lib: add information metrics library
  lib: add bitrate statistics library
  app/test-pmd: add bitrate statistics calculation

Reshma Pattan (1):
  app/proc_info: add metrics displaying

 MAINTAINERS                                        |  12 +
 app/proc_info/main.c                               |  79 ++++-
 app/test-pmd/parameters.c                          |  20 +-
 app/test-pmd/testpmd.c                             |  78 ++++-
 app/test-pmd/testpmd.h                             |   6 +-
 config/common_base                                 |  15 +
 doc/api/doxy-api-index.md                          |   3 +
 doc/api/doxy-api.conf                              |   3 +
 doc/guides/prog_guide/index.rst                    |   1 +
 doc/guides/prog_guide/metrics_lib.rst              | 297 +++++++++++++++++
 doc/guides/rel_notes/release_17_02.rst             |  20 ++
 lib/Makefile                                       |   3 +
 lib/librte_bitratestats/Makefile                   |  53 +++
 lib/librte_bitratestats/rte_bitrate.c              | 132 ++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++
 .../rte_bitratestats_version.map                   |   9 +
 lib/librte_latencystats/Makefile                   |  56 ++++
 lib/librte_latencystats/rte_latencystats.c         | 366 +++++++++++++++++++++
 lib/librte_latencystats/rte_latencystats.h         | 154 +++++++++
 .../rte_latencystats_version.map                   |  11 +
 lib/librte_mbuf/rte_mbuf.h                         |   3 +
 lib/librte_metrics/Makefile                        |  51 +++
 lib/librte_metrics/rte_metrics.c                   | 299 +++++++++++++++++
 lib/librte_metrics/rte_metrics.h                   | 240 ++++++++++++++
 lib/librte_metrics/rte_metrics_version.map         |  13 +
 mk/rte.app.mk                                      |   3 +
 26 files changed, 2003 insertions(+), 4 deletions(-)
 create mode 100644 doc/guides/prog_guide/metrics_lib.rst
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map
 create mode 100644 lib/librte_latencystats/Makefile
 create mode 100644 lib/librte_latencystats/rte_latencystats.c
 create mode 100644 lib/librte_latencystats/rte_latencystats.h
 create mode 100644 lib/librte_latencystats/rte_latencystats_version.map
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

-- 
2.5.5

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

* [PATCH v10 1/7] lib: add information metrics library
  2017-02-03 10:33                 ` [PATCH v10 0/7] Expanded statistics reporting Remy Horton
@ 2017-02-03 10:33                   ` Remy Horton
  2017-02-03 10:33                   ` [PATCH v10 2/7] app/proc_info: add metrics displaying Remy Horton
                                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patch adds a new information metrics library. This Metrics
library implements a mechanism by which producers can publish
numeric information for later querying by consumers. Metrics
themselves are statistics that are not generated by PMDs, and
hence are not reported via ethdev extended statistics.

Metric information is populated using a push model, where
producers update the values contained within the metric
library by calling an update function on the relevant metrics.
Consumers receive metric information by querying the central
metric data, which is held in shared memory.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                |   4 +
 config/common_base                         |   5 +
 doc/api/doxy-api-index.md                  |   1 +
 doc/api/doxy-api.conf                      |   1 +
 doc/guides/prog_guide/index.rst            |   1 +
 doc/guides/prog_guide/metrics_lib.rst      | 180 +++++++++++++++++
 doc/guides/rel_notes/release_17_02.rst     |   9 +
 lib/Makefile                               |   1 +
 lib/librte_metrics/Makefile                |  51 +++++
 lib/librte_metrics/rte_metrics.c           | 299 +++++++++++++++++++++++++++++
 lib/librte_metrics/rte_metrics.h           | 240 +++++++++++++++++++++++
 lib/librte_metrics/rte_metrics_version.map |  13 ++
 mk/rte.app.mk                              |   2 +
 13 files changed, 807 insertions(+)
 create mode 100644 doc/guides/prog_guide/metrics_lib.rst
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 27f999b..eceebaa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -627,6 +627,10 @@ F: lib/librte_jobstats/
 F: examples/l2fwd-jobstats/
 F: doc/guides/sample_app_ug/l2_forward_job_stats.rst
 
+Metrics
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_metrics/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index 71a4fcb..b819932 100644
--- a/config/common_base
+++ b/config/common_base
@@ -501,6 +501,11 @@ CONFIG_RTE_LIBRTE_EFD=y
 CONFIG_RTE_LIBRTE_JOBSTATS=y
 
 #
+# Compile the device metrics library
+#
+CONFIG_RTE_LIBRTE_METRICS=y
+
+#
 # Compile librte_lpm
 #
 CONFIG_RTE_LIBRTE_LPM=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index eb39f69..26a26b7 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -156,4 +156,5 @@ There are many libraries, so their headers may be grouped by topics:
   [common]             (@ref rte_common.h),
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
+  [device metrics]     (@ref rte_metrics.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index b8a5fd8..e2e070f 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -53,6 +53,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_mbuf \
                           lib/librte_mempool \
                           lib/librte_meter \
+                          lib/librte_metrics \
                           lib/librte_net \
                           lib/librte_pdump \
                           lib/librte_pipeline \
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index 7f825cb..fea651c 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -62,6 +62,7 @@ Programmer's Guide
     packet_classif_access_ctrl
     packet_framework
     vhost_lib
+    metrics_lib
     port_hotplug_framework
     source_org
     dev_kit_build_system
diff --git a/doc/guides/prog_guide/metrics_lib.rst b/doc/guides/prog_guide/metrics_lib.rst
new file mode 100644
index 0000000..87f806d
--- /dev/null
+++ b/doc/guides/prog_guide/metrics_lib.rst
@@ -0,0 +1,180 @@
+..  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.
+
+.. _Metrics_Library:
+
+Metrics Library
+===============
+
+The Metrics library implements a mechanism by which *producers* can
+publish numeric information for later querying by *consumers*. In
+practice producers will typically be other libraries or primary
+processes, whereas consumers will typically be applications.
+
+Metrics themselves are statistics that are not generated by PMDs. Metric
+information is populated using a push model, where producers update the
+values contained within the metric library by calling an update function
+on the relevant metrics. Consumers receive metric information by querying
+the central metric data, which is held in shared memory.
+
+For each metric, a separate value is maintained for each port id, and
+when publishing metric values the producers need to specify which port is
+being updated. In addition there is a special id ``RTE_METRICS_GLOBAL``
+that is intended for global statistics that are not associated with any
+individual device. Since the metrics library is self-contained, the only
+restriction on port numbers is that they are less than ``RTE_MAX_ETHPORTS``
+- there is no requirement for the ports to actually exist.
+
+Initialising the library
+------------------------
+
+Before the library can be used, it has to be initialized by calling
+``rte_metrics_init()`` which sets up the metric store in shared memory.
+This is where producers will publish metric information to, and where
+consumers will query it from.
+
+.. code-block:: c
+
+    rte_metrics_init(rte_socket_id());
+
+This function **must** be called from a primary process, but otherwise
+producers and consumers can be in either primary or secondary processes.
+
+Registering metrics
+-------------------
+
+Metrics must first be *registered*, which is the way producers declare
+the names of the metrics they will be publishing. Registration can either
+be done individually, or a set of metrics can be registered as a group.
+Individual registration is done using ``rte_metrics_reg_name()``:
+
+.. code-block:: c
+
+    id_1 = rte_metrics_reg_name("mean_bits_in");
+    id_2 = rte_metrics_reg_name("mean_bits_out");
+    id_3 = rte_metrics_reg_name("peak_bits_in");
+    id_4 = rte_metrics_reg_name("peak_bits_out");
+
+or alternatively, a set of metrics can be registered together using
+``rte_metrics_reg_names()``:
+
+.. code-block:: c
+
+    const char * const names[] = {
+        "mean_bits_in", "mean_bits_out",
+        "peak_bits_in", "peak_bits_out",
+    };
+    id_set = rte_metrics_reg_names(&names[0], 4);
+
+If the return value is negative, it means registration failed. Otherwise
+the return value is the *key* for the metric, which is used when updating
+values. A table mapping together these key values and the metrics' names
+can be obtained using ``rte_metrics_get_names()``.
+
+Updating metric values
+----------------------
+
+Once registered, producers can update the metric for a given port using
+the ``rte_metrics_update_value()`` function. This uses the metric key
+that is returned when registering the metric, and can also be looked up
+using ``rte_metrics_get_names()``.
+
+.. code-block:: c
+
+    rte_metrics_update_value(port_id, id_1, values[0]);
+    rte_metrics_update_value(port_id, id_2, values[1]);
+    rte_metrics_update_value(port_id, id_3, values[2]);
+    rte_metrics_update_value(port_id, id_4, values[3]);
+
+if metrics were registered as a single set, they can either be updated
+individually using ``rte_metrics_update_value()``, or updated together
+using the ``rte_metrics_update_values()`` function:
+
+.. code-block:: c
+
+    rte_metrics_update_value(port_id, id_set, values[0]);
+    rte_metrics_update_value(port_id, id_set + 1, values[1]);
+    rte_metrics_update_value(port_id, id_set + 2, values[2]);
+    rte_metrics_update_value(port_id, id_set + 3, values[3]);
+
+    rte_metrics_update_values(port_id, id_set, values, 4);
+
+Note that ``rte_metrics_update_values()`` cannot be used to update
+metric values from *multiple* *sets*, as there is no guarantee two
+sets registered one after the other have contiguous id values.
+
+Querying metrics
+----------------
+
+Consumers can obtain metric values by querying the metrics library using
+the ``rte_metrics_get_values()`` function that return an array of
+``struct rte_metric_value``. Each entry within this array contains a metric
+value and its associated key. A key-name mapping can be obtained using the
+``rte_metrics_get_names()`` function that returns an array of
+``struct rte_metric_name`` that is indexed by the key. The following will
+print out all metrics for a given port:
+
+.. code-block:: c
+
+    void print_metrics() {
+        struct rte_metric_name *names;
+        int len;
+
+        len = rte_metrics_get_names(NULL, 0);
+        if (len < 0) {
+            printf("Cannot get metrics count\n");
+            return;
+        }
+        if (len == 0) {
+            printf("No metrics to display (none have been registered)\n");
+            return;
+        }
+        metrics = malloc(sizeof(struct rte_metric_value) * len);
+        names =  malloc(sizeof(struct rte_metric_name) * len);
+        if (metrics == NULL || names == NULL) {
+            printf("Cannot allocate memory\n");
+            free(metrics);
+            free(names);
+            return;
+        }
+        ret = rte_metrics_get_values(port_id, metrics, len);
+        if (ret < 0 || ret > len) {
+            printf("Cannot get metrics values\n");
+            free(metrics);
+            free(names);
+            return;
+        }
+        printf("Metrics for port %i:\n", port_id);
+        for (i = 0; i < len; i++)
+            printf("  %s: %"PRIu64"\n",
+                names[metrics[i].key].name, metrics[i].value);
+        free(metrics);
+        free(names);
+    }
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 83519dc..68581e4 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -38,6 +38,14 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **Added information metric library.**
+
+  A library that allows information metrics to be added and updated
+  by producers, typically other libraries, for later retrieval by
+  consumers such as applications. It is intended to provide a
+  reporting mechanism that is independent of other libraries such
+  as ethdev.
+
 * **Added generic EAL API for I/O device memory read/write operations.**
 
   This API introduces 8-bit, 16-bit, 32bit, 64bit I/O device
@@ -355,6 +363,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_mbuf.so.2
      librte_mempool.so.2
      librte_meter.so.1
+   + librte_metrics.so.1
      librte_net.so.1
      librte_pdump.so.1
      librte_pipeline.so.3
diff --git a/lib/Makefile b/lib/Makefile
index 4178325..29f6a81 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -49,6 +49,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
 DIRS-$(CONFIG_RTE_LIBRTE_NET) += librte_net
 DIRS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += librte_ip_frag
 DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats
+DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power
 DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter
 DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched
diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile
new file mode 100644
index 0000000..8d6e23a
--- /dev/null
+++ b/lib/librte_metrics/Makefile
@@ -0,0 +1,51 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_metrics.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_metrics_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c
new file mode 100644
index 0000000..889d377
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.c
@@ -0,0 +1,299 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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 <string.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_lcore.h>
+#include <rte_memzone.h>
+#include <rte_spinlock.h>
+
+#define RTE_METRICS_MAX_METRICS 256
+#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS"
+
+/**
+ * Internal stats metadata and value entry.
+ *
+ * @internal
+ */
+struct rte_metrics_meta_s {
+	/** Name of metric */
+	char name[RTE_METRICS_MAX_NAME_LEN];
+	/** Current value for metric */
+	uint64_t value[RTE_MAX_ETHPORTS];
+	/** Used for global metrics */
+	uint64_t nonport_value;
+	/** Index of next root element (zero for none) */
+	uint16_t idx_next_set;
+	/** Index of next metric in set (zero for none) */
+	uint16_t idx_next_stat;
+};
+
+/**
+ * Internal stats info structure.
+ *
+ * @internal
+ * Offsets into metadata are used instead of pointers because ASLR
+ * means that having the same physical addresses in different
+ * processes is not guaranteed.
+ */
+struct rte_metrics_data_s {
+	/**   Index of last metadata entry with valid data.
+	 * This value is not valid if cnt_stats is zero.
+	 */
+	uint16_t idx_last_set;
+	/**   Number of metrics. */
+	uint16_t cnt_stats;
+	/** Metric data memory block. */
+	struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS];
+	/** Metric data access lock */
+	rte_spinlock_t lock;
+};
+
+void
+rte_metrics_init(int socket_id)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone != NULL)
+		return;
+	memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME,
+		sizeof(struct rte_metrics_data_s), socket_id, 0);
+	if (memzone == NULL)
+		rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
+	stats = memzone->addr;
+	memset(stats, 0, sizeof(struct rte_metrics_data_s));
+	rte_spinlock_init(&stats->lock);
+}
+
+int
+rte_metrics_reg_name(const char *name)
+{
+	const char * const list_names[] = {name};
+
+	return rte_metrics_reg_names(list_names, 1);
+}
+
+int
+rte_metrics_reg_names(const char * const *names, uint16_t cnt_names)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	uint16_t idx_base;
+
+	/* Some sanity checks */
+	if (cnt_names < 1 || names == NULL)
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS)
+		return -ENOMEM;
+
+	rte_spinlock_lock(&stats->lock);
+
+	/* Overwritten later if this is actually first set.. */
+	stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats;
+
+	stats->idx_last_set = idx_base = stats->cnt_stats;
+
+	for (idx_name = 0; idx_name < cnt_names; idx_name++) {
+		entry = &stats->metadata[idx_name + stats->cnt_stats];
+		strncpy(entry->name, names[idx_name],
+			RTE_METRICS_MAX_NAME_LEN);
+		memset(entry->value, 0, sizeof(entry->value));
+		entry->idx_next_stat = idx_name + stats->cnt_stats + 1;
+	}
+	entry->idx_next_stat = 0;
+	entry->idx_next_set = 0;
+	stats->cnt_stats += cnt_names;
+
+	rte_spinlock_unlock(&stats->lock);
+
+	return idx_base;
+}
+
+int
+rte_metrics_update_value(int port_id, uint16_t key, const uint64_t value)
+{
+	return rte_metrics_update_values(port_id, key, &value, 1);
+}
+
+int
+rte_metrics_update_values(int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_metric;
+	uint16_t idx_value;
+	uint16_t cnt_setsize;
+
+	if (port_id != RTE_METRICS_GLOBAL &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	rte_spinlock_lock(&stats->lock);
+	idx_metric = key;
+	cnt_setsize = 1;
+	while (idx_metric < stats->cnt_stats) {
+		entry = &stats->metadata[idx_metric];
+		if (entry->idx_next_stat == 0)
+			break;
+		cnt_setsize++;
+		idx_metric++;
+	}
+	/* Check update does not cross set border */
+	if (count > cnt_setsize) {
+		rte_spinlock_unlock(&stats->lock);
+		return -ERANGE;
+	}
+
+	if (port_id == RTE_METRICS_GLOBAL)
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].nonport_value =
+				values[idx_value];
+		}
+	else
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].value[port_id] =
+				values[idx_value];
+		}
+	rte_spinlock_unlock(&stats->lock);
+	return 0;
+}
+
+int
+rte_metrics_get_names(struct rte_metric_name *names,
+	uint16_t capacity)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+	if (names != NULL) {
+		if (capacity < stats->cnt_stats) {
+			return_value = stats->cnt_stats;
+			rte_spinlock_unlock(&stats->lock);
+			return return_value;
+		}
+		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
+			strncpy(names[idx_name].name,
+				stats->metadata[idx_name].name,
+				RTE_METRICS_MAX_NAME_LEN);
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
+
+int
+rte_metrics_get_values(int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	if (port_id != RTE_METRICS_GLOBAL &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+
+	if (values != NULL) {
+		if (capacity < stats->cnt_stats) {
+			return_value = stats->cnt_stats;
+			rte_spinlock_unlock(&stats->lock);
+			return return_value;
+		}
+		if (port_id == RTE_METRICS_GLOBAL)
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->nonport_value;
+			}
+		else
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->value[port_id];
+			}
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
new file mode 100644
index 0000000..71c57c6
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.h
@@ -0,0 +1,240 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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.
+ */
+
+/**
+ * @file
+ *
+ * DPDK Metrics module
+ *
+ * Metrics are statistics that are not generated by PMDs, and hence
+ * are better reported through a mechanism that is independent from
+ * the ethdev-based extended statistics. Providers will typically
+ * be other libraries and consumers will typically be applications.
+ *
+ * Metric information is populated using a push model, where producers
+ * update the values contained within the metric library by calling
+ * an update function on the relevant metrics. Consumers receive
+ * metric information by querying the central metric data, which is
+ * held in shared memory. Currently only bulk querying of metrics
+ * by consumers is supported.
+ */
+
+#ifndef _RTE_METRICS_H_
+#define _RTE_METRICS_H_
+
+/** Maximum length of metric name (including null-terminator) */
+#define RTE_METRICS_MAX_NAME_LEN 64
+
+/**
+ * Global (rather than port-specific) metric special id.
+ *
+ * When used for the port_id parameter when calling
+ * rte_metrics_update_metric() or rte_metrics_update_metric(),
+ * the global metrics, which are not associated with any specific
+ * port (i.e. device), are updated.
+ */
+#define RTE_METRICS_GLOBAL -1
+
+
+/**
+ * A name-key lookup for metrics.
+ *
+ * An array of this structure is returned by rte_metrics_get_names().
+ * The struct rte_metric_value references these names via their array index.
+ */
+struct rte_metric_name {
+	/** String describing metric */
+	char name[RTE_METRICS_MAX_NAME_LEN];
+};
+
+
+/**
+ * Metric value structure.
+ *
+ * This structure is used by rte_metrics_get_values() to return metrics,
+ * which are statistics that are not generated by PMDs. It maps a name key,
+ * which corresponds to an index in the array returned by
+ * rte_metrics_get_names().
+ */
+struct rte_metric_value {
+	/** Numeric identifier of metric. */
+	uint16_t key;
+	/** Value for metric */
+	uint64_t value;
+};
+
+
+/**
+ * Initializes metric module. This function must be called from
+ * a primary process before metrics are used.
+ *
+ * @param socket_id
+ *   Socket to use for shared memory allocation.
+ */
+void rte_metrics_init(int socket_id);
+
+/**
+ * Register a metric, making it available as a reporting parameter.
+ *
+ * Registering a metric is the way producers declare a parameter
+ * that they wish to be reported. Once registered, the associated
+ * numeric key can be obtained via rte_metrics_get_names(), which
+ * is required for updating said metric's value.
+ *
+ * @param name
+ *   Metric name
+ *
+ * @return
+ *  - Zero or positive: Success (index key of new metric)
+ *  - -EIO: Error, unable to access metrics shared memory
+ *    (rte_metrics_init() not called)
+ *  - -EINVAL: Error, invalid parameters
+ *  - -ENOMEM: Error, maximum metrics reached
+ */
+int rte_metrics_reg_name(const char *name);
+
+/**
+ * Register a set of metrics.
+ *
+ * This is a bulk version of rte_metrics_reg_metrics() and aside from
+ * handling multiple keys at once is functionally identical.
+ *
+ * @param names
+ *   List of metric names
+ *
+ * @param cnt_names
+ *   Number of metrics in set
+ *
+ * @return
+ *  - Zero or positive: Success (index key of start of set)
+ *  - -EIO: Error, unable to access metrics shared memory
+ *    (rte_metrics_init() not called)
+ *  - -EINVAL: Error, invalid parameters
+ *  - -ENOMEM: Error, maximum metrics reached
+ */
+int rte_metrics_reg_names(const char * const *names, uint16_t cnt_names);
+
+/**
+ * Get metric name-key lookup table.
+ *
+ * @param names
+ *   A struct rte_metric_name array of at least *capacity* in size to
+ *   receive key names. If this is NULL, function returns the required
+ *   number of elements for this array.
+ *
+ * @param capacity
+ *   Size (number of elements) of struct rte_metric_name array.
+ *   Disregarded if names is NULL.
+ *
+ * @return
+ *   - Positive value above capacity: error, *names* is too small.
+ *     Return value is required size.
+ *   - Positive value equal or less than capacity: Success. Return
+ *     value is number of elements filled in.
+ *   - Negative value: error.
+ */
+int rte_metrics_get_names(
+	struct rte_metric_name *names,
+	uint16_t capacity);
+
+/**
+ * Get metric value table.
+ *
+ * @param port_id
+ *   Port id to query
+ *
+ * @param values
+ *   A struct rte_metric_value array of at least *capacity* in size to
+ *   receive metric ids and values. If this is NULL, function returns
+ *   the required number of elements for this array.
+ *
+ * @param capacity
+ *   Size (number of elements) of struct rte_metric_value array.
+ *   Disregarded if names is NULL.
+ *
+ * @return
+ *   - Positive value above capacity: error, *values* is too small.
+ *     Return value is required size.
+ *   - Positive value equal or less than capacity: Success. Return
+ *     value is number of elements filled in.
+ *   - Negative value: error.
+ */
+int rte_metrics_get_values(
+	int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity);
+
+/**
+ * Updates a metric
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Id of metric to update
+ * @param value
+ *   New value
+ *
+ * @return
+ *   - -EIO if unable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_value(
+	int port_id,
+	uint16_t key,
+	const uint64_t value);
+
+/**
+ * Updates a metric set. Note that it is an error to try to
+ * update across a set boundary.
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Base id of metrics set to update
+ * @param values
+ *   Set of new values
+ * @param count
+ *   Number of new values
+ *
+ * @return
+ *   - -ERANGE if count exceeds metric set size
+ *   - -EIO if upable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_values(
+	int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count);
+
+#endif
diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map
new file mode 100644
index 0000000..ee28fa0
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics_version.map
@@ -0,0 +1,13 @@
+DPDK_17.02 {
+	global:
+
+	rte_metrics_get_names;
+	rte_metrics_get_values;
+	rte_metrics_init;
+	rte_metrics_reg_name;
+	rte_metrics_reg_names;
+	rte_metrics_update_value;
+	rte_metrics_update_values;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 0d0a970..46de3d3 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -99,6 +99,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER)        += -lrte_reorder
+_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* [PATCH v10 2/7] app/proc_info: add metrics displaying
  2017-02-03 10:33                 ` [PATCH v10 0/7] Expanded statistics reporting Remy Horton
  2017-02-03 10:33                   ` [PATCH v10 1/7] lib: add information metrics library Remy Horton
@ 2017-02-03 10:33                   ` Remy Horton
  2017-02-03 10:33                   ` [PATCH v10 3/7] lib: add bitrate statistics library Remy Horton
                                     ` (6 subsequent siblings)
  8 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw)
  To: dev; +Cc: Reshma Pattan, Thomas Monjalon

From: Reshma Pattan <reshma.pattan@intel.com>

Modify the dpdk-procinfo process to display the newly added metrics.
Added new command line option "--metrics" to display metrics.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/proc_info/main.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 78 insertions(+), 1 deletion(-)

diff --git a/app/proc_info/main.c b/app/proc_info/main.c
index 2c56d10..f513669 100644
--- a/app/proc_info/main.c
+++ b/app/proc_info/main.c
@@ -1,7 +1,7 @@
 /*
  *   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
@@ -57,6 +57,7 @@
 #include <rte_atomic.h>
 #include <rte_branch_prediction.h>
 #include <rte_string_fns.h>
+#include <rte_metrics.h>
 
 /* Maximum long option length for option parsing. */
 #define MAX_LONG_OPT_SZ 64
@@ -68,6 +69,8 @@ static uint32_t enabled_port_mask;
 static uint32_t enable_stats;
 /**< Enable xstats. */
 static uint32_t enable_xstats;
+/**< Enable metrics. */
+static uint32_t enable_metrics;
 /**< Enable stats reset. */
 static uint32_t reset_stats;
 /**< Enable xstats reset. */
@@ -85,6 +88,8 @@ proc_info_usage(const char *prgname)
 		"  --stats: to display port statistics, enabled by default\n"
 		"  --xstats: to display extended port statistics, disabled by "
 			"default\n"
+		"  --metrics: to display derived metrics of the ports, disabled by "
+			"default\n"
 		"  --stats-reset: to reset port statistics\n"
 		"  --xstats-reset: to reset port extended statistics\n",
 		prgname);
@@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv)
 		{"stats", 0, NULL, 0},
 		{"stats-reset", 0, NULL, 0},
 		{"xstats", 0, NULL, 0},
+		{"metrics", 0, NULL, 0},
 		{"xstats-reset", 0, NULL, 0},
 		{NULL, 0, 0, 0}
 	};
@@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv)
 			else if (!strncmp(long_option[option_index].name, "xstats",
 					MAX_LONG_OPT_SZ))
 				enable_xstats = 1;
+			else if (!strncmp(long_option[option_index].name,
+					"metrics",
+					MAX_LONG_OPT_SZ))
+				enable_metrics = 1;
 			/* Reset stats */
 			if (!strncmp(long_option[option_index].name, "stats-reset",
 					MAX_LONG_OPT_SZ))
@@ -301,6 +311,67 @@ nic_xstats_clear(uint8_t port_id)
 	printf("\n  NIC extended statistics for port %d cleared\n", port_id);
 }
 
+static void
+metrics_display(int port_id)
+{
+	struct rte_metric_value *metrics;
+	struct rte_metric_name *names;
+	int len, ret;
+	static const char *nic_stats_border = "########################";
+
+	len = rte_metrics_get_names(NULL, 0);
+	if (len < 0) {
+		printf("Cannot get metrics count\n");
+		return;
+	}
+	if (len == 0) {
+		printf("No metrics to display (none have been registered)\n");
+		return;
+	}
+
+	metrics = rte_malloc("proc_info_metrics",
+		sizeof(struct rte_metric_value) * len, 0);
+	if (metrics == NULL) {
+		printf("Cannot allocate memory for metrics\n");
+		return;
+	}
+
+	names =  rte_malloc(NULL, sizeof(struct rte_metric_name) * len, 0);
+	if (names == NULL) {
+		printf("Cannot allocate memory for metrcis names\n");
+		rte_free(metrics);
+		return;
+	}
+
+	if (len != rte_metrics_get_names(names, len)) {
+		printf("Cannot get metrics names\n");
+		rte_free(metrics);
+		rte_free(names);
+		return;
+	}
+
+	if (port_id == RTE_METRICS_GLOBAL)
+		printf("###### Non port specific metrics  #########\n");
+	else
+		printf("###### metrics for port %-2d #########\n", port_id);
+	printf("%s############################\n", nic_stats_border);
+	ret = rte_metrics_get_values(port_id, metrics, len);
+	if (ret < 0 || ret > len) {
+		printf("Cannot get metrics values\n");
+		rte_free(metrics);
+		rte_free(names);
+		return;
+	}
+
+	int i;
+	for (i = 0; i < len; i++)
+		printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value);
+
+	printf("%s############################\n", nic_stats_border);
+	rte_free(metrics);
+	rte_free(names);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -360,8 +431,14 @@ main(int argc, char **argv)
 				nic_stats_clear(i);
 			else if (reset_xstats)
 				nic_xstats_clear(i);
+			else if (enable_metrics)
+				metrics_display(i);
 		}
 	}
 
+	/* print port independent stats */
+	if (enable_metrics)
+		metrics_display(RTE_METRICS_GLOBAL);
+
 	return 0;
 }
-- 
2.5.5

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

* [PATCH v10 3/7] lib: add bitrate statistics library
  2017-02-03 10:33                 ` [PATCH v10 0/7] Expanded statistics reporting Remy Horton
  2017-02-03 10:33                   ` [PATCH v10 1/7] lib: add information metrics library Remy Horton
  2017-02-03 10:33                   ` [PATCH v10 2/7] app/proc_info: add metrics displaying Remy Horton
@ 2017-02-03 10:33                   ` Remy Horton
  2017-02-03 10:33                   ` [PATCH v10 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton
                                     ` (5 subsequent siblings)
  8 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patch adds a library that calculates peak and average data-rate
statistics. For ethernet devices. These statistics are reported using
the metrics library.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                        |   4 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/prog_guide/metrics_lib.rst              |  63 ++++++++++
 doc/guides/rel_notes/release_17_02.rst             |   6 +
 lib/Makefile                                       |   1 +
 lib/librte_bitratestats/Makefile                   |  53 +++++++++
 lib/librte_bitratestats/rte_bitrate.c              | 132 +++++++++++++++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++++++++++
 .../rte_bitratestats_version.map                   |   9 ++
 mk/rte.app.mk                                      |   1 +
 12 files changed, 356 insertions(+)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index eceebaa..375adc9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -631,6 +631,10 @@ Metrics
 M: Remy Horton <remy.horton@intel.com>
 F: lib/librte_metrics/
 
+Bit-rate statistica
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_bitratestats/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index b819932..e7b0e5c 100644
--- a/config/common_base
+++ b/config/common_base
@@ -633,3 +633,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
 # Compile the crypto performance application
 #
 CONFIG_RTE_APP_CRYPTO_PERF=y
+
+#
+# Compile the bitrate statistics library
+#
+CONFIG_RTE_LIBRTE_BITRATE=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 26a26b7..8492bce 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -157,4 +157,5 @@ There are many libraries, so their headers may be grouped by topics:
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
   [device metrics]     (@ref rte_metrics.h),
+  [bitrate statistics] (@ref rte_bitrate.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index e2e070f..4010340 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -37,6 +37,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_eal/common/include \
                           lib/librte_eal/common/include/generic \
                           lib/librte_acl \
+                          lib/librte_bitratestats \
                           lib/librte_cfgfile \
                           lib/librte_cmdline \
                           lib/librte_compat \
diff --git a/doc/guides/prog_guide/metrics_lib.rst b/doc/guides/prog_guide/metrics_lib.rst
index 87f806d..c06023c 100644
--- a/doc/guides/prog_guide/metrics_lib.rst
+++ b/doc/guides/prog_guide/metrics_lib.rst
@@ -178,3 +178,66 @@ print out all metrics for a given port:
         free(metrics);
         free(names);
     }
+
+
+Bit-rate statistics library
+---------------------------
+
+The bit-rate library calculates the exponentially-weighted moving
+average and peak bit-rates for each active port (i.e. network device).
+These statistics are reported via the metrics library using the
+following names:
+
+    - ``mean_bits_in``: Average inbound bit-rate
+    - ``mean_bits_out``:  Average outbound bit-rate
+    - ``peak_bits_in``:  Peak inbound bit-rate
+    - ``peak_bits_out``:  Peak outbound bit-rate
+
+Once initialised and clocked at the appropriate frequency, these
+statistics can be obtained by querying the metrics library.
+
+Initialization
+~~~~~~~~~~~~~~
+
+Before it is used the bit-rate statistics library has to be initialised
+by calling ``rte_stats_bitrate_create()``, which will return a bit-rate
+calculation object. Since the bit-rate library uses the metrics library
+to report the calculated statistics, the bit-rate library then needs to
+register the calculated statistics with the metrics library. This is
+done using the helper function ``rte_stats_bitrate_reg()``.
+
+.. code-block:: c
+
+    struct rte_stats_bitrates *bitrate_data;
+
+    bitrate_data = rte_stats_bitrate_create();
+    if (bitrate_data == NULL)
+        rte_exit(EXIT_FAILURE, "Could not allocate bit-rate data.\n");
+    rte_stats_bitrate_reg(bitrate_data);
+
+Controlling the sampling rate
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Since the library works by periodic sampling but does not use an
+internal thread, the application has to periodically call
+``rte_stats_bitrate_calc()``. The frequency at which this function
+is called should be the intended sampling rate required for the
+calculated statistics. For instance if per-second statistics are
+desired, this function should be called once a second.
+
+.. code-block:: c
+
+    tics_datum = rte_rdtsc();
+    tics_per_1sec = rte_get_timer_hz();
+
+    while( 1 ) {
+        /* ... */
+        tics_current = rte_rdtsc();
+	if (tics_current - tics_datum >= tics_per_1sec) {
+	    /* Periodic bitrate calculation */
+	    for (idx_port = 0; idx_port < cnt_ports; idx_port++)
+	            rte_stats_bitrate_calc(bitrate_data, idx_port);
+		tics_datum = tics_current;
+	    }
+        /* ... */
+    }
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 68581e4..98729e8 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -46,6 +46,11 @@ New Features
   reporting mechanism that is independent of other libraries such
   as ethdev.
 
+* **Added bit-rate calculation library.**
+
+  A library that can be used to calculate device bit-rates. Calculated
+  bitrates are reported using the metrics library.
+
 * **Added generic EAL API for I/O device memory read/write operations.**
 
   This API introduces 8-bit, 16-bit, 32bit, 64bit I/O device
@@ -348,6 +353,7 @@ The libraries prepended with a plus sign were incremented in this version.
 .. code-block:: diff
 
      librte_acl.so.2
+   + librte_bitratestats.so.1
      librte_cfgfile.so.2
      librte_cmdline.so.2
      librte_cryptodev.so.2
diff --git a/lib/Makefile b/lib/Makefile
index 29f6a81..ecc54c0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -50,6 +50,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_NET) += librte_net
 DIRS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += librte_ip_frag
 DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
+DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
 DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power
 DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter
 DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched
diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile
new file mode 100644
index 0000000..743b62c
--- /dev/null
+++ b/lib/librte_bitratestats/Makefile
@@ -0,0 +1,53 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016-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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_bitratestats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_bitratestats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c
new file mode 100644
index 0000000..2c20272
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.c
@@ -0,0 +1,132 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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 <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
+
+/*
+ * Persistent bit-rate data.
+ * @internal
+ */
+struct rte_stats_bitrate {
+	uint64_t last_ibytes;
+	uint64_t last_obytes;
+	uint64_t peak_ibits;
+	uint64_t peak_obits;
+	uint64_t ewma_ibits;
+	uint64_t ewma_obits;
+};
+
+struct rte_stats_bitrates {
+	struct rte_stats_bitrate port_stats[RTE_MAX_ETHPORTS];
+	uint16_t id_stats_set;
+};
+
+struct rte_stats_bitrates *
+rte_stats_bitrate_create(void)
+{
+	return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates),
+		RTE_CACHE_LINE_SIZE);
+}
+
+int
+rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data)
+{
+	const char * const names[] = {
+		"mean_bits_in", "mean_bits_out",
+		"peak_bits_in", "peak_bits_out",
+	};
+	int return_value;
+
+	return_value = rte_metrics_reg_names(&names[0], 4);
+	if (return_value >= 0)
+		bitrate_data->id_stats_set = return_value;
+	return return_value;
+}
+
+int
+rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data,
+	uint8_t port_id)
+{
+	struct rte_stats_bitrate *port_data;
+	struct rte_eth_stats eth_stats;
+	int ret_code;
+	uint64_t cnt_bits;
+	int64_t delta;
+	const int64_t alpha_percent = 20;
+	uint64_t values[4];
+
+	ret_code = rte_eth_stats_get(port_id, &eth_stats);
+	if (ret_code != 0)
+		return ret_code;
+
+	port_data = &bitrate_data->port_stats[port_id];
+
+	/* Incoming bitrate. This is an iteratively calculated EWMA
+	 * (Expomentially Weighted Moving Average) that uses a
+	 * weighting factor of alpha_percent.
+	 */
+	cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3;
+	port_data->last_ibytes = eth_stats.ibytes;
+	if (cnt_bits > port_data->peak_ibits)
+		port_data->peak_ibits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_ibits;
+	/* The +-50 fixes integer rounding during divison */
+	if (delta > 0)
+		delta = (delta * alpha_percent + 50) / 100;
+	else
+		delta = (delta * alpha_percent - 50) / 100;
+	port_data->ewma_ibits += delta;
+
+	/* Outgoing bitrate (also EWMA) */
+	cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3;
+	port_data->last_obytes = eth_stats.obytes;
+	if (cnt_bits > port_data->peak_obits)
+		port_data->peak_obits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_obits;
+	delta = (delta * alpha_percent + 50) / 100;
+	port_data->ewma_obits += delta;
+
+	values[0] = port_data->ewma_ibits;
+	values[1] = port_data->ewma_obits;
+	values[2] = port_data->peak_ibits;
+	values[3] = port_data->peak_obits;
+	rte_metrics_update_values(port_id, bitrate_data->id_stats_set,
+		values, 4);
+	return 0;
+}
diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h
new file mode 100644
index 0000000..564e4f7
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.h
@@ -0,0 +1,80 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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.
+ */
+
+
+/**
+ *  Bitrate statistics data structure.
+ *  This data structure is intentionally opaque.
+ */
+struct rte_stats_bitrates;
+
+
+/**
+ * Allocate a bitrate statistics structure
+ *
+ * @return
+ *   - Pointer to structure on success
+ *   - NULL on error (zmalloc failure)
+ */
+struct rte_stats_bitrates *rte_stats_bitrate_create(void);
+
+
+/**
+ * Register bitrate statistics with the metric library.
+ *
+ * @param bitrate_data
+ *   Pointer allocated by rte_stats_create()
+ *
+ * @return
+ *   Zero on success
+ *   Negative on error
+ */
+int rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data);
+
+
+/**
+ * Calculate statistics for current time window. The period with which
+ * this function is called should be the intended sampling window width.
+ *
+ * @param bitrate_data
+ *   Bitrate statistics data pointer
+ *
+ * @param port_id
+ *   Port id to calculate statistics for
+ *
+ * @return
+ *  - Zero on success
+ *  - Negative value on error
+ */
+int rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data,
+	uint8_t port_id);
diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map
new file mode 100644
index 0000000..66f232f
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitratestats_version.map
@@ -0,0 +1,9 @@
+DPDK_17.02 {
+	global:
+
+	rte_stats_bitrate_calc;
+	rte_stats_bitrate_create;
+	rte_stats_bitrate_reg;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 46de3d3..8f1f8d7 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -100,6 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER)        += -lrte_reorder
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
 
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
-- 
2.5.5

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

* [PATCH v10 4/7] app/test-pmd: add bitrate statistics calculation
  2017-02-03 10:33                 ` [PATCH v10 0/7] Expanded statistics reporting Remy Horton
                                     ` (2 preceding siblings ...)
  2017-02-03 10:33                   ` [PATCH v10 3/7] lib: add bitrate statistics library Remy Horton
@ 2017-02-03 10:33                   ` Remy Horton
  2017-02-03 10:33                   ` [PATCH v10 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton
                                     ` (4 subsequent siblings)
  8 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

Calculate bitrate statistics using the bitrate stats library. The
resulting statistics can be viewed via proc_info.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/testpmd.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index bfb2f8e..b31a300 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -1,7 +1,7 @@
 /*-
  *   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
@@ -79,6 +79,10 @@
 #include <rte_pdump.h>
 #endif
 #include <rte_flow.h>
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_BITRATE
+#include <rte_bitrate.h>
+#endif
 
 #include "testpmd.h"
 
@@ -323,6 +327,9 @@ uint16_t nb_rx_queue_stats_mappings = 0;
 
 unsigned max_socket = 0;
 
+/* Bitrate statistics */
+struct rte_stats_bitrates *bitrate_data;
+
 /* Forward function declarations */
 static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -922,12 +929,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
 	struct fwd_stream **fsm;
 	streamid_t nb_fs;
 	streamid_t sm_id;
+#ifdef RTE_LIBRTE_BITRATE
+	uint64_t tics_per_1sec;
+	uint64_t tics_datum;
+	uint64_t tics_current;
+	uint8_t idx_port, cnt_ports;
+#endif
 
+#ifdef RTE_LIBRTE_BITRATE
+	cnt_ports = rte_eth_dev_count();
+	tics_datum = rte_rdtsc();
+	tics_per_1sec = rte_get_timer_hz();
+#endif
 	fsm = &fwd_streams[fc->stream_idx];
 	nb_fs = fc->stream_nb;
 	do {
 		for (sm_id = 0; sm_id < nb_fs; sm_id++)
 			(*pkt_fwd)(fsm[sm_id]);
+#ifdef RTE_LIBRTE_BITRATE
+		tics_current = rte_rdtsc();
+		if (tics_current - tics_datum >= tics_per_1sec) {
+			/* Periodic bitrate calculation */
+			for (idx_port = 0; idx_port < cnt_ports; idx_port++)
+				rte_stats_bitrate_calc(bitrate_data, idx_port);
+			tics_datum = tics_current;
+		}
+#endif
 	} while (! fc->stopped);
 }
 
@@ -2139,6 +2166,18 @@ main(int argc, char** argv)
 	FOREACH_PORT(port_id, ports)
 		rte_eth_promiscuous_enable(port_id);
 
+	/* Init metrics library */
+	rte_metrics_init(rte_socket_id());
+
+	/* Setup bitrate stats */
+#ifdef RTE_LIBRTE_BITRATE
+	bitrate_data = rte_stats_bitrate_create();
+	if (bitrate_data == NULL)
+		rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n");
+	rte_stats_bitrate_reg(bitrate_data);
+#endif
+
+
 #ifdef RTE_LIBRTE_CMDLINE
 	if (interactive == 1) {
 		if (auto_start) {
-- 
2.5.5

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

* [PATCH v10 5/7] mbuf: add a timestamp to the mbuf for latencystats
  2017-02-03 10:33                 ` [PATCH v10 0/7] Expanded statistics reporting Remy Horton
                                     ` (3 preceding siblings ...)
  2017-02-03 10:33                   ` [PATCH v10 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton
@ 2017-02-03 10:33                   ` Remy Horton
  2017-02-03 10:33                   ` [PATCH v10 6/7] lib: added new library for latency stats Remy Horton
                                     ` (3 subsequent siblings)
  8 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw)
  To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan

From: Harry van Haaren <harry.van.haaren@intel.com>

This commit adds a uint64_t to the mbuf struct,
allowing collection of latency and jitter statistics
by measuring packet I/O timestamps. This change is
required by the latencystats library.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
---
 lib/librte_mbuf/rte_mbuf.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index 0d01167..6a8c4f6 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -512,6 +512,9 @@ struct rte_mbuf {
 
 	/** Timesync flags for use with IEEE1588. */
 	uint16_t timesync;
+
+	/** Timestamp for measuring latency. */
+	uint64_t timestamp;
 } __rte_cache_aligned;
 
 /**
-- 
2.5.5

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

* [PATCH v10 6/7] lib: added new library for latency stats
  2017-02-03 10:33                 ` [PATCH v10 0/7] Expanded statistics reporting Remy Horton
                                     ` (4 preceding siblings ...)
  2017-02-03 10:33                   ` [PATCH v10 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton
@ 2017-02-03 10:33                   ` Remy Horton
  2017-02-03 10:33                   ` [PATCH v10 7/7] app/test-pmd: add latency statistics calculation Remy Horton
                                     ` (2 subsequent siblings)
  8 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw)
  To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan

From: Harry van Haaren <harry.van.haaren@intel.com>

Add a library designed to calculate latency statistics and report them
to the application when queried. The library measures minimum, average and
maximum latencies, and jitter in nano seconds. The current implementation
supports global latency stats, i.e. per application stats.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
---
 MAINTAINERS                                        |   4 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/prog_guide/metrics_lib.rst              |  58 +++-
 doc/guides/rel_notes/release_17_02.rst             |   5 +
 lib/Makefile                                       |   1 +
 lib/librte_latencystats/Makefile                   |  56 ++++
 lib/librte_latencystats/rte_latencystats.c         | 366 +++++++++++++++++++++
 lib/librte_latencystats/rte_latencystats.h         | 154 +++++++++
 .../rte_latencystats_version.map                   |  11 +
 mk/rte.app.mk                                      |   2 +-
 12 files changed, 661 insertions(+), 3 deletions(-)
 create mode 100644 lib/librte_latencystats/Makefile
 create mode 100644 lib/librte_latencystats/rte_latencystats.c
 create mode 100644 lib/librte_latencystats/rte_latencystats.h
 create mode 100644 lib/librte_latencystats/rte_latencystats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 375adc9..b89cd3a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -635,6 +635,10 @@ Bit-rate statistica
 M: Remy Horton <remy.horton@intel.com>
 F: lib/librte_bitratestats/
 
+Latency Stats
+M: Reshma Pattan <reshma.pattan@intel.com>
+F: lib/librte_latencystats/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index e7b0e5c..ccfe1cd 100644
--- a/config/common_base
+++ b/config/common_base
@@ -638,3 +638,8 @@ CONFIG_RTE_APP_CRYPTO_PERF=y
 # Compile the bitrate statistics library
 #
 CONFIG_RTE_LIBRTE_BITRATE=y
+
+#
+# Compile the latency statistics library
+#
+CONFIG_RTE_LIBRTE_LATENCY_STATS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 8492bce..9d1818c 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -158,4 +158,5 @@ There are many libraries, so their headers may be grouped by topics:
   [keepalive]          (@ref rte_keepalive.h),
   [device metrics]     (@ref rte_metrics.h),
   [bitrate statistics] (@ref rte_bitrate.h),
+  [latency statistics] (@ref rte_latencystats.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index 4010340..84a4fdd 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -50,6 +50,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_jobstats \
                           lib/librte_kni \
                           lib/librte_kvargs \
+                          lib/librte_latencystats \
                           lib/librte_lpm \
                           lib/librte_mbuf \
                           lib/librte_mempool \
diff --git a/doc/guides/prog_guide/metrics_lib.rst b/doc/guides/prog_guide/metrics_lib.rst
index c06023c..1423288 100644
--- a/doc/guides/prog_guide/metrics_lib.rst
+++ b/doc/guides/prog_guide/metrics_lib.rst
@@ -199,8 +199,8 @@ statistics can be obtained by querying the metrics library.
 Initialization
 ~~~~~~~~~~~~~~
 
-Before it is used the bit-rate statistics library has to be initialised
-by calling ``rte_stats_bitrate_create()``, which will return a bit-rate
+Before the library can be used, it has to be initialised by calling
+``rte_stats_bitrate_create()``, which will return a bit-rate
 calculation object. Since the bit-rate library uses the metrics library
 to report the calculated statistics, the bit-rate library then needs to
 register the calculated statistics with the metrics library. This is
@@ -241,3 +241,57 @@ desired, this function should be called once a second.
 	    }
         /* ... */
     }
+
+
+Latency statistics library
+--------------------------
+
+The latency statistics library calculates the latency of packet
+processing by a DPDK application, reporting the minimum, average,
+and maximum nano-seconds that packet processing takes, as well as
+the jitter in processing delay. These statistics are then reported
+via the metrics library using the following names:
+
+    - ``min_latency_ns``: Minimum processing latency (nano-seconds)
+    - ``avg_latency_ns``:  Average  processing latency (nano-seconds)
+    - ``mac_latency_ns``:  Maximum  processing latency (nano-seconds)
+    - ``jitter_ns``: Variance in processing latency (nano-seconds)
+
+Once initialised and clocked at the appropriate frequency, these
+statistics can be obtained by querying the metrics library.
+
+Initialization
+~~~~~~~~~~~~~~
+
+Before the library can be used, it has to be initialised by calling
+``rte_latencystats_init()``.
+
+.. code-block:: c
+
+    lcoreid_t latencystats_lcore_id = -1;
+
+    int ret = rte_latencystats_init(1, NULL);
+    if (ret)
+        rte_exit(EXIT_FAILURE, "Could not allocate latency data.\n");
+
+
+Triggering statistic updates
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``rte_latencystats_update()`` function needs to be called
+periodically so that latency statistics can be updated.
+
+.. code-block:: c
+
+    if (latencystats_lcore_id == rte_lcore_id())
+        rte_latencystats_update();
+
+Library shutdown
+~~~~~~~~~~~~~~~~
+
+When finished, ``rte_latencystats_uninit()`` needs to be called to
+de-initialise the latency library.
+
+.. code-block:: c
+
+    rte_latencystats_uninit();
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 98729e8..bb4ad93 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -224,6 +224,10 @@ New Features
   See the :ref:`Elastic Flow Distributor Library <Efd_Library>` documentation in
   the Programmers Guide document, for more information.
 
+* **Added latency stats library.**
+
+  A library that measures packet latency. The collected statistics are jitter
+  and latency. For latency the minimum, average, and maximum is measured.
 
 Resolved Issues
 ---------------
@@ -365,6 +369,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_jobstats.so.1
      librte_kni.so.2
      librte_kvargs.so.1
+   + librte_latencystats.so.1
      librte_lpm.so.2
      librte_mbuf.so.2
      librte_mempool.so.2
diff --git a/lib/Makefile b/lib/Makefile
index ecc54c0..78cba3e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -51,6 +51,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += librte_ip_frag
 DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
+DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats
 DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power
 DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter
 DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched
diff --git a/lib/librte_latencystats/Makefile b/lib/librte_latencystats/Makefile
new file mode 100644
index 0000000..fd145d3
--- /dev/null
+++ b/lib/librte_latencystats/Makefile
@@ -0,0 +1,56 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016-2017 Intel Corporation. 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_latencystats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
+LDLIBS += -lm
+LDLIBS += -lpthread
+
+EXPORT_MAP := rte_latencystats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) := rte_latencystats.c
+
+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)-include := rte_latencystats.h
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_latencystats/rte_latencystats.c b/lib/librte_latencystats/rte_latencystats.c
new file mode 100644
index 0000000..5334b8b
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats.c
@@ -0,0 +1,366 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-2017 Intel Corporation. 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 <unistd.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <math.h>
+
+#include <rte_mbuf.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_metrics.h>
+#include <rte_memzone.h>
+#include <rte_lcore.h>
+#include <rte_timer.h>
+
+#include "rte_latencystats.h"
+
+/** Nano seconds per second */
+#define NS_PER_SEC 1E9
+
+/** Clock cycles per nano second */
+static uint64_t
+latencystat_cycles_per_ns(void)
+{
+	return rte_get_timer_hz() / NS_PER_SEC;
+}
+
+/* Macros for printing using RTE_LOG */
+#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1
+
+static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats";
+static int latency_stats_index;
+static uint64_t samp_intvl;
+static uint64_t timer_tsc;
+static uint64_t prev_tsc;
+
+struct rte_latency_stats {
+	float min_latency; /**< Minimum latency in nano seconds */
+	float avg_latency; /**< Average latency in nano seconds */
+	float max_latency; /**< Maximum latency in nano seconds */
+	float jitter; /** Latency variation */
+};
+
+static struct rte_latency_stats *glob_stats;
+
+struct rxtx_cbs {
+	struct rte_eth_rxtx_callback *cb;
+};
+
+static struct rxtx_cbs rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
+static struct rxtx_cbs tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
+
+struct latency_stats_nameoff {
+	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	unsigned int offset;
+};
+
+static const struct latency_stats_nameoff lat_stats_strings[] = {
+	{"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)},
+	{"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)},
+	{"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)},
+	{"jitter_ns", offsetof(struct rte_latency_stats, jitter)},
+};
+
+#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \
+				sizeof(lat_stats_strings[0]))
+
+int32_t
+rte_latencystats_update(void)
+{
+	unsigned int i;
+	float *stats_ptr = NULL;
+	uint64_t values[NUM_LATENCY_STATS] = {0};
+	int ret;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++) {
+		stats_ptr = RTE_PTR_ADD(glob_stats,
+				lat_stats_strings[i].offset);
+		values[i] = (uint64_t)floor((*stats_ptr)/
+				latencystat_cycles_per_ns());
+	}
+
+	ret = rte_metrics_update_values(RTE_METRICS_GLOBAL,
+					latency_stats_index,
+					values, NUM_LATENCY_STATS);
+	if (ret < 0)
+		RTE_LOG(INFO, LATENCY_STATS, "Failed to push the stats\n");
+
+	return ret;
+}
+
+static void
+rte_latencystats_fill_values(struct rte_metric_value *values)
+{
+	unsigned int i;
+	float *stats_ptr = NULL;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++) {
+		stats_ptr = RTE_PTR_ADD(glob_stats,
+				lat_stats_strings[i].offset);
+		values[i].key = i;
+		values[i].value = (uint64_t)floor((*stats_ptr)/
+						latencystat_cycles_per_ns());
+	}
+}
+
+static uint16_t
+add_time_stamps(uint8_t pid __rte_unused,
+		uint16_t qid __rte_unused,
+		struct rte_mbuf **pkts,
+		uint16_t nb_pkts,
+		uint16_t max_pkts __rte_unused,
+		void *user_cb __rte_unused)
+{
+	unsigned int i;
+	uint64_t diff_tsc, now;
+
+	/*
+	 * For every sample interval,
+	 * time stamp is marked on one received packet.
+	 */
+	now = rte_rdtsc();
+	for (i = 0; i < nb_pkts; i++) {
+		diff_tsc = now - prev_tsc;
+		timer_tsc += diff_tsc;
+		if (timer_tsc >= samp_intvl) {
+			/*
+			 * TBD: Mark the timestamp only
+			 * if not already marked by the
+			 * hardware or the PMD.
+			 */
+			pkts[i]->timestamp = now;
+			timer_tsc = 0;
+		}
+		prev_tsc = now;
+		now = rte_rdtsc();
+	}
+
+	return nb_pkts;
+}
+
+static uint16_t
+calc_latency(uint8_t pid __rte_unused,
+		uint16_t qid __rte_unused,
+		struct rte_mbuf **pkts,
+		uint16_t nb_pkts,
+		void *_ __rte_unused)
+{
+	unsigned int i, cnt = 0;
+	uint64_t now;
+	float latency[nb_pkts];
+	static float prev_latency;
+	/*
+	 * Alpha represents degree of weighting decrease in EWMA,
+	 * a constant smoothing factor between 0 and 1. The value
+	 * is used below for measuring average latency.
+	 */
+	const float alpha = 0.2;
+
+	now = rte_rdtsc();
+	for (i = 0; i < nb_pkts; i++) {
+		if (pkts[i]->timestamp)
+			latency[cnt++] = now - pkts[i]->timestamp;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		/*
+		 * The jitter is calculated as statistical mean of interpacket
+		 * delay variation. The "jitter estimate" is computed by taking
+		 * the absolute values of the ipdv sequence and applying an
+		 * exponential filter with parameter 1/16 to generate the
+		 * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter,
+		 * D(i-1,i) is difference in latency of two consecutive packets
+		 * i-1 and i.
+		 * Reference: Calculated as per RFC 5481, sec 4.1,
+		 * RFC 3393 sec 4.5, RFC 1889 sec.
+		 */
+		glob_stats->jitter +=  (abs(prev_latency - latency[i])
+					- glob_stats->jitter)/16;
+		if (glob_stats->min_latency == 0)
+			glob_stats->min_latency = latency[i];
+		else if (latency[i] < glob_stats->min_latency)
+			glob_stats->min_latency = latency[i];
+		else if (latency[i] > glob_stats->max_latency)
+			glob_stats->max_latency = latency[i];
+		/*
+		 * The average latency is measured using exponential moving
+		 * average, i.e. using EWMA
+		 * https://en.wikipedia.org/wiki/Moving_average
+		 */
+		glob_stats->avg_latency +=
+			alpha * (latency[i] - glob_stats->avg_latency);
+		prev_latency = latency[i];
+	}
+
+	return nb_pkts;
+}
+
+int
+rte_latencystats_init(uint64_t app_samp_intvl,
+		rte_latency_stats_flow_type_fn user_cb)
+{
+	unsigned int i;
+	uint8_t pid;
+	uint16_t qid;
+	struct rxtx_cbs *cbs = NULL;
+	const uint8_t nb_ports = rte_eth_dev_count();
+	const char *ptr_strings[NUM_LATENCY_STATS] = {0};
+	const struct rte_memzone *mz = NULL;
+	const unsigned int flags = 0;
+
+	if (rte_memzone_lookup(MZ_RTE_LATENCY_STATS))
+		return -EEXIST;
+
+	/** Allocate stats in shared memory fo multi process support */
+	mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats),
+					rte_socket_id(), flags);
+	if (mz == NULL) {
+		RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n",
+			__func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	glob_stats = mz->addr;
+	samp_intvl = app_samp_intvl * latencystat_cycles_per_ns();
+
+	/** Register latency stats with stats library */
+	for (i = 0; i < NUM_LATENCY_STATS; i++)
+		ptr_strings[i] = lat_stats_strings[i].name;
+
+	latency_stats_index = rte_metrics_reg_names(ptr_strings,
+							NUM_LATENCY_STATS);
+	if (latency_stats_index < 0) {
+		RTE_LOG(DEBUG, LATENCY_STATS,
+			"Failed to register latency stats names\n");
+		return -1;
+	}
+
+	/** Register Rx/Tx callbacks */
+	for (pid = 0; pid < nb_ports; pid++) {
+		struct rte_eth_dev_info dev_info;
+		rte_eth_dev_info_get(pid, &dev_info);
+		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
+			cbs = &rx_cbs[pid][qid];
+			cbs->cb = rte_eth_add_first_rx_callback(pid, qid,
+					add_time_stamps, user_cb);
+			if (!cbs->cb)
+				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
+					"register Rx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
+			cbs = &tx_cbs[pid][qid];
+			cbs->cb =  rte_eth_add_tx_callback(pid, qid,
+					calc_latency, user_cb);
+			if (!cbs->cb)
+				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
+					"register Tx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+	}
+	return 0;
+}
+
+int
+rte_latencystats_uninit(void)
+{
+	uint8_t pid;
+	uint16_t qid;
+	int ret = 0;
+	struct rxtx_cbs *cbs = NULL;
+	const uint8_t nb_ports = rte_eth_dev_count();
+
+	/** De register Rx/Tx callbacks */
+	for (pid = 0; pid < nb_ports; pid++) {
+		struct rte_eth_dev_info dev_info;
+		rte_eth_dev_info_get(pid, &dev_info);
+		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
+			cbs = &rx_cbs[pid][qid];
+			ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb);
+			if (ret)
+				RTE_LOG(INFO, LATENCY_STATS, "failed to "
+					"remove Rx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
+			cbs = &tx_cbs[pid][qid];
+			ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb);
+			if (ret)
+				RTE_LOG(INFO, LATENCY_STATS, "failed to "
+					"remove Tx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+	}
+
+	return 0;
+}
+
+int
+rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size)
+{
+	unsigned int i;
+
+	if (names == NULL || size < NUM_LATENCY_STATS)
+		return NUM_LATENCY_STATS;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++)
+		snprintf(names[i].name, sizeof(names[i].name),
+				"%s", lat_stats_strings[i].name);
+
+	return NUM_LATENCY_STATS;
+}
+
+int
+rte_latencystats_get(struct rte_metric_value *values, uint16_t size)
+{
+	if (size < NUM_LATENCY_STATS || values == NULL)
+		return NUM_LATENCY_STATS;
+
+	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		const struct rte_memzone *mz;
+		mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS);
+		if (mz == NULL) {
+			RTE_LOG(ERR, LATENCY_STATS,
+				"Latency stats memzone not found\n");
+			return -ENOMEM;
+		}
+		glob_stats =  mz->addr;
+	}
+
+	/* Retrieve latency stats */
+	rte_latencystats_fill_values(values);
+
+	return NUM_LATENCY_STATS;
+}
diff --git a/lib/librte_latencystats/rte_latencystats.h b/lib/librte_latencystats/rte_latencystats.h
new file mode 100644
index 0000000..28c6dcf
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats.h
@@ -0,0 +1,154 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-2017 Intel Corporation. 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 _RTE_LATENCYSTATS_H_
+#define _RTE_LATENCYSTATS_H_
+
+/**
+ * @file
+ * RTE latency stats
+ *
+ * library to provide application and flow based latency stats.
+ */
+
+#include <rte_metrics.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  Note: This function pointer is for future flow based latency stats
+ *  implementation.
+ *
+ * Function type used for identifting flow types of a Rx packet.
+ *
+ * The callback function is called on Rx for each packet.
+ * This function is used for flow based latency calculations.
+ *
+ * @param pkt
+ *   Packet that has to be identified with its flow types.
+ * @param user_param
+ *   The arbitrary user parameter passed in by the application when
+ *   the callback was originally configured.
+ * @return
+ *   The flow_mask, representing the multiple flow types of a packet.
+ */
+typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt,
+							void *user_param);
+
+/**
+ *  Registers Rx/Tx callbacks for each active port, queue.
+ *
+ * @param samp_intvl
+ *  Sampling time period in nano seconds, at which packet
+ *  should be marked with time stamp.
+ * @param user_cb
+ *  Note: This param is for future flow based latency stats
+ *  implementation.
+ *  User callback to be called to get flow types of a packet.
+ *  Used for flow based latency calculation.
+ *  If the value is NULL, global stats will be calculated,
+ *  else flow based latency stats will be calculated.
+ *  For now just pass on the NULL value to this param.
+ *  @return
+ *   -1     : On error
+ *   -ENOMEM: On error
+ *    0     : On success
+ */
+int rte_latencystats_init(uint64_t samp_intvl,
+			rte_latency_stats_flow_type_fn user_cb);
+
+/**
+ * Calculates the latency and jitter values internally, exposing the updated
+ * values via *rte_latencystats_get* or the rte_metrics API.
+ * @return:
+ *  0      : on Success
+ *  < 0    : Error in updating values.
+ */
+int32_t rte_latencystats_update(void);
+
+/**
+ *  Removes registered Rx/Tx callbacks for each active port, queue.
+ *
+ *  @return
+ *   -1: On error
+ *    0: On success
+ */
+int rte_latencystats_uninit(void);
+
+/**
+ * Retrieve names of latency statistics
+ *
+ * @param names
+ *  Block of memory to insert names into. Must be at least size in capacity.
+ *  If set to NULL, function returns required capacity.
+ * @param size
+ *  Capacity of latency stats names (number of names).
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ */
+int rte_latencystats_get_names(struct rte_metric_name *names,
+				uint16_t size);
+
+/**
+ * Retrieve latency statistics.
+ *
+ * @param values
+ *   A pointer to a table of structure of type *rte_metric_value*
+ *   to be filled with latency statistics ids and values.
+ *   This parameter can be set to NULL if size is 0.
+ * @param size
+ *   The size of the stats table, which should be large enough to store
+ *   all the latency stats.
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ *   -ENOMEM: On failure.
+ */
+int rte_latencystats_get(struct rte_metric_value *values,
+			uint16_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_LATENCYSTATS_H_ */
diff --git a/lib/librte_latencystats/rte_latencystats_version.map b/lib/librte_latencystats/rte_latencystats_version.map
new file mode 100644
index 0000000..d240563
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats_version.map
@@ -0,0 +1,11 @@
+DPDK_17.02 {
+	global:
+
+	rte_latencystats_get;
+	rte_latencystats_get_names;
+	rte_latencystats_init;
+	rte_latencystats_uninit;
+	rte_latencystats_update;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 8f1f8d7..97b680a 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -101,7 +101,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
 _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER)        += -lrte_reorder
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
 _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
-
+_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)  += -lrte_latencystats
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND)       += -lrte_pmd_bond
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT)    += -lrte_pmd_xenvirt -lxenstore
-- 
2.5.5

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

* [PATCH v10 7/7] app/test-pmd: add latency statistics calculation
  2017-02-03 10:33                 ` [PATCH v10 0/7] Expanded statistics reporting Remy Horton
                                     ` (5 preceding siblings ...)
  2017-02-03 10:33                   ` [PATCH v10 6/7] lib: added new library for latency stats Remy Horton
@ 2017-02-03 10:33                   ` Remy Horton
  2017-02-16 10:53                   ` [PATCH v10 0/7] Expanded statistics reporting Thomas Monjalon
  2017-03-09 16:25                   ` [PATCH v11 " Remy Horton
  8 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw)
  To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan

From: Harry van Haaren <harry.van.haaren@intel.com>

This patch adds latency stats commandline argument to testpmd,
allowing to specify the lcore to use for latencystats updates.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/parameters.c | 20 +++++++++++++++++++-
 app/test-pmd/testpmd.c    | 37 +++++++++++++++++++++++++++++++++++++
 app/test-pmd/testpmd.h    |  6 +++++-
 3 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 28db8cd..30b60ba 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -1,7 +1,7 @@
 /*-
  *   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
@@ -149,6 +149,10 @@ usage(char* progname)
 	       "the packet will be enqueued into the rx drop-queue. "
 	       "If the drop-queue doesn't exist, the packet is dropped. "
 	       "By default drop-queue=127.\n");
+#ifdef RTE_LIBRTE_LATENCY_STATS
+	printf("  --latencystats=N: enable latency and jitter statistcs "
+	       "monitoring on lcore id N.\n");
+#endif
 	printf("  --crc-strip: enable CRC stripping by hardware.\n");
 	printf("  --enable-lro: enable large receive offload.\n");
 	printf("  --enable-rx-cksum: enable rx hardware checksum offload.\n");
@@ -526,6 +530,7 @@ launch_args_parse(int argc, char** argv)
 		{ "pkt-filter-report-hash",     1, 0, 0 },
 		{ "pkt-filter-size",            1, 0, 0 },
 		{ "pkt-filter-drop-queue",      1, 0, 0 },
+		{ "latencystats",               1, 0, 0 },
 		{ "crc-strip",                  0, 0, 0 },
 		{ "enable-lro",                 0, 0, 0 },
 		{ "enable-rx-cksum",            0, 0, 0 },
@@ -766,6 +771,19 @@ launch_args_parse(int argc, char** argv)
 						 "drop queue %d invalid - must"
 						 "be >= 0 \n", n);
 			}
+#ifdef RTE_LIBRTE_LATENCY_STATS
+			if (!strcmp(lgopts[opt_idx].name,
+				    "latencystats")) {
+				n = atoi(optarg);
+				if (n >= 0) {
+					latencystats_lcore_id = (lcoreid_t) n;
+					latencystats_enabled = 1;
+				} else
+					rte_exit(EXIT_FAILURE,
+						 "invalid lcore id %d for latencystats"
+						 " must be >= 0\n", n);
+			}
+#endif
 			if (!strcmp(lgopts[opt_idx].name, "crc-strip"))
 				rx_mode.hw_strip_crc = 1;
 			if (!strcmp(lgopts[opt_idx].name, "enable-lro"))
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index b31a300..524e758 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -83,6 +83,10 @@
 #ifdef RTE_LIBRTE_BITRATE
 #include <rte_bitrate.h>
 #endif
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_LATENCY_STATS
+#include <rte_latencystats.h>
+#endif
 
 #include "testpmd.h"
 
@@ -276,6 +280,20 @@ uint32_t bypass_timeout = RTE_BYPASS_TMT_OFF;
 
 #endif
 
+#ifdef RTE_LIBRTE_LATENCY_STATS
+
+/*
+ * Set when latency stats is enabled in the commandline
+ */
+uint8_t latencystats_enabled;
+
+/*
+ * Lcore ID to serive latency statistics.
+ */
+lcoreid_t latencystats_lcore_id = -1;
+
+#endif
+
 /*
  * Ethernet device configuration.
  */
@@ -955,6 +973,11 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
 			tics_datum = tics_current;
 		}
 #endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+		if (latencystats_lcore_id == rte_lcore_id())
+			rte_latencystats_update();
+#endif
+
 	} while (! fc->stopped);
 }
 
@@ -2108,6 +2131,9 @@ signal_handler(int signum)
 		/* uninitialize packet capture framework */
 		rte_pdump_uninit();
 #endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+		rte_latencystats_uninit();
+#endif
 		force_quit();
 		/* exit with the expected status */
 		signal(signum, SIG_DFL);
@@ -2169,6 +2195,17 @@ main(int argc, char** argv)
 	/* Init metrics library */
 	rte_metrics_init(rte_socket_id());
 
+#ifdef RTE_LIBRTE_LATENCY_STATS
+	if (latencystats_enabled != 0) {
+		int ret = rte_latencystats_init(1, NULL);
+		if (ret)
+			printf("Warning: latencystats init()"
+				" returned error %d\n",	ret);
+		printf("Latencystats running on lcore %d\n",
+			latencystats_lcore_id);
+	}
+#endif
+
 	/* Setup bitrate stats */
 #ifdef RTE_LIBRTE_BITRATE
 	bitrate_data = rte_stats_bitrate_create();
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 8cf2860..f0652ee 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -1,7 +1,7 @@
 /*-
  *   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
@@ -381,6 +381,10 @@ extern enum dcb_queue_mapping_mode dcb_q_mapping;
 extern uint16_t mbuf_data_size; /**< Mbuf data space size. */
 extern uint32_t param_total_num_mbufs;
 
+
+extern uint8_t latencystats_enabled;
+extern lcoreid_t latencystats_lcore_id;
+
 extern struct rte_fdir_conf fdir_conf;
 
 /*
-- 
2.5.5

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

* Re: [PATCH v10 0/7] Expanded statistics reporting
  2017-02-03 10:33                 ` [PATCH v10 0/7] Expanded statistics reporting Remy Horton
                                     ` (6 preceding siblings ...)
  2017-02-03 10:33                   ` [PATCH v10 7/7] app/test-pmd: add latency statistics calculation Remy Horton
@ 2017-02-16 10:53                   ` Thomas Monjalon
  2017-02-23  7:09                     ` Remy Horton
  2017-03-09 16:25                   ` [PATCH v11 " Remy Horton
  8 siblings, 1 reply; 115+ messages in thread
From: Thomas Monjalon @ 2017-02-16 10:53 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev

2017-02-03 10:33, Remy Horton:
> This patchset extends statistics reporting to include peak and
> average data-rate metrics. It comes in two parts: a statistics
> reporting library, and a bitrate calculation library that uses
> it. This structure is intended to seperate statistic reporting
> from ethdev and allow more flexible metric registration.

Note that this series integrates a third part for latency metric.

> v10 changes:
> * Rebased
> * Relocated some config-related directives.
> * Removed incorrect capitalisations in API docs.
> * Formatting & detail corrections in release notes.
> * Moved around struct member descriptions.
> * Rewritten rte_metrics.h file description.
> * Rewritten description of RTE_METRICS_GLOBAL.
> * Used 'producers' and 'consumers' as terms.
> * Removed markup (bold text) in Doxygen tags.
> * Added programming guide section.

Thanks for adding the prog guide section. It helps.

I think there are three remaining questions:
- When the metrics computation are done? (in which thread?)
- May the few lines of computation code be done differently when tightly
integrated in an application logic?
- Could it be hosted in a separate repository on dpdk.org?

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

* Re: [PATCH v10 0/7] Expanded statistics reporting
  2017-02-16 10:53                   ` [PATCH v10 0/7] Expanded statistics reporting Thomas Monjalon
@ 2017-02-23  7:09                     ` Remy Horton
  2017-02-23  8:45                       ` Thomas Monjalon
  0 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-02-23  7:09 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev


On 16/02/2017 10:53, Thomas Monjalon wrote:
> 2017-02-03 10:33, Remy Horton:
[..]
> I think there are three remaining questions:
> - When the metrics computation are done? (in which thread?)

Actual calculation is not done by libmetrics itself - it only handles
distribution. Calculation is done prior to the calculated values being
passed to rte_metrics_update_value*(), so the thread that does the
calculation is a decision for the application.


> - May the few lines of computation code be done differently when tightly
> integrated in an application logic?

Yes, since it is the application itself (or in the case of bit-rate, a
separate library) that does the calculation.


> - Could it be hosted in a separate repository on dpdk.org?
>

That's part of a broader discussion on how DPDK is packaged.

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

* Re: [PATCH v10 0/7] Expanded statistics reporting
  2017-02-23  7:09                     ` Remy Horton
@ 2017-02-23  8:45                       ` Thomas Monjalon
  0 siblings, 0 replies; 115+ messages in thread
From: Thomas Monjalon @ 2017-02-23  8:45 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev

2017-02-23 07:09, Remy Horton:
> 
> On 16/02/2017 10:53, Thomas Monjalon wrote:
> > 2017-02-03 10:33, Remy Horton:
> [..]
> > I think there are three remaining questions:
> > - When the metrics computation are done? (in which thread?)
> 
> Actual calculation is not done by libmetrics itself - it only handles
> distribution. Calculation is done prior to the calculated values being
> passed to rte_metrics_update_value*(), so the thread that does the
> calculation is a decision for the application.

Of course computation is not done in libmetrics. The question was about
its integration in the application and the perfromance impact.
Should it be in the dataplane threads or in separate threads?

> > - May the few lines of computation code be done differently when tightly
> > integrated in an application logic?
> 
> Yes, since it is the application itself (or in the case of bit-rate, a
> separate library) that does the calculation.

The question was more about the cache misses with this library.

> > - Could it be hosted in a separate repository on dpdk.org?
> 
> That's part of a broader discussion on how DPDK is packaged.

And specifically for these metrics libraries, do you agree it could
be packaged separately?

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

* [PATCH v11 0/7] Expanded statistics reporting
  2017-02-03 10:33                 ` [PATCH v10 0/7] Expanded statistics reporting Remy Horton
                                     ` (7 preceding siblings ...)
  2017-02-16 10:53                   ` [PATCH v10 0/7] Expanded statistics reporting Thomas Monjalon
@ 2017-03-09 16:25                   ` Remy Horton
  2017-03-09 16:25                     ` [PATCH v11 1/7] lib: add information metrics library Remy Horton
                                       ` (6 more replies)
  8 siblings, 7 replies; 115+ messages in thread
From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patchset consists of three libraries: A Metrics library for
distributing device information, a library that calculates bit-rate
statistics, and a library that calculates latency statistics. The
latter two libraries make use of the first library.

Metrics Library
---------------
The Metrics library implements a mechanism by which producers can
publish numeric information for later querying by consumers.
In practice producers will typically be other libraries or
primary processes, whereas consumers will typically be applications.

Metrics themselves are statistics that are not generated by PMDs.
Metric information is populated using a push model, where producers
update the values contained within the metric library by calling an
update function on the relevant metrics. Consumers receive metric
information by querying the central metric data, which is held
in shared memory so it can also be accessed by secondary processes.

For each metric, a separate value is maintained for each port id,
and when publishing metric values the producers need to specify
which port is being updated. In addition there is a special id
RTE_METRICS_GLOBAL that is intended for global statistics that are
not associated with any individual device. Since the metrics
library is self-contained, the only restriction on port numbers is
that they are less than RTE_MAX_ETHPORTS - there is no requirement
for the ports to actually exist.

Metrics must first be registered, which is the way producers declare
the names of the metrics they will be publishing. Registration can
either be done individually, or as a group as a metric set. The
intention is for all metrics in a set to be updated in one go,
although it is also possible for metrics within a set to be updated
individually. It is up to the producers to update metrics as required.

Bit-rate statistics library
---------------------------
The bit-rate library calculates the mean, the exponentially-weighted
moving average, and peak bit-rates for each active port (i.e. network
device). These statistics are then reported via the metrics library
using the following names: mean_bits_in, mean_bits_out, ewma_bits_in,
ewma_bits_out, peak_bits_in, and peak_bits_out. The sampling window 
used for calculation is decided by the application requiring the statistics.

Latency statistics library
--------------------------
The latency statistics library calculates the port-to-port latency of
packet processing by a DPDK application, reporting the minimum, average,
and maximum nano-seconds that packet processing takes, as well as the
jitter in processing delay. These statistics are then reported via the
metrics library using the following names: min_latency_ns, avg_latency_ns,
mac_latency_ns, and jitter_ns.


For more details on the metrics library and the Bit-rate and Latency
components see the Programmer's Guide updates in the patchset.
--
v11 changes:
* Rebased
* .map references to 17.02 changed to 17.05
* Release ntoes moved to release_17_05.rst
* Bit-rate library now also gives unfiltered average

v10 changes:
* Rebased
* Relocated some config-related directives.
* Removed incorrect capitalisations in API docs.
* Formatting & detail corrections in release notes.
* Moved around struct member descriptions.
* Rewritten rte_metrics.h file description.
* Rewritten description of RTE_METRICS_GLOBAL.
* Used 'producers' and 'consumers' as terms.
* Removed markup (bold text) in Doxygen tags.
* Added programming guide section.

v9 changes:
* Updated .map files to reflect function changes in v8
* Fixed rte_malloc() of zero bytes in proc_info when no metrics exist
* Fixed rte_metrics_init not being called explicitly in testpmd

v8 changes:
* Release notes correction
* Updated copyright years
* rte_metric_init() takes socket id & must be explicitly called
* rte_metrics_reg_metric renamed to rte_metrics_reg_name()
* rte_metrics_update_metric() renamed to rte_metrics_update_value()
* Doxygen updates
* Changed malloc()/free() to rte_malloc()/rte_free()
* Removed redundant memset()
* rte_stats_bitrates_s renamed to rte_stats_bitrates_s
* Split mbuf change to own patch for visibility
* CYCLES_PER_NS now a static inline function
* latency: "hidden" pthread creation now has polling API instead.
* Struct declarations and variable definitions cleaned up
* Double initialization of the latency library now returns -EEXIST
* MAINTAINERS entry for layenctstats in correct section

v7 changes:
* RTE_METRICS_NONPORT renamed to RTE_METRICS_GLOBAL
* Multiple changes to rte_metrics.h doxygen documentation
* Split apart latency patch into lib, test-pmd, & proc_info parts
* Reordered patches by functionality
* Insufficent capacity return value changed from -ERANGE to actual size
* Cache alignment in bitrate library
* Tightened up const usage to avoid STATIC_CONST_CHAR_ARRAY warning
* Reshma reinstated as author for (now split) latency patch
* Rebase to master

v6 changes:
* Metrics display now has "Non port specific" rather than "port -1"
* Fixed sign issue in EWMA delta calculation
* Rebased to master

v5 changes:
* Updated Shared Library Versions in release notes
* Merged in Reshma's latencystats library

v4 changes:
* References to 16.11 changed to 17.02
* Fetching of non-port values was broken
* Added sanity checks to value fetching
* rte_stat_value renamed to rte_metric_value
* Corrected doxygen descriptions
* Added MAINTAINERS entries
* Added #ifdef directives to bitrate code in test-pmd

v3 changes:
* Marked rte_stats_bitrate_s as internal
* Minor integer roundoff correction
* Coding style corrections
* Removed spurious object allocation
* Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3.
* Reintroduced non-port values (RTE_METRICS_NONPORT)
* Added spinlocks to metric library
* Removed spurious test registration/update
* Added release notes entries

v2 changes:
* Uses a new metrics library rather than being part of ethdev


Harry van Haaren (3):
  mbuf: add a timestamp to the mbuf for latencystats
  lib: added new library for latency stats
  app/test-pmd: add latency statistics calculation

Remy Horton (3):
  lib: add information metrics library
  lib: add bitrate statistics library
  app/test-pmd: add bitrate statistics calculation

Reshma Pattan (1):
  app/proc_info: add metrics displaying

 MAINTAINERS                                        |  12 +
 app/proc_info/main.c                               |  79 ++++-
 app/test-pmd/parameters.c                          |  20 +-
 app/test-pmd/testpmd.c                             |  78 ++++-
 app/test-pmd/testpmd.h                             |   6 +-
 config/common_base                                 |  15 +
 doc/api/doxy-api-index.md                          |   3 +
 doc/api/doxy-api.conf                              |   3 +
 doc/guides/prog_guide/index.rst                    |   1 +
 doc/guides/prog_guide/metrics_lib.rst              | 299 +++++++++++++++++
 doc/guides/rel_notes/release_17_02.rst             |   3 +
 doc/guides/rel_notes/release_17_05.rst             |  18 +
 lib/Makefile                                       |   3 +
 lib/librte_bitratestats/Makefile                   |  53 +++
 lib/librte_bitratestats/rte_bitrate.c              | 141 ++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 +++++
 .../rte_bitratestats_version.map                   |   9 +
 lib/librte_latencystats/Makefile                   |  56 ++++
 lib/librte_latencystats/rte_latencystats.c         | 366 +++++++++++++++++++++
 lib/librte_latencystats/rte_latencystats.h         | 154 +++++++++
 .../rte_latencystats_version.map                   |  11 +
 lib/librte_mbuf/rte_mbuf.h                         |   3 +
 lib/librte_metrics/Makefile                        |  51 +++
 lib/librte_metrics/rte_metrics.c                   | 299 +++++++++++++++++
 lib/librte_metrics/rte_metrics.h                   | 240 ++++++++++++++
 lib/librte_metrics/rte_metrics_version.map         |  13 +
 mk/rte.app.mk                                      |   3 +
 27 files changed, 2015 insertions(+), 4 deletions(-)
 create mode 100644 doc/guides/prog_guide/metrics_lib.rst
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map
 create mode 100644 lib/librte_latencystats/Makefile
 create mode 100644 lib/librte_latencystats/rte_latencystats.c
 create mode 100644 lib/librte_latencystats/rte_latencystats.h
 create mode 100644 lib/librte_latencystats/rte_latencystats_version.map
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

-- 
2.5.5

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

* [PATCH v11 1/7] lib: add information metrics library
  2017-03-09 16:25                   ` [PATCH v11 " Remy Horton
@ 2017-03-09 16:25                     ` Remy Horton
  2017-03-09 16:25                     ` [PATCH v11 2/7] app/proc_info: add metrics displaying Remy Horton
                                       ` (5 subsequent siblings)
  6 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patch adds a new information metrics library. This Metrics
library implements a mechanism by which producers can publish
numeric information for later querying by consumers. Metrics
themselves are statistics that are not generated by PMDs, and
hence are not reported via ethdev extended statistics.

Metric information is populated using a push model, where
producers update the values contained within the metric
library by calling an update function on the relevant metrics.
Consumers receive metric information by querying the central
metric data, which is held in shared memory.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                |   4 +
 config/common_base                         |   5 +
 doc/api/doxy-api-index.md                  |   1 +
 doc/api/doxy-api.conf                      |   1 +
 doc/guides/prog_guide/index.rst            |   1 +
 doc/guides/prog_guide/metrics_lib.rst      | 180 +++++++++++++++++
 doc/guides/rel_notes/release_17_02.rst     |   1 +
 doc/guides/rel_notes/release_17_05.rst     |   8 +
 lib/Makefile                               |   1 +
 lib/librte_metrics/Makefile                |  51 +++++
 lib/librte_metrics/rte_metrics.c           | 299 +++++++++++++++++++++++++++++
 lib/librte_metrics/rte_metrics.h           | 240 +++++++++++++++++++++++
 lib/librte_metrics/rte_metrics_version.map |  13 ++
 mk/rte.app.mk                              |   2 +
 14 files changed, 807 insertions(+)
 create mode 100644 doc/guides/prog_guide/metrics_lib.rst
 create mode 100644 lib/librte_metrics/Makefile
 create mode 100644 lib/librte_metrics/rte_metrics.c
 create mode 100644 lib/librte_metrics/rte_metrics.h
 create mode 100644 lib/librte_metrics/rte_metrics_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 5030c1c..66478f3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -635,6 +635,10 @@ F: lib/librte_jobstats/
 F: examples/l2fwd-jobstats/
 F: doc/guides/sample_app_ug/l2_forward_job_stats.rst
 
+Metrics
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_metrics/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index aeee13e..cea055f 100644
--- a/config/common_base
+++ b/config/common_base
@@ -501,6 +501,11 @@ CONFIG_RTE_LIBRTE_EFD=y
 CONFIG_RTE_LIBRTE_JOBSTATS=y
 
 #
+# Compile the device metrics library
+#
+CONFIG_RTE_LIBRTE_METRICS=y
+
+#
 # Compile librte_lpm
 #
 CONFIG_RTE_LIBRTE_LPM=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index eb39f69..26a26b7 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -156,4 +156,5 @@ There are many libraries, so their headers may be grouped by topics:
   [common]             (@ref rte_common.h),
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
+  [device metrics]     (@ref rte_metrics.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index fdcf13c..fbbcf8e 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -52,6 +52,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_mbuf \
                           lib/librte_mempool \
                           lib/librte_meter \
+                          lib/librte_metrics \
                           lib/librte_net \
                           lib/librte_pdump \
                           lib/librte_pipeline \
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index 77f427e..2a69844 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -62,6 +62,7 @@ Programmer's Guide
     packet_classif_access_ctrl
     packet_framework
     vhost_lib
+    metrics_lib
     port_hotplug_framework
     source_org
     dev_kit_build_system
diff --git a/doc/guides/prog_guide/metrics_lib.rst b/doc/guides/prog_guide/metrics_lib.rst
new file mode 100644
index 0000000..87f806d
--- /dev/null
+++ b/doc/guides/prog_guide/metrics_lib.rst
@@ -0,0 +1,180 @@
+..  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.
+
+.. _Metrics_Library:
+
+Metrics Library
+===============
+
+The Metrics library implements a mechanism by which *producers* can
+publish numeric information for later querying by *consumers*. In
+practice producers will typically be other libraries or primary
+processes, whereas consumers will typically be applications.
+
+Metrics themselves are statistics that are not generated by PMDs. Metric
+information is populated using a push model, where producers update the
+values contained within the metric library by calling an update function
+on the relevant metrics. Consumers receive metric information by querying
+the central metric data, which is held in shared memory.
+
+For each metric, a separate value is maintained for each port id, and
+when publishing metric values the producers need to specify which port is
+being updated. In addition there is a special id ``RTE_METRICS_GLOBAL``
+that is intended for global statistics that are not associated with any
+individual device. Since the metrics library is self-contained, the only
+restriction on port numbers is that they are less than ``RTE_MAX_ETHPORTS``
+- there is no requirement for the ports to actually exist.
+
+Initialising the library
+------------------------
+
+Before the library can be used, it has to be initialized by calling
+``rte_metrics_init()`` which sets up the metric store in shared memory.
+This is where producers will publish metric information to, and where
+consumers will query it from.
+
+.. code-block:: c
+
+    rte_metrics_init(rte_socket_id());
+
+This function **must** be called from a primary process, but otherwise
+producers and consumers can be in either primary or secondary processes.
+
+Registering metrics
+-------------------
+
+Metrics must first be *registered*, which is the way producers declare
+the names of the metrics they will be publishing. Registration can either
+be done individually, or a set of metrics can be registered as a group.
+Individual registration is done using ``rte_metrics_reg_name()``:
+
+.. code-block:: c
+
+    id_1 = rte_metrics_reg_name("mean_bits_in");
+    id_2 = rte_metrics_reg_name("mean_bits_out");
+    id_3 = rte_metrics_reg_name("peak_bits_in");
+    id_4 = rte_metrics_reg_name("peak_bits_out");
+
+or alternatively, a set of metrics can be registered together using
+``rte_metrics_reg_names()``:
+
+.. code-block:: c
+
+    const char * const names[] = {
+        "mean_bits_in", "mean_bits_out",
+        "peak_bits_in", "peak_bits_out",
+    };
+    id_set = rte_metrics_reg_names(&names[0], 4);
+
+If the return value is negative, it means registration failed. Otherwise
+the return value is the *key* for the metric, which is used when updating
+values. A table mapping together these key values and the metrics' names
+can be obtained using ``rte_metrics_get_names()``.
+
+Updating metric values
+----------------------
+
+Once registered, producers can update the metric for a given port using
+the ``rte_metrics_update_value()`` function. This uses the metric key
+that is returned when registering the metric, and can also be looked up
+using ``rte_metrics_get_names()``.
+
+.. code-block:: c
+
+    rte_metrics_update_value(port_id, id_1, values[0]);
+    rte_metrics_update_value(port_id, id_2, values[1]);
+    rte_metrics_update_value(port_id, id_3, values[2]);
+    rte_metrics_update_value(port_id, id_4, values[3]);
+
+if metrics were registered as a single set, they can either be updated
+individually using ``rte_metrics_update_value()``, or updated together
+using the ``rte_metrics_update_values()`` function:
+
+.. code-block:: c
+
+    rte_metrics_update_value(port_id, id_set, values[0]);
+    rte_metrics_update_value(port_id, id_set + 1, values[1]);
+    rte_metrics_update_value(port_id, id_set + 2, values[2]);
+    rte_metrics_update_value(port_id, id_set + 3, values[3]);
+
+    rte_metrics_update_values(port_id, id_set, values, 4);
+
+Note that ``rte_metrics_update_values()`` cannot be used to update
+metric values from *multiple* *sets*, as there is no guarantee two
+sets registered one after the other have contiguous id values.
+
+Querying metrics
+----------------
+
+Consumers can obtain metric values by querying the metrics library using
+the ``rte_metrics_get_values()`` function that return an array of
+``struct rte_metric_value``. Each entry within this array contains a metric
+value and its associated key. A key-name mapping can be obtained using the
+``rte_metrics_get_names()`` function that returns an array of
+``struct rte_metric_name`` that is indexed by the key. The following will
+print out all metrics for a given port:
+
+.. code-block:: c
+
+    void print_metrics() {
+        struct rte_metric_name *names;
+        int len;
+
+        len = rte_metrics_get_names(NULL, 0);
+        if (len < 0) {
+            printf("Cannot get metrics count\n");
+            return;
+        }
+        if (len == 0) {
+            printf("No metrics to display (none have been registered)\n");
+            return;
+        }
+        metrics = malloc(sizeof(struct rte_metric_value) * len);
+        names =  malloc(sizeof(struct rte_metric_name) * len);
+        if (metrics == NULL || names == NULL) {
+            printf("Cannot allocate memory\n");
+            free(metrics);
+            free(names);
+            return;
+        }
+        ret = rte_metrics_get_values(port_id, metrics, len);
+        if (ret < 0 || ret > len) {
+            printf("Cannot get metrics values\n");
+            free(metrics);
+            free(names);
+            return;
+        }
+        printf("Metrics for port %i:\n", port_id);
+        for (i = 0; i < len; i++)
+            printf("  %s: %"PRIu64"\n",
+                names[metrics[i].key].name, metrics[i].value);
+        free(metrics);
+        free(names);
+    }
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 357965a..8bd706f 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -368,6 +368,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_mbuf.so.2
      librte_mempool.so.2
      librte_meter.so.1
+   + librte_metrics.so.1
      librte_net.so.1
      librte_pdump.so.1
      librte_pipeline.so.3
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index e25ea9f..3ed809e 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -61,6 +61,14 @@ Resolved Issues
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+* **Added information metric library.**
+
+  A library that allows information metrics to be added and updated
+  by producers, typically other libraries, for later retrieval by
+  consumers such as applications. It is intended to provide a
+  reporting mechanism that is independent of other libraries such
+  as ethdev.
+
 
 EAL
 ~~~
diff --git a/lib/Makefile b/lib/Makefile
index 4178325..29f6a81 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -49,6 +49,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl
 DIRS-$(CONFIG_RTE_LIBRTE_NET) += librte_net
 DIRS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += librte_ip_frag
 DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats
+DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power
 DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter
 DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched
diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile
new file mode 100644
index 0000000..8d6e23a
--- /dev/null
+++ b/lib/librte_metrics/Makefile
@@ -0,0 +1,51 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_metrics.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_metrics_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c
new file mode 100644
index 0000000..aa9ec50
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.c
@@ -0,0 +1,299 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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 <string.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_lcore.h>
+#include <rte_memzone.h>
+#include <rte_spinlock.h>
+
+#define RTE_METRICS_MAX_METRICS 256
+#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS"
+
+/**
+ * Internal stats metadata and value entry.
+ *
+ * @internal
+ */
+struct rte_metrics_meta_s {
+	/** Name of metric */
+	char name[RTE_METRICS_MAX_NAME_LEN];
+	/** Current value for metric */
+	uint64_t value[RTE_MAX_ETHPORTS];
+	/** Used for global metrics */
+	uint64_t global_value;
+	/** Index of next root element (zero for none) */
+	uint16_t idx_next_set;
+	/** Index of next metric in set (zero for none) */
+	uint16_t idx_next_stat;
+};
+
+/**
+ * Internal stats info structure.
+ *
+ * @internal
+ * Offsets into metadata are used instead of pointers because ASLR
+ * means that having the same physical addresses in different
+ * processes is not guaranteed.
+ */
+struct rte_metrics_data_s {
+	/**   Index of last metadata entry with valid data.
+	 * This value is not valid if cnt_stats is zero.
+	 */
+	uint16_t idx_last_set;
+	/**   Number of metrics. */
+	uint16_t cnt_stats;
+	/** Metric data memory block. */
+	struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS];
+	/** Metric data access lock */
+	rte_spinlock_t lock;
+};
+
+void
+rte_metrics_init(int socket_id)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone != NULL)
+		return;
+	memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME,
+		sizeof(struct rte_metrics_data_s), socket_id, 0);
+	if (memzone == NULL)
+		rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n");
+	stats = memzone->addr;
+	memset(stats, 0, sizeof(struct rte_metrics_data_s));
+	rte_spinlock_init(&stats->lock);
+}
+
+int
+rte_metrics_reg_name(const char *name)
+{
+	const char * const list_names[] = {name};
+
+	return rte_metrics_reg_names(list_names, 1);
+}
+
+int
+rte_metrics_reg_names(const char * const *names, uint16_t cnt_names)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	uint16_t idx_base;
+
+	/* Some sanity checks */
+	if (cnt_names < 1 || names == NULL)
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS)
+		return -ENOMEM;
+
+	rte_spinlock_lock(&stats->lock);
+
+	/* Overwritten later if this is actually first set.. */
+	stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats;
+
+	stats->idx_last_set = idx_base = stats->cnt_stats;
+
+	for (idx_name = 0; idx_name < cnt_names; idx_name++) {
+		entry = &stats->metadata[idx_name + stats->cnt_stats];
+		strncpy(entry->name, names[idx_name],
+			RTE_METRICS_MAX_NAME_LEN);
+		memset(entry->value, 0, sizeof(entry->value));
+		entry->idx_next_stat = idx_name + stats->cnt_stats + 1;
+	}
+	entry->idx_next_stat = 0;
+	entry->idx_next_set = 0;
+	stats->cnt_stats += cnt_names;
+
+	rte_spinlock_unlock(&stats->lock);
+
+	return idx_base;
+}
+
+int
+rte_metrics_update_value(int port_id, uint16_t key, const uint64_t value)
+{
+	return rte_metrics_update_values(port_id, key, &value, 1);
+}
+
+int
+rte_metrics_update_values(int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_metric;
+	uint16_t idx_value;
+	uint16_t cnt_setsize;
+
+	if (port_id != RTE_METRICS_GLOBAL &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	if (memzone == NULL)
+		return -EIO;
+	stats = memzone->addr;
+
+	rte_spinlock_lock(&stats->lock);
+	idx_metric = key;
+	cnt_setsize = 1;
+	while (idx_metric < stats->cnt_stats) {
+		entry = &stats->metadata[idx_metric];
+		if (entry->idx_next_stat == 0)
+			break;
+		cnt_setsize++;
+		idx_metric++;
+	}
+	/* Check update does not cross set border */
+	if (count > cnt_setsize) {
+		rte_spinlock_unlock(&stats->lock);
+		return -ERANGE;
+	}
+
+	if (port_id == RTE_METRICS_GLOBAL)
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].global_value =
+				values[idx_value];
+		}
+	else
+		for (idx_value = 0; idx_value < count; idx_value++) {
+			idx_metric = key + idx_value;
+			stats->metadata[idx_metric].value[port_id] =
+				values[idx_value];
+		}
+	rte_spinlock_unlock(&stats->lock);
+	return 0;
+}
+
+int
+rte_metrics_get_names(struct rte_metric_name *names,
+	uint16_t capacity)
+{
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+	if (names != NULL) {
+		if (capacity < stats->cnt_stats) {
+			return_value = stats->cnt_stats;
+			rte_spinlock_unlock(&stats->lock);
+			return return_value;
+		}
+		for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
+			strncpy(names[idx_name].name,
+				stats->metadata[idx_name].name,
+				RTE_METRICS_MAX_NAME_LEN);
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
+
+int
+rte_metrics_get_values(int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity)
+{
+	struct rte_metrics_meta_s *entry;
+	struct rte_metrics_data_s *stats;
+	const struct rte_memzone *memzone;
+	uint16_t idx_name;
+	int return_value;
+
+	if (port_id != RTE_METRICS_GLOBAL &&
+			(port_id < 0 || port_id > RTE_MAX_ETHPORTS))
+		return -EINVAL;
+
+	memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
+	/* If not allocated, fail silently */
+	if (memzone == NULL)
+		return 0;
+	stats = memzone->addr;
+	rte_spinlock_lock(&stats->lock);
+
+	if (values != NULL) {
+		if (capacity < stats->cnt_stats) {
+			return_value = stats->cnt_stats;
+			rte_spinlock_unlock(&stats->lock);
+			return return_value;
+		}
+		if (port_id == RTE_METRICS_GLOBAL)
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->global_value;
+			}
+		else
+			for (idx_name = 0;
+					idx_name < stats->cnt_stats;
+					idx_name++) {
+				entry = &stats->metadata[idx_name];
+				values[idx_name].key = idx_name;
+				values[idx_name].value = entry->value[port_id];
+			}
+	}
+	return_value = stats->cnt_stats;
+	rte_spinlock_unlock(&stats->lock);
+	return return_value;
+}
diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h
new file mode 100644
index 0000000..7458328
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics.h
@@ -0,0 +1,240 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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.
+ */
+
+/**
+ * @file
+ *
+ * DPDK Metrics module
+ *
+ * Metrics are statistics that are not generated by PMDs, and hence
+ * are better reported through a mechanism that is independent from
+ * the ethdev-based extended statistics. Providers will typically
+ * be other libraries and consumers will typically be applications.
+ *
+ * Metric information is populated using a push model, where producers
+ * update the values contained within the metric library by calling
+ * an update function on the relevant metrics. Consumers receive
+ * metric information by querying the central metric data, which is
+ * held in shared memory. Currently only bulk querying of metrics
+ * by consumers is supported.
+ */
+
+#ifndef _RTE_METRICS_H_
+#define _RTE_METRICS_H_
+
+/** Maximum length of metric name (including null-terminator) */
+#define RTE_METRICS_MAX_NAME_LEN 64
+
+/**
+ * Global metric special id.
+ *
+ * When used for the port_id parameter when calling
+ * rte_metrics_update_metric() or rte_metrics_update_metric(),
+ * the global metric, which are not associated with any specific
+ * port (i.e. device), are updated.
+ */
+#define RTE_METRICS_GLOBAL -1
+
+
+/**
+ * A name-key lookup for metrics.
+ *
+ * An array of this structure is returned by rte_metrics_get_names().
+ * The struct rte_metric_value references these names via their array index.
+ */
+struct rte_metric_name {
+	/** String describing metric */
+	char name[RTE_METRICS_MAX_NAME_LEN];
+};
+
+
+/**
+ * Metric value structure.
+ *
+ * This structure is used by rte_metrics_get_values() to return metrics,
+ * which are statistics that are not generated by PMDs. It maps a name key,
+ * which corresponds to an index in the array returned by
+ * rte_metrics_get_names().
+ */
+struct rte_metric_value {
+	/** Numeric identifier of metric. */
+	uint16_t key;
+	/** Value for metric */
+	uint64_t value;
+};
+
+
+/**
+ * Initializes metric module. This function must be called from
+ * a primary process before metrics are used.
+ *
+ * @param socket_id
+ *   Socket to use for shared memory allocation.
+ */
+void rte_metrics_init(int socket_id);
+
+/**
+ * Register a metric, making it available as a reporting parameter.
+ *
+ * Registering a metric is the way producers declare a parameter
+ * that they wish to be reported. Once registered, the associated
+ * numeric key can be obtained via rte_metrics_get_names(), which
+ * is required for updating said metric's value.
+ *
+ * @param name
+ *   Metric name
+ *
+ * @return
+ *  - Zero or positive: Success (index key of new metric)
+ *  - -EIO: Error, unable to access metrics shared memory
+ *    (rte_metrics_init() not called)
+ *  - -EINVAL: Error, invalid parameters
+ *  - -ENOMEM: Error, maximum metrics reached
+ */
+int rte_metrics_reg_name(const char *name);
+
+/**
+ * Register a set of metrics.
+ *
+ * This is a bulk version of rte_metrics_reg_metrics() and aside from
+ * handling multiple keys at once is functionally identical.
+ *
+ * @param names
+ *   List of metric names
+ *
+ * @param cnt_names
+ *   Number of metrics in set
+ *
+ * @return
+ *  - Zero or positive: Success (index key of start of set)
+ *  - -EIO: Error, unable to access metrics shared memory
+ *    (rte_metrics_init() not called)
+ *  - -EINVAL: Error, invalid parameters
+ *  - -ENOMEM: Error, maximum metrics reached
+ */
+int rte_metrics_reg_names(const char * const *names, uint16_t cnt_names);
+
+/**
+ * Get metric name-key lookup table.
+ *
+ * @param names
+ *   A struct rte_metric_name array of at least *capacity* in size to
+ *   receive key names. If this is NULL, function returns the required
+ *   number of elements for this array.
+ *
+ * @param capacity
+ *   Size (number of elements) of struct rte_metric_name array.
+ *   Disregarded if names is NULL.
+ *
+ * @return
+ *   - Positive value above capacity: error, *names* is too small.
+ *     Return value is required size.
+ *   - Positive value equal or less than capacity: Success. Return
+ *     value is number of elements filled in.
+ *   - Negative value: error.
+ */
+int rte_metrics_get_names(
+	struct rte_metric_name *names,
+	uint16_t capacity);
+
+/**
+ * Get metric value table.
+ *
+ * @param port_id
+ *   Port id to query
+ *
+ * @param values
+ *   A struct rte_metric_value array of at least *capacity* in size to
+ *   receive metric ids and values. If this is NULL, function returns
+ *   the required number of elements for this array.
+ *
+ * @param capacity
+ *   Size (number of elements) of struct rte_metric_value array.
+ *   Disregarded if names is NULL.
+ *
+ * @return
+ *   - Positive value above capacity: error, *values* is too small.
+ *     Return value is required size.
+ *   - Positive value equal or less than capacity: Success. Return
+ *     value is number of elements filled in.
+ *   - Negative value: error.
+ */
+int rte_metrics_get_values(
+	int port_id,
+	struct rte_metric_value *values,
+	uint16_t capacity);
+
+/**
+ * Updates a metric
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Id of metric to update
+ * @param value
+ *   New value
+ *
+ * @return
+ *   - -EIO if unable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_value(
+	int port_id,
+	uint16_t key,
+	const uint64_t value);
+
+/**
+ * Updates a metric set. Note that it is an error to try to
+ * update across a set boundary.
+ *
+ * @param port_id
+ *   Port to update metrics for
+ * @param key
+ *   Base id of metrics set to update
+ * @param values
+ *   Set of new values
+ * @param count
+ *   Number of new values
+ *
+ * @return
+ *   - -ERANGE if count exceeds metric set size
+ *   - -EIO if upable to access shared metrics memory
+ *   - Zero on success
+ */
+int rte_metrics_update_values(
+	int port_id,
+	uint16_t key,
+	const uint64_t *values,
+	uint32_t count);
+
+#endif
diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map
new file mode 100644
index 0000000..4c5234c
--- /dev/null
+++ b/lib/librte_metrics/rte_metrics_version.map
@@ -0,0 +1,13 @@
+DPDK_17.05 {
+	global:
+
+	rte_metrics_get_names;
+	rte_metrics_get_values;
+	rte_metrics_init;
+	rte_metrics_reg_name;
+	rte_metrics_reg_names;
+	rte_metrics_update_value;
+	rte_metrics_update_values;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index d46a33e..98eb052 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -99,6 +99,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING)           += -lrte_ring
 _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER)        += -lrte_reorder
+_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+
 
 ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n)
 # plugins (link only if static libraries)
-- 
2.5.5

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

* [PATCH v11 2/7] app/proc_info: add metrics displaying
  2017-03-09 16:25                   ` [PATCH v11 " Remy Horton
  2017-03-09 16:25                     ` [PATCH v11 1/7] lib: add information metrics library Remy Horton
@ 2017-03-09 16:25                     ` Remy Horton
  2017-03-09 16:25                     ` [PATCH v11 3/7] lib: add bitrate statistics library Remy Horton
                                       ` (4 subsequent siblings)
  6 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw)
  To: dev; +Cc: Reshma Pattan, Thomas Monjalon

From: Reshma Pattan <reshma.pattan@intel.com>

Modify the dpdk-procinfo process to display the newly added metrics.
Added new command line option "--metrics" to display metrics.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/proc_info/main.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 78 insertions(+), 1 deletion(-)

diff --git a/app/proc_info/main.c b/app/proc_info/main.c
index 2c56d10..f513669 100644
--- a/app/proc_info/main.c
+++ b/app/proc_info/main.c
@@ -1,7 +1,7 @@
 /*
  *   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
@@ -57,6 +57,7 @@
 #include <rte_atomic.h>
 #include <rte_branch_prediction.h>
 #include <rte_string_fns.h>
+#include <rte_metrics.h>
 
 /* Maximum long option length for option parsing. */
 #define MAX_LONG_OPT_SZ 64
@@ -68,6 +69,8 @@ static uint32_t enabled_port_mask;
 static uint32_t enable_stats;
 /**< Enable xstats. */
 static uint32_t enable_xstats;
+/**< Enable metrics. */
+static uint32_t enable_metrics;
 /**< Enable stats reset. */
 static uint32_t reset_stats;
 /**< Enable xstats reset. */
@@ -85,6 +88,8 @@ proc_info_usage(const char *prgname)
 		"  --stats: to display port statistics, enabled by default\n"
 		"  --xstats: to display extended port statistics, disabled by "
 			"default\n"
+		"  --metrics: to display derived metrics of the ports, disabled by "
+			"default\n"
 		"  --stats-reset: to reset port statistics\n"
 		"  --xstats-reset: to reset port extended statistics\n",
 		prgname);
@@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv)
 		{"stats", 0, NULL, 0},
 		{"stats-reset", 0, NULL, 0},
 		{"xstats", 0, NULL, 0},
+		{"metrics", 0, NULL, 0},
 		{"xstats-reset", 0, NULL, 0},
 		{NULL, 0, 0, 0}
 	};
@@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv)
 			else if (!strncmp(long_option[option_index].name, "xstats",
 					MAX_LONG_OPT_SZ))
 				enable_xstats = 1;
+			else if (!strncmp(long_option[option_index].name,
+					"metrics",
+					MAX_LONG_OPT_SZ))
+				enable_metrics = 1;
 			/* Reset stats */
 			if (!strncmp(long_option[option_index].name, "stats-reset",
 					MAX_LONG_OPT_SZ))
@@ -301,6 +311,67 @@ nic_xstats_clear(uint8_t port_id)
 	printf("\n  NIC extended statistics for port %d cleared\n", port_id);
 }
 
+static void
+metrics_display(int port_id)
+{
+	struct rte_metric_value *metrics;
+	struct rte_metric_name *names;
+	int len, ret;
+	static const char *nic_stats_border = "########################";
+
+	len = rte_metrics_get_names(NULL, 0);
+	if (len < 0) {
+		printf("Cannot get metrics count\n");
+		return;
+	}
+	if (len == 0) {
+		printf("No metrics to display (none have been registered)\n");
+		return;
+	}
+
+	metrics = rte_malloc("proc_info_metrics",
+		sizeof(struct rte_metric_value) * len, 0);
+	if (metrics == NULL) {
+		printf("Cannot allocate memory for metrics\n");
+		return;
+	}
+
+	names =  rte_malloc(NULL, sizeof(struct rte_metric_name) * len, 0);
+	if (names == NULL) {
+		printf("Cannot allocate memory for metrcis names\n");
+		rte_free(metrics);
+		return;
+	}
+
+	if (len != rte_metrics_get_names(names, len)) {
+		printf("Cannot get metrics names\n");
+		rte_free(metrics);
+		rte_free(names);
+		return;
+	}
+
+	if (port_id == RTE_METRICS_GLOBAL)
+		printf("###### Non port specific metrics  #########\n");
+	else
+		printf("###### metrics for port %-2d #########\n", port_id);
+	printf("%s############################\n", nic_stats_border);
+	ret = rte_metrics_get_values(port_id, metrics, len);
+	if (ret < 0 || ret > len) {
+		printf("Cannot get metrics values\n");
+		rte_free(metrics);
+		rte_free(names);
+		return;
+	}
+
+	int i;
+	for (i = 0; i < len; i++)
+		printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value);
+
+	printf("%s############################\n", nic_stats_border);
+	rte_free(metrics);
+	rte_free(names);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -360,8 +431,14 @@ main(int argc, char **argv)
 				nic_stats_clear(i);
 			else if (reset_xstats)
 				nic_xstats_clear(i);
+			else if (enable_metrics)
+				metrics_display(i);
 		}
 	}
 
+	/* print port independent stats */
+	if (enable_metrics)
+		metrics_display(RTE_METRICS_GLOBAL);
+
 	return 0;
 }
-- 
2.5.5

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

* [PATCH v11 3/7] lib: add bitrate statistics library
  2017-03-09 16:25                   ` [PATCH v11 " Remy Horton
  2017-03-09 16:25                     ` [PATCH v11 1/7] lib: add information metrics library Remy Horton
  2017-03-09 16:25                     ` [PATCH v11 2/7] app/proc_info: add metrics displaying Remy Horton
@ 2017-03-09 16:25                     ` Remy Horton
  2017-03-09 16:25                     ` [PATCH v11 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton
                                       ` (3 subsequent siblings)
  6 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

This patch adds a library that calculates peak and average data-rate
statistics. For ethernet devices. These statistics are reported using
the metrics library.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 MAINTAINERS                                        |   4 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/prog_guide/metrics_lib.rst              |  65 ++++++++++
 doc/guides/rel_notes/release_17_02.rst             |   1 +
 doc/guides/rel_notes/release_17_05.rst             |   5 +
 lib/Makefile                                       |   1 +
 lib/librte_bitratestats/Makefile                   |  53 ++++++++
 lib/librte_bitratestats/rte_bitrate.c              | 141 +++++++++++++++++++++
 lib/librte_bitratestats/rte_bitrate.h              |  80 ++++++++++++
 .../rte_bitratestats_version.map                   |   9 ++
 mk/rte.app.mk                                      |   1 +
 13 files changed, 367 insertions(+)
 create mode 100644 lib/librte_bitratestats/Makefile
 create mode 100644 lib/librte_bitratestats/rte_bitrate.c
 create mode 100644 lib/librte_bitratestats/rte_bitrate.h
 create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 66478f3..8abf4fd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -639,6 +639,10 @@ Metrics
 M: Remy Horton <remy.horton@intel.com>
 F: lib/librte_metrics/
 
+Bit-rate statistica
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_bitratestats/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index cea055f..d700ee0 100644
--- a/config/common_base
+++ b/config/common_base
@@ -630,3 +630,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
 # Compile the crypto performance application
 #
 CONFIG_RTE_APP_CRYPTO_PERF=y
+
+#
+# Compile the bitrate statistics library
+#
+CONFIG_RTE_LIBRTE_BITRATE=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 26a26b7..8492bce 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -157,4 +157,5 @@ There are many libraries, so their headers may be grouped by topics:
   [ABI compat]         (@ref rte_compat.h),
   [keepalive]          (@ref rte_keepalive.h),
   [device metrics]     (@ref rte_metrics.h),
+  [bitrate statistics] (@ref rte_bitrate.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index fbbcf8e..c4b3b68 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -36,6 +36,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_eal/common/include \
                           lib/librte_eal/common/include/generic \
                           lib/librte_acl \
+                          lib/librte_bitratestats \
                           lib/librte_cfgfile \
                           lib/librte_cmdline \
                           lib/librte_compat \
diff --git a/doc/guides/prog_guide/metrics_lib.rst b/doc/guides/prog_guide/metrics_lib.rst
index 87f806d..1c2a28f 100644
--- a/doc/guides/prog_guide/metrics_lib.rst
+++ b/doc/guides/prog_guide/metrics_lib.rst
@@ -178,3 +178,68 @@ print out all metrics for a given port:
         free(metrics);
         free(names);
     }
+
+
+Bit-rate statistics library
+---------------------------
+
+The bit-rate library calculates the exponentially-weighted moving
+average and peak bit-rates for each active port (i.e. network device).
+These statistics are reported via the metrics library using the
+following names:
+
+    - ``mean_bits_in``: Average inbound bit-rate
+    - ``mean_bits_out``:  Average outbound bit-rate
+    - ``ewma_bits_in``: Average inbound bit-rate (EWMA smoothed)
+    - ``ewma_bits_out``:  Average outbound bit-rate (EWMA smoothed)
+    - ``peak_bits_in``:  Peak inbound bit-rate
+    - ``peak_bits_out``:  Peak outbound bit-rate
+
+Once initialised and clocked at the appropriate frequency, these
+statistics can be obtained by querying the metrics library.
+
+Initialization
+~~~~~~~~~~~~~~
+
+Before it is used the bit-rate statistics library has to be initialised
+by calling ``rte_stats_bitrate_create()``, which will return a bit-rate
+calculation object. Since the bit-rate library uses the metrics library
+to report the calculated statistics, the bit-rate library then needs to
+register the calculated statistics with the metrics library. This is
+done using the helper function ``rte_stats_bitrate_reg()``.
+
+.. code-block:: c
+
+    struct rte_stats_bitrates *bitrate_data;
+
+    bitrate_data = rte_stats_bitrate_create();
+    if (bitrate_data == NULL)
+        rte_exit(EXIT_FAILURE, "Could not allocate bit-rate data.\n");
+    rte_stats_bitrate_reg(bitrate_data);
+
+Controlling the sampling rate
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Since the library works by periodic sampling but does not use an
+internal thread, the application has to periodically call
+``rte_stats_bitrate_calc()``. The frequency at which this function
+is called should be the intended sampling rate required for the
+calculated statistics. For instance if per-second statistics are
+desired, this function should be called once a second.
+
+.. code-block:: c
+
+    tics_datum = rte_rdtsc();
+    tics_per_1sec = rte_get_timer_hz();
+
+    while( 1 ) {
+        /* ... */
+        tics_current = rte_rdtsc();
+	if (tics_current - tics_datum >= tics_per_1sec) {
+	    /* Periodic bitrate calculation */
+	    for (idx_port = 0; idx_port < cnt_ports; idx_port++)
+	            rte_stats_bitrate_calc(bitrate_data, idx_port);
+		tics_datum = tics_current;
+	    }
+        /* ... */
+    }
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 8bd706f..63786df 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -353,6 +353,7 @@ The libraries prepended with a plus sign were incremented in this version.
 .. code-block:: diff
 
      librte_acl.so.2
+   + librte_bitratestats.so.1
      librte_cfgfile.so.2
      librte_cmdline.so.2
      librte_cryptodev.so.2
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 3ed809e..83c83b2 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -69,6 +69,11 @@ Resolved Issues
   reporting mechanism that is independent of other libraries such
   as ethdev.
 
+* **Added bit-rate calculation library.**
+
+  A library that can be used to calculate device bit-rates. Calculated
+  bitrates are reported using the metrics library.
+
 
 EAL
 ~~~
diff --git a/lib/Makefile b/lib/Makefile
index 29f6a81..ecc54c0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -50,6 +50,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_NET) += librte_net
 DIRS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += librte_ip_frag
 DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
+DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
 DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power
 DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter
 DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched
diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile
new file mode 100644
index 0000000..743b62c
--- /dev/null
+++ b/lib/librte_bitratestats/Makefile
@@ -0,0 +1,53 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016-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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_bitratestats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+
+EXPORT_MAP := rte_bitratestats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c
+
+# Install header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h
+
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c
new file mode 100644
index 0000000..3252598
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.c
@@ -0,0 +1,141 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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 <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
+
+/*
+ * Persistent bit-rate data.
+ * @internal
+ */
+struct rte_stats_bitrate {
+	uint64_t last_ibytes;
+	uint64_t last_obytes;
+	uint64_t peak_ibits;
+	uint64_t peak_obits;
+	uint64_t mean_ibits;
+	uint64_t mean_obits;
+	uint64_t ewma_ibits;
+	uint64_t ewma_obits;
+};
+
+struct rte_stats_bitrates {
+	struct rte_stats_bitrate port_stats[RTE_MAX_ETHPORTS];
+	uint16_t id_stats_set;
+};
+
+struct rte_stats_bitrates *
+rte_stats_bitrate_create(void)
+{
+	return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates),
+		RTE_CACHE_LINE_SIZE);
+}
+
+int
+rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data)
+{
+	const char * const names[] = {
+		"ewma_bits_in", "ewma_bits_out",
+		"mean_bits_in", "mean_bits_out",
+		"peak_bits_in", "peak_bits_out",
+	};
+	int return_value;
+
+	return_value = rte_metrics_reg_names(&names[0], 6);
+	if (return_value >= 0)
+		bitrate_data->id_stats_set = return_value;
+	return return_value;
+}
+
+int
+rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data,
+	uint8_t port_id)
+{
+	struct rte_stats_bitrate *port_data;
+	struct rte_eth_stats eth_stats;
+	int ret_code;
+	uint64_t cnt_bits;
+	int64_t delta;
+	const int64_t alpha_percent = 20;
+	uint64_t values[6];
+
+	ret_code = rte_eth_stats_get(port_id, &eth_stats);
+	if (ret_code != 0)
+		return ret_code;
+
+	port_data = &bitrate_data->port_stats[port_id];
+
+	/* Incoming bitrate. This is an iteratively calculated EWMA
+	 * (Expomentially Weighted Moving Average) that uses a
+	 * weighting factor of alpha_percent. An unsmoothed mean
+	 * for just the current time delta is also calculated for the
+	 * benefit of people who don't understand signal processing.
+	 */
+	cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3;
+	port_data->last_ibytes = eth_stats.ibytes;
+	if (cnt_bits > port_data->peak_ibits)
+		port_data->peak_ibits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_ibits;
+	/* The +-50 fixes integer rounding during divison */
+	if (delta > 0)
+		delta = (delta * alpha_percent + 50) / 100;
+	else
+		delta = (delta * alpha_percent - 50) / 100;
+	port_data->ewma_ibits += delta;
+	port_data->mean_ibits = cnt_bits;
+
+	/* Outgoing bitrate (also EWMA) */
+	cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3;
+	port_data->last_obytes = eth_stats.obytes;
+	if (cnt_bits > port_data->peak_obits)
+		port_data->peak_obits = cnt_bits;
+	delta = cnt_bits;
+	delta -= port_data->ewma_obits;
+	delta = (delta * alpha_percent + 50) / 100;
+	port_data->ewma_obits += delta;
+	port_data->mean_obits = cnt_bits;
+
+	values[0] = port_data->ewma_ibits;
+	values[1] = port_data->ewma_obits;
+	values[2] = port_data->mean_ibits;
+	values[3] = port_data->mean_obits;
+	values[4] = port_data->peak_ibits;
+	values[5] = port_data->peak_obits;
+	rte_metrics_update_values(port_id, bitrate_data->id_stats_set,
+		values, 6);
+	return 0;
+}
diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h
new file mode 100644
index 0000000..564e4f7
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitrate.h
@@ -0,0 +1,80 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-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.
+ */
+
+
+/**
+ *  Bitrate statistics data structure.
+ *  This data structure is intentionally opaque.
+ */
+struct rte_stats_bitrates;
+
+
+/**
+ * Allocate a bitrate statistics structure
+ *
+ * @return
+ *   - Pointer to structure on success
+ *   - NULL on error (zmalloc failure)
+ */
+struct rte_stats_bitrates *rte_stats_bitrate_create(void);
+
+
+/**
+ * Register bitrate statistics with the metric library.
+ *
+ * @param bitrate_data
+ *   Pointer allocated by rte_stats_create()
+ *
+ * @return
+ *   Zero on success
+ *   Negative on error
+ */
+int rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data);
+
+
+/**
+ * Calculate statistics for current time window. The period with which
+ * this function is called should be the intended sampling window width.
+ *
+ * @param bitrate_data
+ *   Bitrate statistics data pointer
+ *
+ * @param port_id
+ *   Port id to calculate statistics for
+ *
+ * @return
+ *  - Zero on success
+ *  - Negative value on error
+ */
+int rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data,
+	uint8_t port_id);
diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map
new file mode 100644
index 0000000..fe74544
--- /dev/null
+++ b/lib/librte_bitratestats/rte_bitratestats_version.map
@@ -0,0 +1,9 @@
+DPDK_17.05 {
+	global:
+
+	rte_stats_bitrate_calc;
+	rte_stats_bitrate_create;
+	rte_stats_bitrate_reg;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 98eb052..39c988a 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -100,6 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER)        += -lrte_reorder
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
+_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
 
 
 ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n)
-- 
2.5.5

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

* [PATCH v11 4/7] app/test-pmd: add bitrate statistics calculation
  2017-03-09 16:25                   ` [PATCH v11 " Remy Horton
                                       ` (2 preceding siblings ...)
  2017-03-09 16:25                     ` [PATCH v11 3/7] lib: add bitrate statistics library Remy Horton
@ 2017-03-09 16:25                     ` Remy Horton
  2017-03-09 16:25                     ` [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton
                                       ` (2 subsequent siblings)
  6 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon

Calculate bitrate statistics using the bitrate stats library. The
resulting statistics can be viewed via proc_info.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/testpmd.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index bfb2f8e..b31a300 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -1,7 +1,7 @@
 /*-
  *   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
@@ -79,6 +79,10 @@
 #include <rte_pdump.h>
 #endif
 #include <rte_flow.h>
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_BITRATE
+#include <rte_bitrate.h>
+#endif
 
 #include "testpmd.h"
 
@@ -323,6 +327,9 @@ uint16_t nb_rx_queue_stats_mappings = 0;
 
 unsigned max_socket = 0;
 
+/* Bitrate statistics */
+struct rte_stats_bitrates *bitrate_data;
+
 /* Forward function declarations */
 static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -922,12 +929,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
 	struct fwd_stream **fsm;
 	streamid_t nb_fs;
 	streamid_t sm_id;
+#ifdef RTE_LIBRTE_BITRATE
+	uint64_t tics_per_1sec;
+	uint64_t tics_datum;
+	uint64_t tics_current;
+	uint8_t idx_port, cnt_ports;
+#endif
 
+#ifdef RTE_LIBRTE_BITRATE
+	cnt_ports = rte_eth_dev_count();
+	tics_datum = rte_rdtsc();
+	tics_per_1sec = rte_get_timer_hz();
+#endif
 	fsm = &fwd_streams[fc->stream_idx];
 	nb_fs = fc->stream_nb;
 	do {
 		for (sm_id = 0; sm_id < nb_fs; sm_id++)
 			(*pkt_fwd)(fsm[sm_id]);
+#ifdef RTE_LIBRTE_BITRATE
+		tics_current = rte_rdtsc();
+		if (tics_current - tics_datum >= tics_per_1sec) {
+			/* Periodic bitrate calculation */
+			for (idx_port = 0; idx_port < cnt_ports; idx_port++)
+				rte_stats_bitrate_calc(bitrate_data, idx_port);
+			tics_datum = tics_current;
+		}
+#endif
 	} while (! fc->stopped);
 }
 
@@ -2139,6 +2166,18 @@ main(int argc, char** argv)
 	FOREACH_PORT(port_id, ports)
 		rte_eth_promiscuous_enable(port_id);
 
+	/* Init metrics library */
+	rte_metrics_init(rte_socket_id());
+
+	/* Setup bitrate stats */
+#ifdef RTE_LIBRTE_BITRATE
+	bitrate_data = rte_stats_bitrate_create();
+	if (bitrate_data == NULL)
+		rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n");
+	rte_stats_bitrate_reg(bitrate_data);
+#endif
+
+
 #ifdef RTE_LIBRTE_CMDLINE
 	if (interactive == 1) {
 		if (auto_start) {
-- 
2.5.5

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

* [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for latencystats
  2017-03-09 16:25                   ` [PATCH v11 " Remy Horton
                                       ` (3 preceding siblings ...)
  2017-03-09 16:25                     ` [PATCH v11 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton
@ 2017-03-09 16:25                     ` Remy Horton
  2017-03-09 19:02                       ` Stephen Hemminger
  2017-03-09 16:25                     ` [PATCH v11 6/7] lib: added new library for latency stats Remy Horton
  2017-03-09 16:25                     ` [PATCH v11 7/7] app/test-pmd: add latency statistics calculation Remy Horton
  6 siblings, 1 reply; 115+ messages in thread
From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw)
  To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan

From: Harry van Haaren <harry.van.haaren@intel.com>

This commit adds a uint64_t to the mbuf struct,
allowing collection of latency and jitter statistics
by measuring packet I/O timestamps. This change is
required by the latencystats library.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
---
 lib/librte_mbuf/rte_mbuf.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index ce57d47..e0dad6e 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -514,6 +514,9 @@ struct rte_mbuf {
 
 	/** Timesync flags for use with IEEE1588. */
 	uint16_t timesync;
+
+	/** Timestamp for measuring latency. */
+	uint64_t timestamp;
 } __rte_cache_aligned;
 
 /**
-- 
2.5.5

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

* [PATCH v11 6/7] lib: added new library for latency stats
  2017-03-09 16:25                   ` [PATCH v11 " Remy Horton
                                       ` (4 preceding siblings ...)
  2017-03-09 16:25                     ` [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton
@ 2017-03-09 16:25                     ` Remy Horton
  2017-03-09 16:25                     ` [PATCH v11 7/7] app/test-pmd: add latency statistics calculation Remy Horton
  6 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw)
  To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan

From: Harry van Haaren <harry.van.haaren@intel.com>

Add a library designed to calculate latency statistics and report them
to the application when queried. The library measures minimum, average and
maximum latencies, and jitter in nano seconds. The current implementation
supports global latency stats, i.e. per application stats.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
---
 MAINTAINERS                                        |   4 +
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/prog_guide/metrics_lib.rst              |  58 +++-
 doc/guides/rel_notes/release_17_02.rst             |   1 +
 doc/guides/rel_notes/release_17_05.rst             |   5 +
 lib/Makefile                                       |   1 +
 lib/librte_latencystats/Makefile                   |  56 ++++
 lib/librte_latencystats/rte_latencystats.c         | 366 +++++++++++++++++++++
 lib/librte_latencystats/rte_latencystats.h         | 154 +++++++++
 .../rte_latencystats_version.map                   |  11 +
 mk/rte.app.mk                                      |   2 +-
 13 files changed, 662 insertions(+), 3 deletions(-)
 create mode 100644 lib/librte_latencystats/Makefile
 create mode 100644 lib/librte_latencystats/rte_latencystats.c
 create mode 100644 lib/librte_latencystats/rte_latencystats.h
 create mode 100644 lib/librte_latencystats/rte_latencystats_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 8abf4fd..0dc95f5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -643,6 +643,10 @@ Bit-rate statistica
 M: Remy Horton <remy.horton@intel.com>
 F: lib/librte_bitratestats/
 
+Latency Stats
+M: Reshma Pattan <reshma.pattan@intel.com>
+F: lib/librte_latencystats/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index d700ee0..9d7bddf 100644
--- a/config/common_base
+++ b/config/common_base
@@ -635,3 +635,8 @@ CONFIG_RTE_APP_CRYPTO_PERF=y
 # Compile the bitrate statistics library
 #
 CONFIG_RTE_LIBRTE_BITRATE=y
+
+#
+# Compile the latency statistics library
+#
+CONFIG_RTE_LIBRTE_LATENCY_STATS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 8492bce..9d1818c 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -158,4 +158,5 @@ There are many libraries, so their headers may be grouped by topics:
   [keepalive]          (@ref rte_keepalive.h),
   [device metrics]     (@ref rte_metrics.h),
   [bitrate statistics] (@ref rte_bitrate.h),
+  [latency statistics] (@ref rte_latencystats.h),
   [version]            (@ref rte_version.h)
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index c4b3b68..5babafa 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -49,6 +49,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_jobstats \
                           lib/librte_kni \
                           lib/librte_kvargs \
+                          lib/librte_latencystats \
                           lib/librte_lpm \
                           lib/librte_mbuf \
                           lib/librte_mempool \
diff --git a/doc/guides/prog_guide/metrics_lib.rst b/doc/guides/prog_guide/metrics_lib.rst
index 1c2a28f..702c29d 100644
--- a/doc/guides/prog_guide/metrics_lib.rst
+++ b/doc/guides/prog_guide/metrics_lib.rst
@@ -201,8 +201,8 @@ statistics can be obtained by querying the metrics library.
 Initialization
 ~~~~~~~~~~~~~~
 
-Before it is used the bit-rate statistics library has to be initialised
-by calling ``rte_stats_bitrate_create()``, which will return a bit-rate
+Before the library can be used, it has to be initialised by calling
+``rte_stats_bitrate_create()``, which will return a bit-rate
 calculation object. Since the bit-rate library uses the metrics library
 to report the calculated statistics, the bit-rate library then needs to
 register the calculated statistics with the metrics library. This is
@@ -243,3 +243,57 @@ desired, this function should be called once a second.
 	    }
         /* ... */
     }
+
+
+Latency statistics library
+--------------------------
+
+The latency statistics library calculates the latency of packet
+processing by a DPDK application, reporting the minimum, average,
+and maximum nano-seconds that packet processing takes, as well as
+the jitter in processing delay. These statistics are then reported
+via the metrics library using the following names:
+
+    - ``min_latency_ns``: Minimum processing latency (nano-seconds)
+    - ``avg_latency_ns``:  Average  processing latency (nano-seconds)
+    - ``mac_latency_ns``:  Maximum  processing latency (nano-seconds)
+    - ``jitter_ns``: Variance in processing latency (nano-seconds)
+
+Once initialised and clocked at the appropriate frequency, these
+statistics can be obtained by querying the metrics library.
+
+Initialization
+~~~~~~~~~~~~~~
+
+Before the library can be used, it has to be initialised by calling
+``rte_latencystats_init()``.
+
+.. code-block:: c
+
+    lcoreid_t latencystats_lcore_id = -1;
+
+    int ret = rte_latencystats_init(1, NULL);
+    if (ret)
+        rte_exit(EXIT_FAILURE, "Could not allocate latency data.\n");
+
+
+Triggering statistic updates
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``rte_latencystats_update()`` function needs to be called
+periodically so that latency statistics can be updated.
+
+.. code-block:: c
+
+    if (latencystats_lcore_id == rte_lcore_id())
+        rte_latencystats_update();
+
+Library shutdown
+~~~~~~~~~~~~~~~~
+
+When finished, ``rte_latencystats_uninit()`` needs to be called to
+de-initialise the latency library.
+
+.. code-block:: c
+
+    rte_latencystats_uninit();
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 63786df..05764a0 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -365,6 +365,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_jobstats.so.1
      librte_kni.so.2
      librte_kvargs.so.1
+   + librte_latencystats.so.1
      librte_lpm.so.2
      librte_mbuf.so.2
      librte_mempool.so.2
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 83c83b2..7b6791f 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -74,6 +74,11 @@ Resolved Issues
   A library that can be used to calculate device bit-rates. Calculated
   bitrates are reported using the metrics library.
 
+* **Added latency stats library.**
+
+  A library that measures packet latency. The collected statistics are jitter
+  and latency. For latency the minimum, average, and maximum is measured.
+
 
 EAL
 ~~~
diff --git a/lib/Makefile b/lib/Makefile
index ecc54c0..78cba3e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -51,6 +51,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += librte_ip_frag
 DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats
 DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics
 DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats
+DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats
 DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power
 DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter
 DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched
diff --git a/lib/librte_latencystats/Makefile b/lib/librte_latencystats/Makefile
new file mode 100644
index 0000000..fd145d3
--- /dev/null
+++ b/lib/librte_latencystats/Makefile
@@ -0,0 +1,56 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2016-2017 Intel Corporation. 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 $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_latencystats.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
+LDLIBS += -lm
+LDLIBS += -lpthread
+
+EXPORT_MAP := rte_latencystats_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) := rte_latencystats.c
+
+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)-include := rte_latencystats.h
+
+# this lib depends upon:
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_mbuf
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_metrics
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_latencystats/rte_latencystats.c b/lib/librte_latencystats/rte_latencystats.c
new file mode 100644
index 0000000..5334b8b
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats.c
@@ -0,0 +1,366 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-2017 Intel Corporation. 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 <unistd.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <math.h>
+
+#include <rte_mbuf.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_metrics.h>
+#include <rte_memzone.h>
+#include <rte_lcore.h>
+#include <rte_timer.h>
+
+#include "rte_latencystats.h"
+
+/** Nano seconds per second */
+#define NS_PER_SEC 1E9
+
+/** Clock cycles per nano second */
+static uint64_t
+latencystat_cycles_per_ns(void)
+{
+	return rte_get_timer_hz() / NS_PER_SEC;
+}
+
+/* Macros for printing using RTE_LOG */
+#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1
+
+static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats";
+static int latency_stats_index;
+static uint64_t samp_intvl;
+static uint64_t timer_tsc;
+static uint64_t prev_tsc;
+
+struct rte_latency_stats {
+	float min_latency; /**< Minimum latency in nano seconds */
+	float avg_latency; /**< Average latency in nano seconds */
+	float max_latency; /**< Maximum latency in nano seconds */
+	float jitter; /** Latency variation */
+};
+
+static struct rte_latency_stats *glob_stats;
+
+struct rxtx_cbs {
+	struct rte_eth_rxtx_callback *cb;
+};
+
+static struct rxtx_cbs rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
+static struct rxtx_cbs tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
+
+struct latency_stats_nameoff {
+	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	unsigned int offset;
+};
+
+static const struct latency_stats_nameoff lat_stats_strings[] = {
+	{"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)},
+	{"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)},
+	{"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)},
+	{"jitter_ns", offsetof(struct rte_latency_stats, jitter)},
+};
+
+#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \
+				sizeof(lat_stats_strings[0]))
+
+int32_t
+rte_latencystats_update(void)
+{
+	unsigned int i;
+	float *stats_ptr = NULL;
+	uint64_t values[NUM_LATENCY_STATS] = {0};
+	int ret;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++) {
+		stats_ptr = RTE_PTR_ADD(glob_stats,
+				lat_stats_strings[i].offset);
+		values[i] = (uint64_t)floor((*stats_ptr)/
+				latencystat_cycles_per_ns());
+	}
+
+	ret = rte_metrics_update_values(RTE_METRICS_GLOBAL,
+					latency_stats_index,
+					values, NUM_LATENCY_STATS);
+	if (ret < 0)
+		RTE_LOG(INFO, LATENCY_STATS, "Failed to push the stats\n");
+
+	return ret;
+}
+
+static void
+rte_latencystats_fill_values(struct rte_metric_value *values)
+{
+	unsigned int i;
+	float *stats_ptr = NULL;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++) {
+		stats_ptr = RTE_PTR_ADD(glob_stats,
+				lat_stats_strings[i].offset);
+		values[i].key = i;
+		values[i].value = (uint64_t)floor((*stats_ptr)/
+						latencystat_cycles_per_ns());
+	}
+}
+
+static uint16_t
+add_time_stamps(uint8_t pid __rte_unused,
+		uint16_t qid __rte_unused,
+		struct rte_mbuf **pkts,
+		uint16_t nb_pkts,
+		uint16_t max_pkts __rte_unused,
+		void *user_cb __rte_unused)
+{
+	unsigned int i;
+	uint64_t diff_tsc, now;
+
+	/*
+	 * For every sample interval,
+	 * time stamp is marked on one received packet.
+	 */
+	now = rte_rdtsc();
+	for (i = 0; i < nb_pkts; i++) {
+		diff_tsc = now - prev_tsc;
+		timer_tsc += diff_tsc;
+		if (timer_tsc >= samp_intvl) {
+			/*
+			 * TBD: Mark the timestamp only
+			 * if not already marked by the
+			 * hardware or the PMD.
+			 */
+			pkts[i]->timestamp = now;
+			timer_tsc = 0;
+		}
+		prev_tsc = now;
+		now = rte_rdtsc();
+	}
+
+	return nb_pkts;
+}
+
+static uint16_t
+calc_latency(uint8_t pid __rte_unused,
+		uint16_t qid __rte_unused,
+		struct rte_mbuf **pkts,
+		uint16_t nb_pkts,
+		void *_ __rte_unused)
+{
+	unsigned int i, cnt = 0;
+	uint64_t now;
+	float latency[nb_pkts];
+	static float prev_latency;
+	/*
+	 * Alpha represents degree of weighting decrease in EWMA,
+	 * a constant smoothing factor between 0 and 1. The value
+	 * is used below for measuring average latency.
+	 */
+	const float alpha = 0.2;
+
+	now = rte_rdtsc();
+	for (i = 0; i < nb_pkts; i++) {
+		if (pkts[i]->timestamp)
+			latency[cnt++] = now - pkts[i]->timestamp;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		/*
+		 * The jitter is calculated as statistical mean of interpacket
+		 * delay variation. The "jitter estimate" is computed by taking
+		 * the absolute values of the ipdv sequence and applying an
+		 * exponential filter with parameter 1/16 to generate the
+		 * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter,
+		 * D(i-1,i) is difference in latency of two consecutive packets
+		 * i-1 and i.
+		 * Reference: Calculated as per RFC 5481, sec 4.1,
+		 * RFC 3393 sec 4.5, RFC 1889 sec.
+		 */
+		glob_stats->jitter +=  (abs(prev_latency - latency[i])
+					- glob_stats->jitter)/16;
+		if (glob_stats->min_latency == 0)
+			glob_stats->min_latency = latency[i];
+		else if (latency[i] < glob_stats->min_latency)
+			glob_stats->min_latency = latency[i];
+		else if (latency[i] > glob_stats->max_latency)
+			glob_stats->max_latency = latency[i];
+		/*
+		 * The average latency is measured using exponential moving
+		 * average, i.e. using EWMA
+		 * https://en.wikipedia.org/wiki/Moving_average
+		 */
+		glob_stats->avg_latency +=
+			alpha * (latency[i] - glob_stats->avg_latency);
+		prev_latency = latency[i];
+	}
+
+	return nb_pkts;
+}
+
+int
+rte_latencystats_init(uint64_t app_samp_intvl,
+		rte_latency_stats_flow_type_fn user_cb)
+{
+	unsigned int i;
+	uint8_t pid;
+	uint16_t qid;
+	struct rxtx_cbs *cbs = NULL;
+	const uint8_t nb_ports = rte_eth_dev_count();
+	const char *ptr_strings[NUM_LATENCY_STATS] = {0};
+	const struct rte_memzone *mz = NULL;
+	const unsigned int flags = 0;
+
+	if (rte_memzone_lookup(MZ_RTE_LATENCY_STATS))
+		return -EEXIST;
+
+	/** Allocate stats in shared memory fo multi process support */
+	mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats),
+					rte_socket_id(), flags);
+	if (mz == NULL) {
+		RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n",
+			__func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	glob_stats = mz->addr;
+	samp_intvl = app_samp_intvl * latencystat_cycles_per_ns();
+
+	/** Register latency stats with stats library */
+	for (i = 0; i < NUM_LATENCY_STATS; i++)
+		ptr_strings[i] = lat_stats_strings[i].name;
+
+	latency_stats_index = rte_metrics_reg_names(ptr_strings,
+							NUM_LATENCY_STATS);
+	if (latency_stats_index < 0) {
+		RTE_LOG(DEBUG, LATENCY_STATS,
+			"Failed to register latency stats names\n");
+		return -1;
+	}
+
+	/** Register Rx/Tx callbacks */
+	for (pid = 0; pid < nb_ports; pid++) {
+		struct rte_eth_dev_info dev_info;
+		rte_eth_dev_info_get(pid, &dev_info);
+		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
+			cbs = &rx_cbs[pid][qid];
+			cbs->cb = rte_eth_add_first_rx_callback(pid, qid,
+					add_time_stamps, user_cb);
+			if (!cbs->cb)
+				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
+					"register Rx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
+			cbs = &tx_cbs[pid][qid];
+			cbs->cb =  rte_eth_add_tx_callback(pid, qid,
+					calc_latency, user_cb);
+			if (!cbs->cb)
+				RTE_LOG(INFO, LATENCY_STATS, "Failed to "
+					"register Tx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+	}
+	return 0;
+}
+
+int
+rte_latencystats_uninit(void)
+{
+	uint8_t pid;
+	uint16_t qid;
+	int ret = 0;
+	struct rxtx_cbs *cbs = NULL;
+	const uint8_t nb_ports = rte_eth_dev_count();
+
+	/** De register Rx/Tx callbacks */
+	for (pid = 0; pid < nb_ports; pid++) {
+		struct rte_eth_dev_info dev_info;
+		rte_eth_dev_info_get(pid, &dev_info);
+		for (qid = 0; qid < dev_info.nb_rx_queues; qid++) {
+			cbs = &rx_cbs[pid][qid];
+			ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb);
+			if (ret)
+				RTE_LOG(INFO, LATENCY_STATS, "failed to "
+					"remove Rx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
+			cbs = &tx_cbs[pid][qid];
+			ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb);
+			if (ret)
+				RTE_LOG(INFO, LATENCY_STATS, "failed to "
+					"remove Tx callback for pid=%d, "
+					"qid=%d\n", pid, qid);
+		}
+	}
+
+	return 0;
+}
+
+int
+rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size)
+{
+	unsigned int i;
+
+	if (names == NULL || size < NUM_LATENCY_STATS)
+		return NUM_LATENCY_STATS;
+
+	for (i = 0; i < NUM_LATENCY_STATS; i++)
+		snprintf(names[i].name, sizeof(names[i].name),
+				"%s", lat_stats_strings[i].name);
+
+	return NUM_LATENCY_STATS;
+}
+
+int
+rte_latencystats_get(struct rte_metric_value *values, uint16_t size)
+{
+	if (size < NUM_LATENCY_STATS || values == NULL)
+		return NUM_LATENCY_STATS;
+
+	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		const struct rte_memzone *mz;
+		mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS);
+		if (mz == NULL) {
+			RTE_LOG(ERR, LATENCY_STATS,
+				"Latency stats memzone not found\n");
+			return -ENOMEM;
+		}
+		glob_stats =  mz->addr;
+	}
+
+	/* Retrieve latency stats */
+	rte_latencystats_fill_values(values);
+
+	return NUM_LATENCY_STATS;
+}
diff --git a/lib/librte_latencystats/rte_latencystats.h b/lib/librte_latencystats/rte_latencystats.h
new file mode 100644
index 0000000..28c6dcf
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats.h
@@ -0,0 +1,154 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-2017 Intel Corporation. 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 _RTE_LATENCYSTATS_H_
+#define _RTE_LATENCYSTATS_H_
+
+/**
+ * @file
+ * RTE latency stats
+ *
+ * library to provide application and flow based latency stats.
+ */
+
+#include <rte_metrics.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  Note: This function pointer is for future flow based latency stats
+ *  implementation.
+ *
+ * Function type used for identifting flow types of a Rx packet.
+ *
+ * The callback function is called on Rx for each packet.
+ * This function is used for flow based latency calculations.
+ *
+ * @param pkt
+ *   Packet that has to be identified with its flow types.
+ * @param user_param
+ *   The arbitrary user parameter passed in by the application when
+ *   the callback was originally configured.
+ * @return
+ *   The flow_mask, representing the multiple flow types of a packet.
+ */
+typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt,
+							void *user_param);
+
+/**
+ *  Registers Rx/Tx callbacks for each active port, queue.
+ *
+ * @param samp_intvl
+ *  Sampling time period in nano seconds, at which packet
+ *  should be marked with time stamp.
+ * @param user_cb
+ *  Note: This param is for future flow based latency stats
+ *  implementation.
+ *  User callback to be called to get flow types of a packet.
+ *  Used for flow based latency calculation.
+ *  If the value is NULL, global stats will be calculated,
+ *  else flow based latency stats will be calculated.
+ *  For now just pass on the NULL value to this param.
+ *  @return
+ *   -1     : On error
+ *   -ENOMEM: On error
+ *    0     : On success
+ */
+int rte_latencystats_init(uint64_t samp_intvl,
+			rte_latency_stats_flow_type_fn user_cb);
+
+/**
+ * Calculates the latency and jitter values internally, exposing the updated
+ * values via *rte_latencystats_get* or the rte_metrics API.
+ * @return:
+ *  0      : on Success
+ *  < 0    : Error in updating values.
+ */
+int32_t rte_latencystats_update(void);
+
+/**
+ *  Removes registered Rx/Tx callbacks for each active port, queue.
+ *
+ *  @return
+ *   -1: On error
+ *    0: On success
+ */
+int rte_latencystats_uninit(void);
+
+/**
+ * Retrieve names of latency statistics
+ *
+ * @param names
+ *  Block of memory to insert names into. Must be at least size in capacity.
+ *  If set to NULL, function returns required capacity.
+ * @param size
+ *  Capacity of latency stats names (number of names).
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ */
+int rte_latencystats_get_names(struct rte_metric_name *names,
+				uint16_t size);
+
+/**
+ * Retrieve latency statistics.
+ *
+ * @param values
+ *   A pointer to a table of structure of type *rte_metric_value*
+ *   to be filled with latency statistics ids and values.
+ *   This parameter can be set to NULL if size is 0.
+ * @param size
+ *   The size of the stats table, which should be large enough to store
+ *   all the latency stats.
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ *   -ENOMEM: On failure.
+ */
+int rte_latencystats_get(struct rte_metric_value *values,
+			uint16_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_LATENCYSTATS_H_ */
diff --git a/lib/librte_latencystats/rte_latencystats_version.map b/lib/librte_latencystats/rte_latencystats_version.map
new file mode 100644
index 0000000..ac8403e
--- /dev/null
+++ b/lib/librte_latencystats/rte_latencystats_version.map
@@ -0,0 +1,11 @@
+DPDK_17.05 {
+	global:
+
+	rte_latencystats_get;
+	rte_latencystats_get_names;
+	rte_latencystats_init;
+	rte_latencystats_uninit;
+	rte_latencystats_update;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 39c988a..4dfb413 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -101,7 +101,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER)        += -lrte_reorder
 _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS)        += -lrte_metrics
 _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE)        += -lrte_bitratestats
-
+_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)  += -lrte_latencystats
 
 ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n)
 # plugins (link only if static libraries)
-- 
2.5.5

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

* [PATCH v11 7/7] app/test-pmd: add latency statistics calculation
  2017-03-09 16:25                   ` [PATCH v11 " Remy Horton
                                       ` (5 preceding siblings ...)
  2017-03-09 16:25                     ` [PATCH v11 6/7] lib: added new library for latency stats Remy Horton
@ 2017-03-09 16:25                     ` Remy Horton
  6 siblings, 0 replies; 115+ messages in thread
From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw)
  To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan

From: Harry van Haaren <harry.van.haaren@intel.com>

This patch adds latency stats commandline argument to testpmd,
allowing to specify the lcore to use for latencystats updates.

Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/parameters.c | 20 +++++++++++++++++++-
 app/test-pmd/testpmd.c    | 37 +++++++++++++++++++++++++++++++++++++
 app/test-pmd/testpmd.h    |  6 +++++-
 3 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 28db8cd..30b60ba 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -1,7 +1,7 @@
 /*-
  *   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
@@ -149,6 +149,10 @@ usage(char* progname)
 	       "the packet will be enqueued into the rx drop-queue. "
 	       "If the drop-queue doesn't exist, the packet is dropped. "
 	       "By default drop-queue=127.\n");
+#ifdef RTE_LIBRTE_LATENCY_STATS
+	printf("  --latencystats=N: enable latency and jitter statistcs "
+	       "monitoring on lcore id N.\n");
+#endif
 	printf("  --crc-strip: enable CRC stripping by hardware.\n");
 	printf("  --enable-lro: enable large receive offload.\n");
 	printf("  --enable-rx-cksum: enable rx hardware checksum offload.\n");
@@ -526,6 +530,7 @@ launch_args_parse(int argc, char** argv)
 		{ "pkt-filter-report-hash",     1, 0, 0 },
 		{ "pkt-filter-size",            1, 0, 0 },
 		{ "pkt-filter-drop-queue",      1, 0, 0 },
+		{ "latencystats",               1, 0, 0 },
 		{ "crc-strip",                  0, 0, 0 },
 		{ "enable-lro",                 0, 0, 0 },
 		{ "enable-rx-cksum",            0, 0, 0 },
@@ -766,6 +771,19 @@ launch_args_parse(int argc, char** argv)
 						 "drop queue %d invalid - must"
 						 "be >= 0 \n", n);
 			}
+#ifdef RTE_LIBRTE_LATENCY_STATS
+			if (!strcmp(lgopts[opt_idx].name,
+				    "latencystats")) {
+				n = atoi(optarg);
+				if (n >= 0) {
+					latencystats_lcore_id = (lcoreid_t) n;
+					latencystats_enabled = 1;
+				} else
+					rte_exit(EXIT_FAILURE,
+						 "invalid lcore id %d for latencystats"
+						 " must be >= 0\n", n);
+			}
+#endif
 			if (!strcmp(lgopts[opt_idx].name, "crc-strip"))
 				rx_mode.hw_strip_crc = 1;
 			if (!strcmp(lgopts[opt_idx].name, "enable-lro"))
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index b31a300..524e758 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -83,6 +83,10 @@
 #ifdef RTE_LIBRTE_BITRATE
 #include <rte_bitrate.h>
 #endif
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_LATENCY_STATS
+#include <rte_latencystats.h>
+#endif
 
 #include "testpmd.h"
 
@@ -276,6 +280,20 @@ uint32_t bypass_timeout = RTE_BYPASS_TMT_OFF;
 
 #endif
 
+#ifdef RTE_LIBRTE_LATENCY_STATS
+
+/*
+ * Set when latency stats is enabled in the commandline
+ */
+uint8_t latencystats_enabled;
+
+/*
+ * Lcore ID to serive latency statistics.
+ */
+lcoreid_t latencystats_lcore_id = -1;
+
+#endif
+
 /*
  * Ethernet device configuration.
  */
@@ -955,6 +973,11 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
 			tics_datum = tics_current;
 		}
 #endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+		if (latencystats_lcore_id == rte_lcore_id())
+			rte_latencystats_update();
+#endif
+
 	} while (! fc->stopped);
 }
 
@@ -2108,6 +2131,9 @@ signal_handler(int signum)
 		/* uninitialize packet capture framework */
 		rte_pdump_uninit();
 #endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+		rte_latencystats_uninit();
+#endif
 		force_quit();
 		/* exit with the expected status */
 		signal(signum, SIG_DFL);
@@ -2169,6 +2195,17 @@ main(int argc, char** argv)
 	/* Init metrics library */
 	rte_metrics_init(rte_socket_id());
 
+#ifdef RTE_LIBRTE_LATENCY_STATS
+	if (latencystats_enabled != 0) {
+		int ret = rte_latencystats_init(1, NULL);
+		if (ret)
+			printf("Warning: latencystats init()"
+				" returned error %d\n",	ret);
+		printf("Latencystats running on lcore %d\n",
+			latencystats_lcore_id);
+	}
+#endif
+
 	/* Setup bitrate stats */
 #ifdef RTE_LIBRTE_BITRATE
 	bitrate_data = rte_stats_bitrate_create();
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 8cf2860..f0652ee 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -1,7 +1,7 @@
 /*-
  *   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
@@ -381,6 +381,10 @@ extern enum dcb_queue_mapping_mode dcb_q_mapping;
 extern uint16_t mbuf_data_size; /**< Mbuf data space size. */
 extern uint32_t param_total_num_mbufs;
 
+
+extern uint8_t latencystats_enabled;
+extern lcoreid_t latencystats_lcore_id;
+
 extern struct rte_fdir_conf fdir_conf;
 
 /*
-- 
2.5.5

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

* Re: [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for latencystats
  2017-03-09 16:25                     ` [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton
@ 2017-03-09 19:02                       ` Stephen Hemminger
  2017-03-10  9:48                         ` Van Haaren, Harry
  0 siblings, 1 reply; 115+ messages in thread
From: Stephen Hemminger @ 2017-03-09 19:02 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev, Harry van Haaren, Thomas Monjalon, Reshma Pattan

On Thu,  9 Mar 2017 16:25:32 +0000
Remy Horton <remy.horton@intel.com> wrote:

> From: Harry van Haaren <harry.van.haaren@intel.com>
> 
> This commit adds a uint64_t to the mbuf struct,
> allowing collection of latency and jitter statistics
> by measuring packet I/O timestamps. This change is
> required by the latencystats library.
> 
> Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
> ---
>  lib/librte_mbuf/rte_mbuf.h | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
> index ce57d47..e0dad6e 100644
> --- a/lib/librte_mbuf/rte_mbuf.h
> +++ b/lib/librte_mbuf/rte_mbuf.h
> @@ -514,6 +514,9 @@ struct rte_mbuf {
>  
>  	/** Timesync flags for use with IEEE1588. */
>  	uint16_t timesync;
> +
> +	/** Timestamp for measuring latency. */
> +	uint64_t timestamp;
>  } __rte_cache_aligned;
>  
>  /**

This creates a hole in the mbuf structure, and won't apply to current
version of mbuf that has priv_size.

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

* Re: [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for latencystats
  2017-03-09 19:02                       ` Stephen Hemminger
@ 2017-03-10  9:48                         ` Van Haaren, Harry
  0 siblings, 0 replies; 115+ messages in thread
From: Van Haaren, Harry @ 2017-03-10  9:48 UTC (permalink / raw)
  To: Stephen Hemminger, Horton, Remy; +Cc: dev, Thomas Monjalon, Pattan, Reshma

> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Cc: dev@dpdk.org; Van Haaren, Harry <harry.van.haaren@intel.com>; Thomas Monjalon
> <thomas.monjalon@6wind.com>; Pattan, Reshma <reshma.pattan@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for
> latencystats
> 
> On Thu,  9 Mar 2017 16:25:32 +0000
> Remy Horton <remy.horton@intel.com> wrote:
> 
> > From: Harry van Haaren <harry.van.haaren@intel.com>
> >
> > This commit adds a uint64_t to the mbuf struct,
> > allowing collection of latency and jitter statistics
> > by measuring packet I/O timestamps. This change is
> > required by the latencystats library.
> >
> > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
> > Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
> > ---
> >  lib/librte_mbuf/rte_mbuf.h | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
> > index ce57d47..e0dad6e 100644
> > --- a/lib/librte_mbuf/rte_mbuf.h
> > +++ b/lib/librte_mbuf/rte_mbuf.h
> > @@ -514,6 +514,9 @@ struct rte_mbuf {
> >
> >  	/** Timesync flags for use with IEEE1588. */
> >  	uint16_t timesync;
> > +
> > +	/** Timestamp for measuring latency. */
> > +	uint64_t timestamp;
> >  } __rte_cache_aligned;
> >
> >  /**
> 
> This creates a hole in the mbuf structure, and won't apply to current
> version of mbuf that has priv_size.

This series was previously targeted to 17.02 when the mbuf rework was on the horizon, so placement of the timestamp was not as critical as it is now. Given the mbuf rework[1] is currently in progress, perhaps it is smarter to remove this patch from the patchset and depend on the mbuf rework patchset to add the timestamp instead.

The latency stat library should probably also set the new PKT_RX_TIMESTAMP field in the mbuf[2].

[1] mbuf rework    http://dpdk.org/dev/patchwork/patch/21601/
[2] mbuf timestamp http://dpdk.org/dev/patchwork/patch/21607/

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

end of thread, other threads:[~2017-03-10  9:48 UTC | newest]

Thread overview: 115+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-24 14:58 [RFC PATCH v1] rte: add bit-rate metrics to xstats Remy Horton
2016-08-26 13:28 ` Pattan, Reshma
2016-08-29 10:01 ` Pattan, Reshma
2016-08-29 11:19   ` Remy Horton
2016-10-28  1:04 ` [PATCH v2 0/3] expanded statistic reporting Remy Horton
2016-10-28  1:04   ` [RFC PATCH v2 1/3] lib: add information metrics library Remy Horton
2016-10-28  1:04   ` [RFC PATCH v2 2/3] lib: add bitrate statistics library Remy Horton
2016-10-28  1:12     ` Stephen Hemminger
2016-10-28  7:48       ` Remy Horton
2016-10-28  7:39     ` Morten Brørup
2016-11-01  1:53       ` Remy Horton
2016-10-28  1:04   ` [RFC PATCH v2 3/3] app/test-pmd: add support for bitrate statistics Remy Horton
2016-11-04  3:36   ` [PATCH v3 0/3] Expanded statistics reporting Remy Horton
2016-11-04  3:36     ` [PATCH v3 1/3] lib: add information metrics library Remy Horton
2016-11-04 16:42       ` Pattan, Reshma
2016-11-07 15:25         ` Pattan, Reshma
2016-11-08  3:19           ` Remy Horton
2016-11-04  3:36     ` [PATCH v3 2/3] lib: add bitrate statistics library Remy Horton
2016-11-04  3:36     ` [PATCH v3 3/3] app/test-pmd: add support for bitrate statistics Remy Horton
2016-11-15  7:15     ` [PATCH v4 0/3] Expanded statistics reporting Remy Horton
2016-11-15  7:15       ` [PATCH v4 1/3] lib: add information metrics library Remy Horton
2016-11-15  7:15       ` [PATCH v4 2/3] lib: add bitrate statistics library Remy Horton
2016-11-15 15:17         ` Pattan, Reshma
2016-11-15  7:15       ` [PATCH v4 3/3] app/test-pmd: add support for bitrate statistics Remy Horton
2016-11-18  8:00       ` [PATCH v5 0/4] Expanded statistics reporting Remy Horton
2016-11-18  8:00         ` [PATCH v5 1/4] lib: add information metrics library Remy Horton
2016-11-18  8:00         ` [PATCH v5 2/4] lib: add bitrate statistics library Remy Horton
2016-11-18  8:00         ` [PATCH v5 3/4] app/test-pmd: add support for bitrate statistics Remy Horton
2016-11-18  8:00         ` [PATCH v5 4/4] latencystats: added new library for latency stats Remy Horton
2017-01-11 16:03         ` [PATCH v6 0/4] Expanded statistics reporting Remy Horton
2017-01-11 16:03           ` [PATCH v6 1/4] lib: add information metrics library Remy Horton
2017-01-12 13:22             ` Thomas Monjalon
2017-01-12 15:30               ` Remy Horton
2017-01-12 19:05                 ` Thomas Monjalon
2017-01-16 10:27                   ` Remy Horton
2017-01-11 16:03           ` [PATCH v6 2/4] lib: add bitrate statistics library Remy Horton
2017-01-11 16:15             ` Stephen Hemminger
2017-01-16 13:18               ` Remy Horton
2017-01-11 16:03           ` [PATCH v6 3/4] app/test-pmd: add support for bitrate statistics Remy Horton
2017-01-12 13:32             ` Thomas Monjalon
2017-01-11 16:03           ` [PATCH v6 4/4] latencystats: added new library for latency stats Remy Horton
2017-01-12 13:41             ` Thomas Monjalon
2017-01-12 14:44               ` Remy Horton
2017-01-13  9:45               ` Mcnamara, John
2017-01-13  9:53                 ` Thomas Monjalon
2017-01-16 16:18                   ` Mcnamara, John
2017-01-11 16:58           ` [PATCH v6 0/4] Expanded statistics reporting Thomas Monjalon
2017-01-16 16:19           ` [PATCH v7 0/6] " Remy Horton
2017-01-16 16:19             ` [PATCH v7 1/6] lib: add information metrics library Remy Horton
2017-01-17 11:01               ` Van Haaren, Harry
2017-01-17 13:40                 ` Remy Horton
2017-01-17 14:23                   ` Van Haaren, Harry
2017-01-16 16:19             ` [PATCH v7 2/6] app/proc_info: add metrics displaying Remy Horton
2017-01-17 11:08               ` Van Haaren, Harry
2017-01-17 14:27                 ` Remy Horton
2017-01-16 16:19             ` [PATCH v7 3/6] lib: add bitrate statistics library Remy Horton
2017-01-17 11:16               ` Van Haaren, Harry
2017-01-17 15:37                 ` Remy Horton
2017-01-16 16:19             ` [PATCH v7 4/6] app/test-pmd: add bitrate statistics calculation Remy Horton
2017-01-17 11:19               ` Van Haaren, Harry
2017-01-16 16:19             ` [PATCH v7 5/6] lib: added new library for latency stats Remy Horton
2017-01-17  4:29               ` Jerin Jacob
2017-01-17  6:48                 ` Remy Horton
2017-01-17  7:35                   ` Jerin Jacob
2017-01-17 11:19                 ` Mcnamara, John
2017-01-17 12:34                   ` Jerin Jacob
2017-01-17 14:53                     ` Mcnamara, John
2017-01-17 16:25                       ` Jerin Jacob
2017-01-18 20:11                         ` Olivier Matz
2017-01-24 15:24                           ` Olivier MATZ
2017-01-17 11:41               ` Van Haaren, Harry
2017-01-16 16:19             ` [PATCH v7 6/6] app/test-pmd: add latency statistics calculation Remy Horton
2017-01-17 11:45               ` Van Haaren, Harry
2017-01-17 23:24             ` [PATCH v8 0/7] Expanded statistics reporting Remy Horton
2017-01-17 23:24               ` [PATCH v8 1/7] lib: add information metrics library Remy Horton
2017-01-17 23:24               ` [PATCH v8 2/7] app/proc_info: add metrics displaying Remy Horton
2017-01-17 23:24               ` [PATCH v8 3/7] lib: add bitrate statistics library Remy Horton
2017-01-17 23:24               ` [PATCH v8 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton
2017-01-17 23:24               ` [PATCH v8 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton
2017-01-17 23:24               ` [PATCH v8 6/7] lib: added new library for latency stats Remy Horton
2017-01-17 23:24               ` [PATCH v8 7/7] app/test-pmd: add latency statistics calculation Remy Horton
2017-01-18 15:05               ` [PATCH v9 0/7] Expanded statistics reporting Remy Horton
2017-01-18 15:05                 ` [PATCH v9 1/7] lib: add information metrics library Remy Horton
2017-01-30 15:50                   ` Thomas Monjalon
2017-01-30 21:44                     ` Remy Horton
2017-01-31 13:13                     ` Mcnamara, John
2017-01-31 13:28                       ` Bruce Richardson
2017-02-02 17:22                         ` Thomas Monjalon
2017-01-18 15:05                 ` [PATCH v9 2/7] app/proc_info: add metrics displaying Remy Horton
2017-01-18 15:05                 ` [PATCH v9 3/7] lib: add bitrate statistics library Remy Horton
2017-01-18 15:05                 ` [PATCH v9 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton
2017-01-18 15:05                 ` [PATCH v9 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton
2017-01-18 15:05                 ` [PATCH v9 6/7] lib: added new library for latency stats Remy Horton
2017-01-18 15:05                 ` [PATCH v9 7/7] app/test-pmd: add latency statistics calculation Remy Horton
2017-02-03 10:33                 ` [PATCH v10 0/7] Expanded statistics reporting Remy Horton
2017-02-03 10:33                   ` [PATCH v10 1/7] lib: add information metrics library Remy Horton
2017-02-03 10:33                   ` [PATCH v10 2/7] app/proc_info: add metrics displaying Remy Horton
2017-02-03 10:33                   ` [PATCH v10 3/7] lib: add bitrate statistics library Remy Horton
2017-02-03 10:33                   ` [PATCH v10 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton
2017-02-03 10:33                   ` [PATCH v10 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton
2017-02-03 10:33                   ` [PATCH v10 6/7] lib: added new library for latency stats Remy Horton
2017-02-03 10:33                   ` [PATCH v10 7/7] app/test-pmd: add latency statistics calculation Remy Horton
2017-02-16 10:53                   ` [PATCH v10 0/7] Expanded statistics reporting Thomas Monjalon
2017-02-23  7:09                     ` Remy Horton
2017-02-23  8:45                       ` Thomas Monjalon
2017-03-09 16:25                   ` [PATCH v11 " Remy Horton
2017-03-09 16:25                     ` [PATCH v11 1/7] lib: add information metrics library Remy Horton
2017-03-09 16:25                     ` [PATCH v11 2/7] app/proc_info: add metrics displaying Remy Horton
2017-03-09 16:25                     ` [PATCH v11 3/7] lib: add bitrate statistics library Remy Horton
2017-03-09 16:25                     ` [PATCH v11 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton
2017-03-09 16:25                     ` [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton
2017-03-09 19:02                       ` Stephen Hemminger
2017-03-10  9:48                         ` Van Haaren, Harry
2017-03-09 16:25                     ` [PATCH v11 6/7] lib: added new library for latency stats Remy Horton
2017-03-09 16:25                     ` [PATCH v11 7/7] app/test-pmd: add latency statistics calculation Remy Horton

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.