DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] doc: fix openssl formating text
From: De Lara Guarch, Pablo @ 2017-01-11 15:50 UTC (permalink / raw)
  To: Mrzyglod, DanielX T, Mrozowicz, SlawomirX
  Cc: dev@dpdk.org, Mrzyglod, DanielX T
In-Reply-To: <1484059465-113296-1-git-send-email-danielx.t.mrzyglod@intel.com>



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Daniel Mrzyglod
> Sent: Tuesday, January 10, 2017 2:44 PM
> To: Mrozowicz, SlawomirX
> Cc: dev@dpdk.org; Mrzyglod, DanielX T
> Subject: [dpdk-dev] [PATCH] doc: fix openssl formating text
> 
> The code section was lacking indentation to be be correctly formatted.
> 
> Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>

^ permalink raw reply

* Re: [PATCH v3 0/6] libeventdev API and northbound implementation
From: Jerin Jacob @ 2017-01-11 15:52 UTC (permalink / raw)
  To: Bruce Richardson
  Cc: dev, thomas.monjalon, hemant.agrawal, gage.eads, harry.van.haaren
In-Reply-To: <20161220132251.GA211688@bricha3-MOBL3.ger.corp.intel.com>

On Tue, Dec 20, 2016 at 01:22:51PM +0000, Bruce Richardson wrote:
> On Tue, Dec 20, 2016 at 06:39:30PM +0530, Jerin Jacob wrote:
> > On Tue, Dec 20, 2016 at 11:13:42AM +0000, Bruce Richardson wrote:
> > > On Sun, Dec 18, 2016 at 07:51:29PM +0530, Jerin Jacob wrote:
> > > > As previously discussed in RFC v1 [1], RFC v2 [2], with changes
> > > > described in [3] (also pasted below), here is the first non-draft series
> > > > for this new API.
> > > > 
> > > > [1] http://dpdk.org/ml/archives/dev/2016-August/045181.html
> > > > [2] http://dpdk.org/ml/archives/dev/2016-October/048592.html
> > > > [3] http://dpdk.org/ml/archives/dev/2016-October/048196.html
> > > > 
> > > > v2..v3:
> > > > 
> > > > - This patch set is check-patch clean with an exception that
> > > > 03/06 has one WARNING:MACRO_WITH_FLOW_CONTROL
> > > > - Looking forward to getting additional maintainers for libeventdev
> > > > 
> > > > TODO:
> > > > 1) Create user guide
> > > > 
> > > > Jerin Jacob (6):
> > > >   eventdev: introduce event driven programming model
> > > >   eventdev: define southbound driver interface
> > > >   eventdev: implement the northbound APIs
> > > >   eventdev: implement PMD registration functions
> > > >   event/skeleton: add skeleton eventdev driver
> > > >   app/test: unit test case for eventdev APIs
> > > > 
> > > Hi Jerin,
> > 
> > Hi Bruce,
> > 
> > > 
> > > other than the couple of comments I've made in replies to the individual
> > > patches, this looks pretty good to me. Only additional comment I have is
> > 
> > Thanks
> > 
> > > that some of the macro names are a little long, and maybe we can shorten
> > > them  For example, you've added "_FLAG_" into the config flag macros,
> > > and I'm not sure that is necessary. Similarly, I think we can drop
> > > "_DEV_" from the PRIORITY names to shorten them.
> > 
> > OK. I will remove the explicit _FLAG_  to shorten macro name.
> > The _DEV_ in PRIORITY is not that long. So I would like to keep it for
> > consistency and to denote it across priorities in event dev.
> > 
> > > 
> > > Irrespective of these naming suggestions, once the other couple of
> > > comments are taken care of, I think this set is suitable for merging to
> > > the next-event tree.
> > 
> > I will send v4 with fixes and your suggestions. If their is no further
> > comment on that, we will merge to next-event tree
> > 
> I'm not sure a v4 is needed, unless you especially want to do one. 
> Given the scope of the suggested changes I think you can just make
> those changes on apply to the next-event tree.

Applied to dpdk-next-eventdev tree.

Thanks

> 
> /Bruce

^ permalink raw reply

* Re: [PATCH] doc: fix openssl formating text
From: De Lara Guarch, Pablo @ 2017-01-11 15:55 UTC (permalink / raw)
  To: De Lara Guarch, Pablo, Mrzyglod, DanielX T, Mrozowicz, SlawomirX
  Cc: dev@dpdk.org, Mrzyglod, DanielX T
In-Reply-To: <E115CCD9D858EF4F90C690B0DCB4D897476C2337@IRSMSX108.ger.corp.intel.com>



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of De Lara Guarch,
> Pablo
> Sent: Wednesday, January 11, 2017 3:50 PM
> To: Mrzyglod, DanielX T; Mrozowicz, SlawomirX
> Cc: dev@dpdk.org; Mrzyglod, DanielX T
> Subject: Re: [dpdk-dev] [PATCH] doc: fix openssl formating text
> 
> 
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Daniel Mrzyglod
> > Sent: Tuesday, January 10, 2017 2:44 PM
> > To: Mrozowicz, SlawomirX
> > Cc: dev@dpdk.org; Mrzyglod, DanielX T
> > Subject: [dpdk-dev] [PATCH] doc: fix openssl formating text
> >
> > The code section was lacking indentation to be be correctly formatted.
> >
> > Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
> Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>

Applied to dpdk-next-crypto.
Thanks,

Pablo

^ permalink raw reply

* Re: [PATCH 0/5] Assorted fixes for the flow API
From: Thomas Monjalon @ 2017-01-11 15:57 UTC (permalink / raw)
  To: Adrien Mazarguil; +Cc: dev
In-Reply-To: <cover.1484046037.git.adrien.mazarguil@6wind.com>

2017-01-10 14:08, Adrien Mazarguil:
> This series makes a few adjustments to the flow API (rte_flow) based on
> issues encountered by preliminary PMD implementations and addresses bugs
> reported by Coverity in the testpmd flow command.
> 
> Adrien Mazarguil (5):
>   app/testpmd: fix array bounds checks
>   ethdev: modify flow API's error setting function
>   ethdev: clarify MARK and FLAG actions in flow API
>   ethdev: clarify RSS action in flow API
>   ethdev: define default item masks in flow API

Applied, thanks

^ permalink raw reply

* [PATCH v6 0/4] Expanded statistics reporting
From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon
In-Reply-To: <1479456006-10891-1-git-send-email-remy.horton@intel.com>

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

* [PATCH v6 1/4] lib: add information metrics library
From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon
In-Reply-To: <1484150594-3758-1-git-send-email-remy.horton@intel.com>

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

* [PATCH v6 2/4] lib: add bitrate statistics library
From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon
In-Reply-To: <1484150594-3758-1-git-send-email-remy.horton@intel.com>

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

* [PATCH v6 3/4] app/test-pmd: add support for bitrate statistics
From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon
In-Reply-To: <1484150594-3758-1-git-send-email-remy.horton@intel.com>

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

* [PATCH v6 4/4] latencystats: added new library for latency stats
From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw)
  To: dev; +Cc: Thomas Monjalon, Reshma Pattan
In-Reply-To: <1484150594-3758-1-git-send-email-remy.horton@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.

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

* Re: [PATCH] i40e: improve message grepability
From: Ferruh Yigit @ 2017-01-11 16:05 UTC (permalink / raw)
  To: Michał Mirosław, dev
In-Reply-To: <1c4d6b329cb00fbed3d443800ed7eeb5b4bf57c7.1484127857.git.mirq-linux@rere.qmqm.pl>

On 1/11/2017 9:49 AM, Michał Mirosław wrote:
> Join message lines for easier grepping.
> PRIxXX are left glued to strings as they are in other parts of the file.

I can't apply this cleanly, would you mind rebasing on top of latest
next-net?

Also there is a minor nit below.

Thanks,
ferruh

> 
> Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
> 
> ---
>  drivers/net/i40e/i40e_ethdev.c | 308 +++++++++++++++++++++--------------------
>  1 file changed, 160 insertions(+), 148 deletions(-)
> 
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index db2aebdb..00c15f87 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -764,8 +764,8 @@ i40e_add_tx_flow_control_drop_filter(struct i40e_pf *pf)
>  				pf->main_vsi_seid, 0,
>  				TRUE, NULL, NULL);
>  	if (ret)
> -		PMD_INIT_LOG(ERR, "Failed to add filter to drop flow control "
> -				  " frames from VSIs.");
> +		PMD_INIT_LOG(ERR,
> +			     "Failed to add filter to drop flow control frames from VSIs.");

Most messages aligned to "(", but single tab can give more room for the
msg (4 more chars J), and tab is preferred one according DPDK coding
convention.

I don't have a strong opinion, what do you think?

<...>
> @@ -1788,8 +1789,8 @@ i40e_dev_start(struct rte_eth_dev *dev)
>  		i40e_pf_enable_irq0(hw);
>  
>  		if (dev->data->dev_conf.intr_conf.lsc != 0)
> -			PMD_INIT_LOG(INFO, "lsc won't enable because of"
> -				     " no intr multiplex\n");
> +			PMD_INIT_LOG(INFO,
> +				"lsc won't enable because of no intr multiplex\n");

Like this one is using tab.

<...>

^ permalink raw reply

* Re: [PATCH 12/13] i40e: return -errno when intr setup fails
From: Ferruh Yigit @ 2017-01-11 16:09 UTC (permalink / raw)
  To: Wu, Jingjing, Michal Miroslaw, dev@dpdk.org
In-Reply-To: <9BB6961774997848B5B42BEC655768F810CC016F@SHSMSX103.ccr.corp.intel.com>

On 12/28/2016 3:47 AM, Wu, Jingjing wrote:
> 
> 
>> -----Original Message-----
>> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Michal Miroslaw
>> Sent: Tuesday, December 13, 2016 9:08 AM
>> To: dev@dpdk.org
>> Subject: [dpdk-dev] [PATCH 12/13] i40e: return -errno when intr setup fails
>>
>> Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>

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

Applied to dpdk-next-net/master, thanks.

^ permalink raw reply

* Re: [PATCH v6 2/4] lib: add bitrate statistics library
From: Stephen Hemminger @ 2017-01-11 16:15 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev, Thomas Monjalon
In-Reply-To: <1484150594-3758-3-git-send-email-remy.horton@intel.com>

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

* Re: [PATCH] kni: use bulk functions to allocate and free mbufs
From: Stephen Hemminger @ 2017-01-11 16:17 UTC (permalink / raw)
  To: Sergey Vyazmitinov; +Cc: olivier.matz, ferruh.yigit, dev
In-Reply-To: <1483048216-2936-1-git-send-email-s.vyazmitinov@brain4net.com>

On Fri, 30 Dec 2016 04:50:16 +0700
Sergey Vyazmitinov <s.vyazmitinov@brain4net.com> wrote:

>  /**
> + * Free n packets mbuf back into its original mempool.
> + *
> + * Free each mbuf, and all its segments in case of chained buffers. Each
> + * segment is added back into its original mempool.
> + *
> + * @param mp
> + *   The packets mempool.
> + * @param mbufs
> + *   The packets mbufs array to be freed.
> + * @param n
> + *   Number of packets.
> + */
> +static inline void rte_pktmbuf_free_bulk(struct rte_mempool *mp,
> +		struct rte_mbuf **mbufs, unsigned n)
> +{
> +	struct rte_mbuf *mbuf, *m_next;
> +	unsigned i;
> +	for (i = 0; i < n; ++i) {
> +		mbuf = mbufs[i];
> +		__rte_mbuf_sanity_check(mbuf, 1);
> +
> +		mbuf = mbuf->next;
> +		while (mbuf != NULL) {
> +			m_next = mbuf->next;
> +			rte_pktmbuf_free_seg(mbuf);
> +			mbuf = m_next;
> +		}
> +	}
> +	rte_mempool_put_bulk(mp, (void * const *)mbufs, n);
> +}

The mbufs may come from different pools. You need to handle that.

^ permalink raw reply

* Re: [dpdk-stable] [PATCH] app/testpmd: fix ixgbe private API calling
From: Ferruh Yigit @ 2017-01-11 16:19 UTC (permalink / raw)
  To: Iremonger, Bernard, Lu, Wenzhuo, dev@dpdk.org
  Cc: Wu, Jingjing, stable@dpdk.org
In-Reply-To: <8CEF83825BEC744B83065625E567D7C224D1CD35@IRSMSX108.ger.corp.intel.com>

On 1/11/2017 3:47 PM, Iremonger, Bernard wrote:
> Hi Ferruh,
> 
>> -----Original Message-----
>> From: Yigit, Ferruh
>> Sent: Wednesday, January 11, 2017 3:27 PM
>> To: Iremonger, Bernard <bernard.iremonger@intel.com>; Lu, Wenzhuo
>> <wenzhuo.lu@intel.com>; dev@dpdk.org
>> Cc: Wu, Jingjing <jingjing.wu@intel.com>; stable@dpdk.org
>> Subject: Re: [dpdk-stable] [dpdk-dev] [PATCH] app/testpmd: fix ixgbe
>> private API calling
>>
>> On 1/11/2017 3:20 PM, Iremonger, Bernard wrote:
>>> Hi Wenzhuo,
>>>
>>> <snip>
>>>>> Subject: [dpdk-dev] [PATCH] app/testpmd: fix ixgbe private API
>>>>> calling
>>>>>
>>>>> Some ixgbe private APIs are added to expose ixgbe specific functions.
>>>>> When they're used by testpmd, there's no check for if the NICs are
>> ixgbe.
>>>>> Other NICs also have chance to  call these APIs.
>>>>> This patch add the check and the feedback print.
>>>>
>>>> I am not sure that testpmd is the right place to do this.
>>>> The rte_pmd_ixgbe_* functions are public API's which can be called by
>>>> other applications.
>>>> The checks should be in the rte_pmd_ixgbe_* API's
>>>
>>> It is useful to handle the return code -ENOTSUP in testpmd.
>>>
>>
>> Makes sense, and I think it is good idea to add them in your patch, since it
>> introduces returning -ENOTSUP, would you mind sending a new version of
>> your patch with this update?
>> So we can drop this patch completely.
>>
>> Thanks,
>> ferruh
>>
> I don't think this patch should be dropped.
> Testpmd is already handling -EINVAL and -ENODEV.
> It makes sense for it to handle -ENOTSUP for the cases in the patch.

This patch adds driver check [1] before ixgbe APIs, since now that check
is done within ixgbe APIs by your patch. Why do we need this patch at all?

[1]
if (strstr(dev_info.driver_name, "ixgbe") != NULL)

> 
> Regards,
> 
> Bernard.
> 

^ permalink raw reply

* Re: [dpdk-stable] [PATCH] app/testpmd: fix ixgbe private API calling
From: Iremonger, Bernard @ 2017-01-11 16:29 UTC (permalink / raw)
  To: Yigit, Ferruh, Lu, Wenzhuo, dev@dpdk.org; +Cc: Wu, Jingjing, stable@dpdk.org
In-Reply-To: <727ff859-107b-74c3-1110-7ed8bdbc70f6@intel.com>

Hi Ferruh,

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Wednesday, January 11, 2017 4:19 PM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>; Lu, Wenzhuo
> <wenzhuo.lu@intel.com>; dev@dpdk.org
> Cc: Wu, Jingjing <jingjing.wu@intel.com>; stable@dpdk.org
> Subject: Re: [dpdk-stable] [dpdk-dev] [PATCH] app/testpmd: fix ixgbe
> private API calling
> 
> On 1/11/2017 3:47 PM, Iremonger, Bernard wrote:
> > Hi Ferruh,
> >
> >> -----Original Message-----
> >> From: Yigit, Ferruh
> >> Sent: Wednesday, January 11, 2017 3:27 PM
> >> To: Iremonger, Bernard <bernard.iremonger@intel.com>; Lu, Wenzhuo
> >> <wenzhuo.lu@intel.com>; dev@dpdk.org
> >> Cc: Wu, Jingjing <jingjing.wu@intel.com>; stable@dpdk.org
> >> Subject: Re: [dpdk-stable] [dpdk-dev] [PATCH] app/testpmd: fix ixgbe
> >> private API calling
> >>
> >> On 1/11/2017 3:20 PM, Iremonger, Bernard wrote:
> >>> Hi Wenzhuo,
> >>>
> >>> <snip>
> >>>>> Subject: [dpdk-dev] [PATCH] app/testpmd: fix ixgbe private API
> >>>>> calling
> >>>>>
> >>>>> Some ixgbe private APIs are added to expose ixgbe specific functions.
> >>>>> When they're used by testpmd, there's no check for if the NICs are
> >> ixgbe.
> >>>>> Other NICs also have chance to  call these APIs.
> >>>>> This patch add the check and the feedback print.
> >>>>
> >>>> I am not sure that testpmd is the right place to do this.
> >>>> The rte_pmd_ixgbe_* functions are public API's which can be called
> >>>> by other applications.
> >>>> The checks should be in the rte_pmd_ixgbe_* API's
> >>>
> >>> It is useful to handle the return code -ENOTSUP in testpmd.
> >>>
> >>
> >> Makes sense, and I think it is good idea to add them in your patch,
> >> since it introduces returning -ENOTSUP, would you mind sending a new
> >> version of your patch with this update?
> >> So we can drop this patch completely.
> >>
> >> Thanks,
> >> ferruh
> >>
> > I don't think this patch should be dropped.
> > Testpmd is already handling -EINVAL and -ENODEV.
> > It makes sense for it to handle -ENOTSUP for the cases in the patch.
> 
> This patch adds driver check [1] before ixgbe APIs, since now that check is
> done within ixgbe APIs by your patch. Why do we need this patch at all?
> 
> [1]
> if (strstr(dev_info.driver_name, "ixgbe") != NULL)
 
I think our lines have got slightly crossed.
This patch is doing two things, the check [1] above which is not needed now (after my ixgbe patch).
Secondly it is handling the ret code of the rte_pmd_ixgbe_* API's, I think this is useful.

Regards,

Bernard.

  

^ permalink raw reply

* Re: [PATCH] kni: use bulk functions to allocate and free mbufs
From: Olivier MATZ @ 2017-01-11 16:38 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Sergey Vyazmitinov, olivier.matz, ferruh.yigit, dev
In-Reply-To: <20170111081759.7b1ee146@xeon-e3>

On Wed, 11 Jan 2017 08:17:59 -0800, Stephen Hemminger
<stephen@networkplumber.org> wrote:
> On Fri, 30 Dec 2016 04:50:16 +0700
> Sergey Vyazmitinov <s.vyazmitinov@brain4net.com> wrote:
> 
> >  /**
> > + * Free n packets mbuf back into its original mempool.
> > + *
> > + * Free each mbuf, and all its segments in case of chained
> > buffers. Each
> > + * segment is added back into its original mempool.
> > + *
> > + * @param mp
> > + *   The packets mempool.
> > + * @param mbufs
> > + *   The packets mbufs array to be freed.
> > + * @param n
> > + *   Number of packets.
> > + */
> > +static inline void rte_pktmbuf_free_bulk(struct rte_mempool *mp,
> > +		struct rte_mbuf **mbufs, unsigned n)
> > +{
> > +	struct rte_mbuf *mbuf, *m_next;
> > +	unsigned i;
> > +	for (i = 0; i < n; ++i) {
> > +		mbuf = mbufs[i];
> > +		__rte_mbuf_sanity_check(mbuf, 1);
> > +
> > +		mbuf = mbuf->next;
> > +		while (mbuf != NULL) {
> > +			m_next = mbuf->next;
> > +			rte_pktmbuf_free_seg(mbuf);
> > +			mbuf = m_next;
> > +		}
> > +	}
> > +	rte_mempool_put_bulk(mp, (void * const *)mbufs, n);
> > +}  
> 
> The mbufs may come from different pools. You need to handle that.

I have an implementation for that in an endless-work-in-progress
patchset:

 /**
+ * Free several mbufs segments.
+ *
+ * This function frees a table of mbufs, ensuring that each mbuf is
+ * returned into its original pool. It is the equivalent of calling
+ * rte_pktmbuf_free_seg() on all mbuf of the table.
+ *
+ * @param mbufs
+ *    Array of mbuf pointers.
+ * @param n
+ *    Array size.
+ */
+static inline void
+rte_pktmbuf_free_seg_bulk(struct rte_mbuf * const *m_tab, unsigned n)
+{
+       struct rte_mbuf *m;
+       struct rte_mbuf * const *start = NULL;
+       unsigned n_free = 0, i;
+       struct rte_mempool *free_pool = NULL;
+
+       for (i = 0; i < n; i++) {
+               m = m_tab[i];
+
+               if (__rte_pktmbuf_prefree_seg(m) == NULL) {
+                       if (n_free != 0)
+                               rte_mempool_put_bulk(free_pool,
+                                       (void * const *)start, n_free);
+
+                       free_pool = NULL;
+                       n_free = 0;
+                       continue;
+               }
+
+               if (unlikely(m->pool != free_pool)) {
+                       if (n_free != 0)
+                               rte_mempool_put_bulk(free_pool,
+                                       (void * const *)start, n_free);
+
+                       free_pool = m->pool;
+                       start = &m_tab[i];
+                       n_free = 1;
+               } else {
+                       n_free++;
+               }
+       }
+
+       if (n_free != 0)
+               rte_mempool_put_bulk(free_pool,
+                       (void * const *)start, n_free);
+}


In the same patch, I also remove the tx_free_bulk_mbuf() functions
that does almost the same job in specific drivers. Unfortunately,
this patch needs to be rebased and better tested, so it's not ready yet.


Regards,
Olivier

^ permalink raw reply

* [PATCH] net/mlx: remove link update lock
From: Olivier Matz @ 2017-01-11 16:44 UTC (permalink / raw)
  To: dev, adrien.mazarguil; +Cc: Matthieu Ternisien d'Ouville

From: Matthieu Ternisien d'Ouville <matthieu.tdo@6wind.com>

Retrieving link status information through the link update callback should
be quick and non-blocking.

Mellanox PMDs retrieve this information through ioctl() calls on the
related kernel netdevice. This appears to take a long time to
complete and may cause significant slowdowns in applications.

While these system calls cannot be accelerated, removing the lock on the
private structure allows applications to perform other control operations
from separate threads in the meantime. This function remains safe without
locking as it does not write the private structure, it is only used to
retrieve the name of the netdevice.

Signed-off-by: Matthieu Ternisien d'Ouville <matthieu.tdo@6wind.com>
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
 drivers/net/mlx4/mlx4.c        | 32 ++++++--------------------------
 drivers/net/mlx5/mlx5.c        |  2 +-
 drivers/net/mlx5/mlx5.h        |  1 -
 drivers/net/mlx5/mlx5_ethdev.c | 30 ++++++------------------------
 4 files changed, 13 insertions(+), 52 deletions(-)

diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index eb06f56..941176c 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -4823,7 +4823,7 @@ mlx4_allmulticast_disable(struct rte_eth_dev *dev)
 }
 
 /**
- * DPDK callback to retrieve physical link information (unlocked version).
+ * DPDK callback to retrieve physical link information.
  *
  * @param dev
  *   Pointer to Ethernet device structure.
@@ -4831,9 +4831,9 @@ mlx4_allmulticast_disable(struct rte_eth_dev *dev)
  *   Wait for request completion (ignored).
  */
 static int
-mlx4_link_update_unlocked(struct rte_eth_dev *dev, int wait_to_complete)
+mlx4_link_update(struct rte_eth_dev *dev, int wait_to_complete)
 {
-	struct priv *priv = mlx4_get_priv(dev);
+	const struct priv *priv = mlx4_get_priv(dev);
 	struct ethtool_cmd edata = {
 		.cmd = ETHTOOL_GSET
 	};
@@ -4841,6 +4841,8 @@ mlx4_link_update_unlocked(struct rte_eth_dev *dev, int wait_to_complete)
 	struct rte_eth_link dev_link;
 	int link_speed = 0;
 
+	/* priv_lock() is not taken to allow concurrent calls. */
+
 	if (priv == NULL)
 		return -EINVAL;
 	(void)wait_to_complete;
@@ -4876,28 +4878,6 @@ mlx4_link_update_unlocked(struct rte_eth_dev *dev, int wait_to_complete)
 }
 
 /**
- * DPDK callback to retrieve physical link information.
- *
- * @param dev
- *   Pointer to Ethernet device structure.
- * @param wait_to_complete
- *   Wait for request completion (ignored).
- */
-static int
-mlx4_link_update(struct rte_eth_dev *dev, int wait_to_complete)
-{
-	struct priv *priv = mlx4_get_priv(dev);
-	int ret;
-
-	if (priv == NULL)
-		return -EINVAL;
-	priv_lock(priv);
-	ret = mlx4_link_update_unlocked(dev, wait_to_complete);
-	priv_unlock(priv);
-	return ret;
-}
-
-/**
  * DPDK callback to change the MTU.
  *
  * Setting the MTU affects hardware MRU (packets larger than the MTU cannot be
@@ -5413,7 +5393,7 @@ priv_dev_link_status_handler(struct priv *priv, struct rte_eth_dev *dev)
 		struct rte_eth_link *link = &dev->data->dev_link;
 
 		priv->pending_alarm = 0;
-		mlx4_link_update_unlocked(dev, 0);
+		mlx4_link_update(dev, 0);
 		if (((link->link_speed == 0) && link->link_status) ||
 		    ((link->link_speed != 0) && !link->link_status)) {
 			/* Inconsistent status, check again later. */
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 6293c1f..d936e72 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -680,7 +680,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 		/* Bring Ethernet device up. */
 		DEBUG("forcing Ethernet interface up");
 		priv_set_flags(priv, ~IFF_UP, IFF_UP);
-		mlx5_link_update_unlocked(priv->dev, 1);
+		mlx5_link_update(priv->dev, 1);
 		continue;
 
 port_error:
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index ee62e04..d39b199 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -194,7 +194,6 @@ int priv_set_flags(struct priv *, unsigned int, unsigned int);
 int mlx5_dev_configure(struct rte_eth_dev *);
 void mlx5_dev_infos_get(struct rte_eth_dev *, struct rte_eth_dev_info *);
 const uint32_t *mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev);
-int mlx5_link_update_unlocked(struct rte_eth_dev *, int);
 int mlx5_link_update(struct rte_eth_dev *, int);
 int mlx5_dev_set_mtu(struct rte_eth_dev *, uint16_t);
 int mlx5_dev_get_flow_ctrl(struct rte_eth_dev *, struct rte_eth_fc_conf *);
diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c
index fbb1b65..a46526e 100644
--- a/drivers/net/mlx5/mlx5_ethdev.c
+++ b/drivers/net/mlx5/mlx5_ethdev.c
@@ -628,7 +628,7 @@ mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 }
 
 /**
- * Retrieve physical link information (unlocked version using legacy ioctl).
+ * DPDK callback to retrieve physical link information.
  *
  * @param dev
  *   Pointer to Ethernet device structure.
@@ -646,6 +646,8 @@ mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev, int wait_to_complete)
 	struct rte_eth_link dev_link;
 	int link_speed = 0;
 
+	/* priv_lock() is not taken to allow concurrent calls. */
+
 	(void)wait_to_complete;
 	if (priv_ifreq(priv, SIOCGIFFLAGS, &ifr)) {
 		WARN("ioctl(SIOCGIFFLAGS) failed: %s", strerror(errno));
@@ -790,7 +792,7 @@ mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev, int wait_to_complete)
 }
 
 /**
- * DPDK callback to retrieve physical link information (unlocked version).
+ * DPDK callback to retrieve physical link information.
  *
  * @param dev
  *   Pointer to Ethernet device structure.
@@ -798,7 +800,7 @@ mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev, int wait_to_complete)
  *   Wait for request completion (ignored).
  */
 int
-mlx5_link_update_unlocked(struct rte_eth_dev *dev, int wait_to_complete)
+mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
 {
 	int ret;
 
@@ -809,26 +811,6 @@ mlx5_link_update_unlocked(struct rte_eth_dev *dev, int wait_to_complete)
 }
 
 /**
- * DPDK callback to retrieve physical link information.
- *
- * @param dev
- *   Pointer to Ethernet device structure.
- * @param wait_to_complete
- *   Wait for request completion (ignored).
- */
-int
-mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
-{
-	struct priv *priv = mlx5_get_priv(dev);
-	int ret;
-
-	priv_lock(priv);
-	ret = mlx5_link_update_unlocked(dev, wait_to_complete);
-	priv_unlock(priv);
-	return ret;
-}
-
-/**
  * DPDK callback to change the MTU.
  *
  * Setting the MTU affects hardware MRU (packets larger than the MTU cannot be
@@ -1164,7 +1146,7 @@ priv_dev_link_status_handler(struct priv *priv, struct rte_eth_dev *dev)
 		struct rte_eth_link *link = &dev->data->dev_link;
 
 		priv->pending_alarm = 0;
-		mlx5_link_update_unlocked(dev, 0);
+		mlx5_link_update(dev, 0);
 		if (((link->link_speed == 0) && link->link_status) ||
 		    ((link->link_speed != 0) && !link->link_status)) {
 			/* Inconsistent status, check again later. */
-- 
2.8.1

^ permalink raw reply related

* [PATCH] net/mlx: fix IPv4 and IPv6 packet type
From: Olivier Matz @ 2017-01-11 16:44 UTC (permalink / raw)
  To: dev, adrien.mazarguil
  Cc: Matthieu Ternisien d'Ouville, stable, Samuel Gauthier

From: Matthieu Ternisien d'Ouville <matthieu.tdo@6wind.com>

Mellanox PMDs do not differentiate IP header with or without options, so
the advertised packet type for an IPv4 should not be RTE_PTYPE_L3_IPV4,
which explicitly means "does not contain any header option".

Change the driver to set
RTE_PTYPE(_INNER)_L3_IPV4_EXT_UNKNOWN or
RTE_PTYPE(_INNER)_L3_IPV6_EXT_UNKNOWN flags for all IPv4/IPv6 packets
received.

Fixes: 429df3803a16 ("mlx4: replace some offload flags with packet type")
Fixes: 67fa62bc672d ("mlx5: support checksum offload")

CC: stable@dpdk.org
Signed-off-by: Samuel Gauthier <samuel.gauthier@6wind.com>
Signed-off-by: Matthieu Ternisien d'Ouville <matthieu.tdo@6wind.com>
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
 drivers/net/mlx4/mlx4.c      | 18 ++++++++++++------
 drivers/net/mlx5/mlx5_rxtx.c | 12 ++++++------
 2 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 941176c..79efaaa 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -2961,19 +2961,25 @@ rxq_cq_to_pkt_type(uint32_t flags)
 	if (flags & IBV_EXP_CQ_RX_TUNNEL_PACKET)
 		pkt_type =
 			TRANSPOSE(flags,
-			          IBV_EXP_CQ_RX_OUTER_IPV4_PACKET, RTE_PTYPE_L3_IPV4) |
+				  IBV_EXP_CQ_RX_OUTER_IPV4_PACKET,
+				  RTE_PTYPE_L3_IPV4_EXT_UNKNOWN) |
 			TRANSPOSE(flags,
-			          IBV_EXP_CQ_RX_OUTER_IPV6_PACKET, RTE_PTYPE_L3_IPV6) |
+				  IBV_EXP_CQ_RX_OUTER_IPV6_PACKET,
+				  RTE_PTYPE_L3_IPV6_EXT_UNKNOWN) |
 			TRANSPOSE(flags,
-			          IBV_EXP_CQ_RX_IPV4_PACKET, RTE_PTYPE_INNER_L3_IPV4) |
+				  IBV_EXP_CQ_RX_IPV4_PACKET,
+				  RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN) |
 			TRANSPOSE(flags,
-			          IBV_EXP_CQ_RX_IPV6_PACKET, RTE_PTYPE_INNER_L3_IPV6);
+				  IBV_EXP_CQ_RX_IPV6_PACKET,
+				  RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN);
 	else
 		pkt_type =
 			TRANSPOSE(flags,
-			          IBV_EXP_CQ_RX_IPV4_PACKET, RTE_PTYPE_L3_IPV4) |
+				  IBV_EXP_CQ_RX_IPV4_PACKET,
+				  RTE_PTYPE_L3_IPV4_EXT_UNKNOWN) |
 			TRANSPOSE(flags,
-			          IBV_EXP_CQ_RX_IPV6_PACKET, RTE_PTYPE_L3_IPV6);
+				  IBV_EXP_CQ_RX_IPV6_PACKET,
+				  RTE_PTYPE_L3_IPV6_EXT_UNKNOWN);
 	return pkt_type;
 }
 
diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index e0ee2f2..9415720 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -1112,24 +1112,24 @@ rxq_cq_to_pkt_type(volatile struct mlx5_cqe *cqe)
 		pkt_type =
 			TRANSPOSE(flags,
 				  MLX5_CQE_RX_OUTER_IPV4_PACKET,
-				  RTE_PTYPE_L3_IPV4) |
+				  RTE_PTYPE_L3_IPV4_EXT_UNKNOWN) |
 			TRANSPOSE(flags,
 				  MLX5_CQE_RX_OUTER_IPV6_PACKET,
-				  RTE_PTYPE_L3_IPV6) |
+				  RTE_PTYPE_L3_IPV6_EXT_UNKNOWN) |
 			TRANSPOSE(flags,
 				  MLX5_CQE_RX_IPV4_PACKET,
-				  RTE_PTYPE_INNER_L3_IPV4) |
+				  RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN) |
 			TRANSPOSE(flags,
 				  MLX5_CQE_RX_IPV6_PACKET,
-				  RTE_PTYPE_INNER_L3_IPV6);
+				  RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN);
 	else
 		pkt_type =
 			TRANSPOSE(flags,
 				  MLX5_CQE_L3_HDR_TYPE_IPV6,
-				  RTE_PTYPE_L3_IPV6) |
+				  RTE_PTYPE_L3_IPV6_EXT_UNKNOWN) |
 			TRANSPOSE(flags,
 				  MLX5_CQE_L3_HDR_TYPE_IPV4,
-				  RTE_PTYPE_L3_IPV4);
+				  RTE_PTYPE_L3_IPV4_EXT_UNKNOWN);
 	return pkt_type;
 }
 
-- 
2.8.1

^ permalink raw reply related

* [PATCH] net/ixgbevf: reset hardware when stopping port
From: Olivier Matz @ 2017-01-11 16:52 UTC (permalink / raw)
  To: dev, helin.zhang, konstantin.ananyev; +Cc: Guo Fengtian, stable, David Marchand

From: Guo Fengtian <fengtian.guo@6wind.com>

When PF triggers a reset, VF port must acknowledge it by calling
ixgbe_reset_hw().

Before this patch, the port link status, speed and duplex are invalid
(all set to 0).

The patch move the call to ixgbe_reset_hw() from ixgbevf_dev_close() to
ixgbevf_dev_stop(), so that after a port restart on the VM, the link
status is properly marked down, with correct speed and duplex.

Fixes: f0160874c041 ("ixgbe: various updates")

CC: stable@dpdk.org
Signed-off-by: Guo Fengtian <fengtian.guo@6wind.com>
Signed-off-by: David Marchand <david.marchand@6wind.com>
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---

Hi,

The use case for this problem was described some time ago, see:
http://dpdk.org/ml/archives/dev/2015-December/030067.html

It is also part of 2.2 release note:
http://dpdk.org/browse/dpdk/tree/doc/guides/rel_notes/release_2_2.rst#n471

Regards,
Olivier


 drivers/net/ixgbe/ixgbe_ethdev.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index b7ddd4f..2d8641a 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4268,6 +4268,7 @@ ixgbevf_dev_stop(struct rte_eth_dev *dev)
 	PMD_INIT_FUNC_TRACE();
 
 	ixgbevf_intr_disable(hw);
+	ixgbe_reset_hw(hw);
 
 	hw->adapter_stopped = 1;
 	ixgbe_stop_adapter(hw);
@@ -4294,12 +4295,8 @@ ixgbevf_dev_stop(struct rte_eth_dev *dev)
 static void
 ixgbevf_dev_close(struct rte_eth_dev *dev)
 {
-	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
 	PMD_INIT_FUNC_TRACE();
 
-	ixgbe_reset_hw(hw);
-
 	ixgbevf_dev_stop(dev);
 
 	ixgbe_dev_free_queues(dev);
-- 
2.8.1

^ permalink raw reply related

* Re: [PATCH] net/mlx5: support extended statistics
From: Adrien Mazarguil @ 2017-01-11 16:54 UTC (permalink / raw)
  To: Shahaf Shuler; +Cc: dev, Elad Persiko, Hanoch Haim
In-Reply-To: <1484124942-26279-1-git-send-email-shahafs@mellanox.com>

Hi Shahaf,

Thanks, I have a few comments, most of them relatively minor. Please see
below.

On Wed, Jan 11, 2017 at 10:55:42AM +0200, Shahaf Shuler wrote:
> Implement xstats_*() DPDK callbacks
> 
> Signed-off-by: Shahaf Shuler <shahafs@mellanox.com>
> Signed-off-by: Elad Persiko <eladpe@mellanox.com>
> Signed-off-by: Hanoch Haim <hhaim@cisco.com>
> ---
>  drivers/net/mlx5/mlx5.c         |   3 +
>  drivers/net/mlx5/mlx5.h         |  12 ++
>  drivers/net/mlx5/mlx5_defs.h    |   3 +
>  drivers/net/mlx5/mlx5_stats.c   | 342 ++++++++++++++++++++++++++++++++++++++++
>  drivers/net/mlx5/mlx5_trigger.c |   1 +
>  5 files changed, 361 insertions(+)
> 
> diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
> index 6293c1f..3359d3c 100644
> --- a/drivers/net/mlx5/mlx5.c
> +++ b/drivers/net/mlx5/mlx5.c
> @@ -199,6 +199,9 @@
>  	.link_update = mlx5_link_update,
>  	.stats_get = mlx5_stats_get,
>  	.stats_reset = mlx5_stats_reset,
> +	.xstats_get = mlx5_xstats_get,
> +	.xstats_reset = mlx5_xstats_reset,
> +	.xstats_get_names = mlx5_xstats_get_names,
>  	.dev_infos_get = mlx5_dev_infos_get,
>  	.dev_supported_ptypes_get = mlx5_dev_supported_ptypes_get,
>  	.vlan_filter_set = mlx5_vlan_filter_set,
> diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
> index ee62e04..034a05e 100644
> --- a/drivers/net/mlx5/mlx5.h
> +++ b/drivers/net/mlx5/mlx5.h
> @@ -89,6 +89,11 @@ enum {
>  	PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF = 0x101a,
>  };
>  
> +struct mlx5_xstats_ctrl {
> +	uint64_t shadow[MLX5_MAX_XSTATS];
> +	uint16_t stats_n; /* Number of device stats. */
> +};
> +
>  struct priv {
>  	struct rte_eth_dev *dev; /* Ethernet device. */
>  	struct ibv_context *ctx; /* Verbs context. */
> @@ -142,6 +147,7 @@ struct priv {
>  	struct fdir_queue *fdir_drop_queue; /* Flow director drop queue. */
>  	LIST_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */
>  	uint32_t link_speed_capa; /* Link speed capabilities. */
> +	struct mlx5_xstats_ctrl xstats_ctrl; /* Extended stats control. */
>  	rte_spinlock_t lock; /* Lock for control functions. */
>  };
>  
> @@ -250,8 +256,14 @@ int mlx5_dev_rss_reta_update(struct rte_eth_dev *,
>  
>  /* mlx5_stats.c */
>  
> +void priv_xstats_init(struct priv *);
>  void mlx5_stats_get(struct rte_eth_dev *, struct rte_eth_stats *);
>  void mlx5_stats_reset(struct rte_eth_dev *);
> +int mlx5_xstats_get(struct rte_eth_dev *,
> +		    struct rte_eth_xstat *, unsigned int);
> +void mlx5_xstats_reset(struct rte_eth_dev *);
> +int mlx5_xstats_get_names(struct rte_eth_dev *,
> +			  struct rte_eth_xstat_name *, unsigned int);
>  
>  /* mlx5_vlan.c */
>  
> diff --git a/drivers/net/mlx5/mlx5_defs.h b/drivers/net/mlx5/mlx5_defs.h
> index b32816e..beabb70 100644
> --- a/drivers/net/mlx5/mlx5_defs.h
> +++ b/drivers/net/mlx5/mlx5_defs.h
> @@ -79,4 +79,7 @@
>  /* Alarm timeout. */
>  #define MLX5_ALARM_TIMEOUT_US 100000
>  
> +/* Maximum number of extended statistics counters. */
> +#define MLX5_MAX_XSTATS 32
> +
>  #endif /* RTE_PMD_MLX5_DEFS_H_ */
> diff --git a/drivers/net/mlx5/mlx5_stats.c b/drivers/net/mlx5/mlx5_stats.c
> index f2b5781..08a7656 100644
> --- a/drivers/net/mlx5/mlx5_stats.c
> +++ b/drivers/net/mlx5/mlx5_stats.c
> @@ -31,11 +31,16 @@
>   *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>   */
>  
> +#include <linux/sockios.h>
> +#include <linux/ethtool.h>
> +
>  /* DPDK headers don't like -pedantic. */
>  #ifdef PEDANTIC
>  #pragma GCC diagnostic ignored "-Wpedantic"
>  #endif
>  #include <rte_ethdev.h>
> +#include <rte_common.h>
> +#include <rte_malloc.h>
>  #ifdef PEDANTIC
>  #pragma GCC diagnostic error "-Wpedantic"
>  #endif
> @@ -44,6 +49,269 @@
>  #include "mlx5_rxtx.h"
>  #include "mlx5_defs.h"
>  
> +struct mlx5_counter_ctrl {
> +	/* Name of the counter for dpdk user. */

"for dpdk user" is redundant given the purpose of this API.

> +	char dpdk_name[RTE_ETH_XSTATS_NAME_SIZE];
> +	/* Name of the counter on the device table. */
> +	char ctr_name[RTE_ETH_XSTATS_NAME_SIZE];
> +	/* Index in the device counters table. */
> +	uint16_t dev_table_idx;
> +};
> +
> +static struct mlx5_counter_ctrl mlx5_counters_init[] = {
> +	{
> +		.dpdk_name = "rx_port_unicast_bytes",
> +		.ctr_name = "rx_vport_unicast_bytes",
> +		.dev_table_idx = 0

Please add comma after ".dev_table_idx = 0" (same comment applies to the
following definitions). Note you may leave it out entirely since unspecified
fields are automatically initialized to zero.

> +	},
> +	{
> +		.dpdk_name = "rx_port_multicast_bytes",
> +		.ctr_name = "rx_vport_multicast_bytes",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "rx_port_broadcast_bytes",
> +		.ctr_name = "rx_vport_broadcast_bytes",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "rx_port_unicast_packets",
> +		.ctr_name = "rx_vport_unicast_packets",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "rx_port_multicast_packets",
> +		.ctr_name = "rx_vport_multicast_packets",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "rx_port_broadcast_packets",
> +		.ctr_name = "rx_vport_broadcast_packets",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "tx_port_unicast_bytes",
> +		.ctr_name = "tx_vport_unicast_bytes",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "tx_port_multicast_bytes",
> +		.ctr_name = "tx_vport_multicast_bytes",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "tx_port_broadcast_bytes",
> +		.ctr_name = "tx_vport_broadcast_bytes",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "tx_port_unicast_packets",
> +		.ctr_name = "tx_vport_unicast_packets",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "tx_port_multicast_packets",
> +		.ctr_name = "tx_vport_multicast_packets",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "tx_port_broadcast_packets",
> +		.ctr_name = "tx_vport_broadcast_packets",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "rx_wqe_err",
> +		.ctr_name = "rx_wqe_err",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "rx_crc_errors_phy",
> +		.ctr_name = "rx_crc_errors_phy",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "rx_in_range_len_errors_phy",
> +		.ctr_name = "rx_in_range_len_errors_phy",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "rx_symbol_err_phy",
> +		.ctr_name = "rx_symbol_err_phy",
> +		.dev_table_idx = 0
> +	},
> +	{
> +		.dpdk_name = "tx_errors_phy",
> +		.ctr_name = "tx_errors_phy",
> +		.dev_table_idx = 0
> +	},
> +};
> +
> +const unsigned int xstats_n = RTE_DIM(mlx5_counters_init);

Considering this global depends on mlx5_counters_init[] and is only used in
this file, it should be static.

> +
> +/**
> + * Read device counters table.
> + *
> + * @param priv
> + *   Pointer to private structure.
> + * @param[out] stats
> + *   Counters table output buffer.
> + *
> + * @return
> + *   0 on success and stats is filled, negative on error.
> + */
> +static int
> +priv_read_dev_counters(struct priv *priv, uint64_t *stats)
> +{
> +	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
> +	unsigned int i;
> +	struct ifreq ifr;
> +	unsigned int stats_sz = (xstats_ctrl->stats_n * sizeof(uint64_t)) +
> +				 sizeof(struct ethtool_stats);
> +	struct ethtool_stats et_stats[(stats_sz + (
> +				      sizeof(struct ethtool_stats) - 1)) /
> +				      sizeof(struct ethtool_stats)];
> +
> +	et_stats->cmd = ETHTOOL_GSTATS;
> +	et_stats->n_stats = xstats_ctrl->stats_n;
> +	ifr.ifr_data = (caddr_t)et_stats;
> +	if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) {
> +		WARN("unable to get statistic values");
> +		return -1;
> +	}
> +	for (i = 0; (i != xstats_n) ; ++i)
> +		stats[i] = (uint64_t)
> +			   et_stats->data[mlx5_counters_init[i].dev_table_idx];
> +	return 0;
> +}
> +
> +/**
> + * Init the strcutures to read device counters.

Typo, "strcutures".

> + *
> + * @param priv
> + *   Pointer to private structure.
> + */
> +void
> +priv_xstats_init(struct priv *priv)
> +{
> +	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
> +	unsigned int i;
> +	unsigned int j;
> +	char ifname[IF_NAMESIZE];
> +	struct ifreq ifr;
> +	struct ethtool_drvinfo drvinfo;
> +	struct ethtool_gstrings *strings = NULL;
> +	unsigned int dev_stats_n;
> +	unsigned int str_sz;
> +
> +	if (priv_get_ifname(priv, &ifname)) {
> +		WARN("unable to get interface name");
> +		return;
> +	}
> +	/* How many statistics are available. */
> +	drvinfo.cmd = ETHTOOL_GDRVINFO;
> +	ifr.ifr_data = (caddr_t)&drvinfo;
> +	if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) {
> +		WARN("unable to get driver info");
> +		return;
> +	}
> +	dev_stats_n = drvinfo.n_stats;
> +	if (dev_stats_n < 1) {
> +		WARN("no extended statistics available");
> +		return;
> +	}
> +	xstats_ctrl->stats_n = dev_stats_n;
> +	/* Allocate memory to grab stat names and values. */
> +	str_sz = dev_stats_n * ETH_GSTRING_LEN;
> +	strings = (struct ethtool_gstrings *)
> +		  rte_malloc("xstats_strings",
> +			     str_sz + sizeof(struct ethtool_gstrings), 0);
> +	if (!strings) {
> +		WARN("unable to allocate memory for xstats");
> +		return;
> +	}
> +	strings->cmd = ETHTOOL_GSTRINGS;
> +	strings->string_set = ETH_SS_STATS;
> +	strings->len = dev_stats_n;
> +	ifr.ifr_data = (caddr_t)strings;
> +	if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) {
> +		WARN("unable to get statistic names");
> +		goto free;
> +	}
> +	for (j = 0; (j != xstats_n); ++j)
> +		mlx5_counters_init[j].dev_table_idx = dev_stats_n;

As a global, mlx5_counters_init[] affects all DPDK ports that use the mlx5
PMD simultaneously. Are you sure calling priv_xstats_init() from
mlx5_dev_start() is safe?

I think this global should be const and initialized only once.

> +	for (i = 0; (i != dev_stats_n); ++i) {
> +		const char *curr_string = (const char *)
> +			&strings->data[i * ETH_GSTRING_LEN];
> +
> +		for (j = 0; (j != xstats_n); ++j) {
> +			if (!strcmp(mlx5_counters_init[j].ctr_name,
> +				    curr_string)) {
> +				mlx5_counters_init[j].dev_table_idx = i;

The above comment also applies here. The PMD instance should allocate its
own mapping as a priv field if there is no other choice. You could perhaps
make it part of the mlx5_xstats_ctrl structure.

> +				break;
> +			}
> +		}
> +	}
> +	for (j = 0; (j != xstats_n); ++j) {
> +		if (mlx5_counters_init[j].dev_table_idx >= dev_stats_n) {
> +			WARN("Counters are not recognized");

Displaying the name of the counter that is not recognized could help users
determine what's doing on. Please make sure all info/warning/error messages
are helpful enough, e.g.:

 testpmd> show port xstats 0
 ###### NIC extended statistics for port 0 
 mlx5: Counters are not recognized
 testpmd> # what?

> +			goto free;
> +		}
> +	}
> +	/* Copy to shadow at first time. */
> +	assert(xstats_n <= MLX5_MAX_XSTATS);
> +	priv_read_dev_counters(priv, xstats_ctrl->shadow);
> +free:
> +	rte_free(strings);
> +}
> +
> +/**
> + * Get device extended statistics.
> + *
> + * @param priv
> + *   Pointer to private structure.
> + * @param[out] stats
> + *   Pointer to rte extended stats table.
> + *
> + * @return
> + *   Number of extended stats on success and stats is filled,
> + *   nagative on error.

Typo, "nagative".

> + */
> +static int
> +priv_xstats_get(struct priv *priv, struct rte_eth_xstat *stats)
> +{
> +	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
> +	unsigned int i;
> +	uint64_t counters[xstats_n];
> +
> +	if (priv_read_dev_counters(priv, counters) < 0)
> +		return -1;
> +	for (i = 0; (i != xstats_n) ; ++i) {
> +		stats[i].id = i;
> +		stats[i].value = (uint64_t)
> +				 (counters[i] - xstats_ctrl->shadow[i]);

I understand the purpose of the shadow array in this context, however to me
"shadow" implies some sort of caching is taking place. I think "init" or
"base" (as the base value or something) would make its purpose clearer.

> +	}
> +	return xstats_n;
> +}
> +
> +/**
> + * Reset device extended statistics.
> + *
> + * @param priv
> + *   Pointer to private structure.
> + */
> +static void
> +priv_xstats_reset(struct priv *priv)
> +{
> +	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
> +	unsigned int i;
> +	uint64_t counters[xstats_n];
> +
> +	if (priv_read_dev_counters(priv, counters) < 0)
> +		return;
> +	for (i = 0; (i != xstats_n) ; ++i)
> +		xstats_ctrl->shadow[i] = counters[i];
> +}
> +
>  /**
>   * DPDK callback to get device statistics.
>   *
> @@ -142,3 +410,77 @@
>  #endif
>  	priv_unlock(priv);
>  }
> +
> +/**
> + * DPDK callback to get extended device statistics.
> + *
> + * @param dev
> + *   Pointer to Ethernet device structure.
> + * @param[out] stats
> + *   Stats table output buffer.
> + * @param n
> + *   The size of the stats table.
> + *
> + * @return
> + *   Number of xstats on success, negative on failure.
> + */
> +int
> +mlx5_xstats_get(struct rte_eth_dev *dev,
> +		struct rte_eth_xstat *stats, unsigned int n)
> +{
> +	struct priv *priv = mlx5_get_priv(dev);
> +	int ret = xstats_n;
> +
> +	if (n >= xstats_n && stats) {
> +		priv_lock(priv);
> +		ret = priv_xstats_get(priv, stats);
> +		priv_unlock(priv);
> +	}
> +	return ret;
> +}
> +
> +/**
> + * DPDK callback to clear device extended statistics.
> + *
> + * @param dev
> + *   Pointer to Ethernet device structure.
> + */
> +void
> +mlx5_xstats_reset(struct rte_eth_dev *dev)
> +{
> +	struct priv *priv = mlx5_get_priv(dev);
> +
> +	priv_lock(priv);
> +	priv_xstats_reset(priv);
> +	priv_unlock(priv);
> +}
> +
> +/**
> + * DPDK callback to retrieve names of extended device statistics
> + *
> + * @param dev
> + *   Pointer to Ethernet device structure.
> + * @param[out] xstats_names
> + *   Block of memory to insert names into

Let's call "block of memory" a "buffer"? There is also a missing period at
the end of this sentence. 

> + * @param size
> + *   Number of names.

"num" (or "n" as in the API) would make more sense than "size" here.

> + *
> + * @return
> + *   Number of xstats names.
> + */
> +int
> +mlx5_xstats_get_names(struct rte_eth_dev *dev,
> +		struct rte_eth_xstat_name *xstats_names, unsigned int size)
> +{
> +	struct priv *priv = mlx5_get_priv(dev);
> +	unsigned int i;
> +
> +	if (size >= xstats_n && xstats_names) {
> +		priv_lock(priv);
> +		for (i = 0; (i != xstats_n) ; ++i)
> +			strcpy(xstats_names[i].name,
> +			       mlx5_counters_init[i].dpdk_name);
> +		priv_unlock(priv);
> +	}
> +	return xstats_n;
> +}
> diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c
> index 2399243..30addd2 100644
> --- a/drivers/net/mlx5/mlx5_trigger.c
> +++ b/drivers/net/mlx5/mlx5_trigger.c
> @@ -91,6 +91,7 @@
>  		priv_fdir_enable(priv);
>  	priv_dev_interrupt_handler_install(priv, dev);
>  	err = priv_flow_start(priv);
> +	priv_xstats_init(priv);
>  	priv_unlock(priv);
>  	return -err;
>  }
> -- 
> 1.8.3.1

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply

* Re: [PATCH v6 0/4] Expanded statistics reporting
From: Thomas Monjalon @ 2017-01-11 16:58 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev
In-Reply-To: <1484150594-3758-1-git-send-email-remy.horton@intel.com>

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

* Re: [PATCH] kni: use bulk functions to allocate and free mbufs
From: Ferruh Yigit @ 2017-01-11 17:00 UTC (permalink / raw)
  To: Stephen Hemminger, Sergey Vyazmitinov; +Cc: olivier.matz, dev
In-Reply-To: <20170111081759.7b1ee146@xeon-e3>

Hi Sergey,

On 1/11/2017 4:17 PM, Stephen Hemminger wrote:
> On Fri, 30 Dec 2016 04:50:16 +0700
> Sergey Vyazmitinov <s.vyazmitinov@brain4net.com> wrote:
> 
>>  /**
>> + * Free n packets mbuf back into its original mempool.
>> + *
>> + * Free each mbuf, and all its segments in case of chained buffers. Each
>> + * segment is added back into its original mempool.
>> + *
>> + * @param mp
>> + *   The packets mempool.
>> + * @param mbufs
>> + *   The packets mbufs array to be freed.
>> + * @param n
>> + *   Number of packets.
>> + */
>> +static inline void rte_pktmbuf_free_bulk(struct rte_mempool *mp,
>> +		struct rte_mbuf **mbufs, unsigned n)
>> +{
>> +	struct rte_mbuf *mbuf, *m_next;
>> +	unsigned i;
>> +	for (i = 0; i < n; ++i) {
>> +		mbuf = mbufs[i];
>> +		__rte_mbuf_sanity_check(mbuf, 1);
>> +
>> +		mbuf = mbuf->next;
>> +		while (mbuf != NULL) {
>> +			m_next = mbuf->next;
>> +			rte_pktmbuf_free_seg(mbuf);
>> +			mbuf = m_next;
>> +		}
>> +	}
>> +	rte_mempool_put_bulk(mp, (void * const *)mbufs, n);
>> +}
> 
> The mbufs may come from different pools. You need to handle that.
> 

As Stephen pointed mbufs can be from different mempools. But still can
benefit from bulk allocation part of your patch, would you mind
separating patches for alloc and free?

Thanks,
ferruh

^ permalink raw reply

* [PATCH] net/ixgbevf: fix stats update after a PF reset
From: Olivier Matz @ 2017-01-11 17:04 UTC (permalink / raw)
  To: dev, helin.zhang, konstantin.ananyev; +Cc: Guo Fengtian, stable

From: Guo Fengtian <fengtian.guo@6wind.com>

When PF is set down, in VF, the value of stats register is zero.
So only increase stats when it's non zero.

Fixes: af75078fece3 ("first public release")

CC: stable@dpdk.org
Signed-off-by: Guo Fengtian <fengtian.guo@6wind.com>
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 2d8641a..455a0c9 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -389,7 +389,8 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
 #define UPDATE_VF_STAT(reg, last, cur)                          \
 {                                                               \
 	uint32_t latest = IXGBE_READ_REG(hw, reg);              \
-	cur += (latest - last) & UINT_MAX;                      \
+	if (latest != 0)					\
+		cur += (latest - last) & UINT_MAX;              \
 	last = latest;                                          \
 }
 
@@ -398,7 +399,8 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
 	u64 new_lsb = IXGBE_READ_REG(hw, lsb);                   \
 	u64 new_msb = IXGBE_READ_REG(hw, msb);                   \
 	u64 latest = ((new_msb << 32) | new_lsb);                \
-	cur += (0x1000000000LL + latest - last) & 0xFFFFFFFFFLL; \
+	if (latest != 0)					 \
+		cur += (0x1000000000LL + latest - last) & 0xFFFFFFFFFLL; \
 	last = latest;                                           \
 }
 
-- 
2.8.1

^ permalink raw reply related

* [PATCH] net/virtio: fix advertised Rx offload capabilities
From: Olivier Matz @ 2017-01-11 17:05 UTC (permalink / raw)
  To: dev, yuanhan.liu; +Cc: stable

When the virtio PMD is used on top of a vhost that does not support
offloads, Rx offload capabilities are still advertised by
virtio_dev_info_get(). But if an application tries to start the PMD with
Rx offloads enabled (rxmode.hw_ip_checksum = 1), the initialization of
the device will fail with -ENOTSUP and the following log:

  rx ip checksum not available on this host

This patch fixes the Rx offload capabilities returned by
virtio_dev_info_get() to be consistent with features advertised by the
host.

Fixes: 96cb6711939e ("net/virtio: support Rx checksum offload")
Fixes: 86d59b21468a ("net/virtio: support LRO")

CC: stable@dpdk.org
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
 drivers/net/virtio/virtio_ethdev.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 817fedf..0d7f587 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1629,7 +1629,7 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet
 static void
 virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
-	uint64_t tso_mask;
+	uint64_t tso_mask, host_features;
 	struct virtio_hw *hw = dev->data->dev_private;
 
 	dev_info->pci_dev = hw->dev;
@@ -1643,18 +1643,25 @@ virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	dev_info->default_txconf = (struct rte_eth_txconf) {
 		.txq_flags = ETH_TXQ_FLAGS_NOOFFLOADS
 	};
-	dev_info->rx_offload_capa =
-		DEV_RX_OFFLOAD_TCP_CKSUM |
-		DEV_RX_OFFLOAD_UDP_CKSUM |
-		DEV_RX_OFFLOAD_TCP_LRO;
-	dev_info->tx_offload_capa = 0;
 
+	host_features = hw->vtpci_ops->get_features(hw);
+	dev_info->rx_offload_capa = 0;
+	if (host_features & (1ULL << VIRTIO_NET_F_GUEST_CSUM)) {
+		dev_info->rx_offload_capa |=
+			DEV_RX_OFFLOAD_TCP_CKSUM |
+			DEV_RX_OFFLOAD_UDP_CKSUM;
+	}
+	tso_mask = (1ULL << VIRTIO_NET_F_GUEST_TSO4) |
+		(1ULL << VIRTIO_NET_F_GUEST_TSO6);
+	if ((host_features & tso_mask) == tso_mask)
+		dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_TCP_LRO;
+
+	dev_info->tx_offload_capa = 0;
 	if (hw->guest_features & (1ULL << VIRTIO_NET_F_CSUM)) {
 		dev_info->tx_offload_capa |=
 			DEV_TX_OFFLOAD_UDP_CKSUM |
 			DEV_TX_OFFLOAD_TCP_CKSUM;
 	}
-
 	tso_mask = (1ULL << VIRTIO_NET_F_HOST_TSO4) |
 		(1ULL << VIRTIO_NET_F_HOST_TSO6);
 	if ((hw->guest_features & tso_mask) == tso_mask)
-- 
2.8.1

^ permalink raw reply related

* Re: [dpdk-stable] [PATCH] net/ixgbe: fix API parameter checking
From: Iremonger, Bernard @ 2017-01-11 17:05 UTC (permalink / raw)
  To: Yigit, Ferruh, dev@dpdk.org, Lu, Wenzhuo; +Cc: stable@dpdk.org
In-Reply-To: <daac85e4-5687-920c-2047-5d0467c2723f@intel.com>

Hi Ferruh,

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Wednesday, January 11, 2017 3:15 PM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>; dev@dpdk.org;
> Lu, Wenzhuo <wenzhuo.lu@intel.com>
> Cc: stable@dpdk.org
> Subject: Re: [dpdk-stable] [PATCH] net/ixgbe: fix API parameter checking
> 
> On 1/11/2017 2:25 PM, Bernard Iremonger wrote:
> > Add checks to rte_pmd_ixgbe_* API's to ensure that the port is an
> > ixgbe port.
> >
> > Fixes: 49e248223e9f ("net/ixgbe: add API for VF management")
> >
> > CC: stable@dpdk.org
> > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> > ---
> >  drivers/net/ixgbe/ixgbe_ethdev.c | 71
> > ++++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 69 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
> > b/drivers/net/ixgbe/ixgbe_ethdev.c
> > index b7ddd4f..ca14104 100644
> > --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> > +++ b/drivers/net/ixgbe/ixgbe_ethdev.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
> > @@ -4066,6 +4066,12 @@ rte_pmd_ixgbe_set_vf_mac_addr(uint8_t port,
> uint16_t vf,
> >  	dev = &rte_eth_devices[port];
> >  	rte_eth_dev_info_get(port, &dev_info);
> >
> > +	if (!strstr(dev_info.driver_name, "ixgbe"))
> > +		return -ENOTSUP;
> > +
> > +	if (strstr(dev_info.driver_name, "ixgbe_vf"))
> > +		return -ENOTSUP;
> > +
> 
> This part seems common for all functions, what do you think exporting this
> into a static function?
> 
> Also in the feature if you need to update the method to decide if this port_id
> is supported or not, only that function will be effected.
> 
> <...>
Ok, I will put the checks into a static function and send a v2.

Regards,

Bernard.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox